PSO2SERVER/Server/QueryServer.cs

129 lines
4.3 KiB
C#
Raw Normal View History

2024-09-10 00:31:40 +08:00
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
2024-09-10 01:13:20 +08:00
using PSO2SERVER.Models;
using PSO2SERVER.Packets;
2024-09-11 16:33:10 +08:00
using System.Threading.Tasks;
2024-09-10 00:31:40 +08:00
2024-09-10 01:13:20 +08:00
namespace PSO2SERVER
2024-09-10 00:31:40 +08:00
{
public enum QueryMode
{
ShipList,/*12100 - 12900*/
2024-09-11 00:44:21 +08:00
Block
2024-09-10 00:31:40 +08:00
}
public class QueryServer
{
2024-09-11 16:33:10 +08:00
public static List<Task> RunningServers = new List<Task>();
2024-09-10 00:31:40 +08:00
private readonly QueryMode _mode;
private readonly int _port;
2024-09-11 19:17:42 +08:00
public QueryServer(QueryMode mode, string desc, int port)
2024-09-10 00:31:40 +08:00
{
_mode = mode;
_port = port;
2024-09-11 16:33:10 +08:00
var queryTask = Task.Run(() => RunAsync());
RunningServers.Add(queryTask);
2024-09-11 19:17:42 +08:00
Logger.WriteInternal("[QSP] 开始监听" + desc + "端口 " + port);
2024-09-10 00:31:40 +08:00
}
2024-09-11 16:33:10 +08:00
private async Task RunAsync()
2024-09-10 00:31:40 +08:00
{
2024-09-11 16:33:10 +08:00
Func<Socket, Task> connectionHandler;
2024-09-10 00:31:40 +08:00
switch (_mode)
{
2024-09-11 00:44:21 +08:00
case QueryMode.Block:
2024-09-11 16:33:10 +08:00
connectionHandler = DoBlockBalanceAsync;
2024-09-10 00:31:40 +08:00
break;
case QueryMode.ShipList:
2024-09-11 16:33:10 +08:00
connectionHandler = DoShipListAsync;
break;
default:
connectionHandler = DoShipListAsync;
2024-09-10 00:31:40 +08:00
break;
}
var serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
Blocking = true
};
var ep = new IPEndPoint(IPAddress.Any, _port);
serverSocket.Bind(ep); // TODO: Custom bind address.
serverSocket.Listen(5);
2024-09-11 16:33:10 +08:00
2024-09-10 00:31:40 +08:00
while (true)
{
2024-09-11 16:33:10 +08:00
var newConnection = await Task.Factory.FromAsync(serverSocket.BeginAccept, serverSocket.EndAccept, null);
_ = connectionHandler(newConnection); // Fire-and-forget pattern for handling connections
2024-09-10 00:31:40 +08:00
}
}
2024-09-11 16:33:10 +08:00
private async Task DoShipListAsync(Socket socket)
2024-09-10 00:31:40 +08:00
{
var writer = new PacketWriter();
var entries = new List<ShipEntry>();
2024-09-11 19:17:42 +08:00
for (var i = 1; i <= 10; i++)
2024-09-10 00:31:40 +08:00
{
var entry = new ShipEntry
{
order = (ushort)i,
number = (uint)i,
2024-09-11 19:17:42 +08:00
//status = i == 2 ? ShipStatus.Online : ShipStatus.Full, // Maybe move to Config?
status = ShipStatus.Online, // Maybe move to Config?
2024-09-10 00:31:40 +08:00
name = String.Format("Ship{0:0#}", i),
2024-09-10 01:13:20 +08:00
ip = ServerApp.BindAddress.GetAddressBytes()
2024-09-10 00:31:40 +08:00
};
entries.Add(entry);
}
2024-09-11 19:17:42 +08:00
// Assuming header size: 8 bytes + (size of ShipEntry * number of entries) + 12 bytes
int headerSize = 8;
int shipEntrySize = Marshal.SizeOf(typeof(ShipEntry));
int totalSize = headerSize + (shipEntrySize * entries.Count) + 12;
PacketHeader header = new PacketHeader(totalSize, 0x11, 0x3D, 0x04, 0x00);
2024-09-10 00:31:40 +08:00
writer.WriteStruct(header);
writer.WriteMagic((uint)entries.Count, 0xE418, 81);
2024-09-11 19:17:42 +08:00
2024-09-10 00:31:40 +08:00
foreach (var entry in entries)
writer.WriteStruct(entry);
writer.Write((Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
writer.Write(1);
2024-09-11 16:33:10 +08:00
var buffer = writer.ToArray();
2024-09-11 19:17:42 +08:00
2024-09-11 16:33:10 +08:00
await Task.Factory.FromAsync(
(cb, state) => socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, cb, state),
socket.EndSend,
null);
2024-09-10 00:31:40 +08:00
socket.Close();
}
2024-09-11 16:33:10 +08:00
private async Task DoBlockBalanceAsync(Socket socket)
2024-09-10 00:31:40 +08:00
{
var writer = new PacketWriter();
writer.WriteStruct(new PacketHeader(0x90, 0x11, 0x2C, 0x0, 0x0));
writer.Write(new byte[0x68 - 8]);
2024-09-10 01:13:20 +08:00
writer.Write(ServerApp.BindAddress.GetAddressBytes());
2024-09-10 00:31:40 +08:00
writer.Write((UInt16)12205);
writer.Write(new byte[0x90 - 0x6A]);
2024-09-11 16:33:10 +08:00
var buffer = writer.ToArray();
await Task.Factory.FromAsync(
(cb, state) => socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, cb, state),
socket.EndSend,
null);
2024-09-10 00:31:40 +08:00
socket.Close();
}
}
}