public void Parse(XElement xml) { serverHostname = xml.Element("server").Element("hostname").Value; switch (xml.Element("server").Attribute("status").Value) { case "UP": serverStatus = ServerQueryStatus.UP; break; case "ERROR": serverStatus = ServerQueryStatus.ERROR; break; case "TIMEOUT": serverStatus = ServerQueryStatus.TIMEOUT; break; } if (serverStatus == ServerQueryStatus.UP) { serverName = xml.Element("server").Element("name").Value; numPlayers = int.Parse(xml.Element("server").Element("numplayers").Value); maxPlayers = int.Parse(xml.Element("server").Element("maxplayers").Value); } else if (serverStatus == ServerQueryStatus.ERROR) { serverError = xml.Element("server").Element("error").Value; } }
public void Clear() { serverHostname = null; serverStatus = ServerQueryStatus.UNKNOWN; serverName = null; numPlayers = 0; maxPlayers = 0; serverError = null; }
public void update() { try { _udp = new UdpClient(); _udp.Client.ReceiveTimeout = 2000; _udp.Client.SendTimeout = 2000; _udp.Connect(serverAddr); int now = Environment.TickCount; _udp.Send(status_packet, status_packet.Length); IPEndPoint serverIn = new IPEndPoint(IPAddress.Any, 0); byte[] data = _udp.Receive(ref serverIn); this.serverPing = Environment.TickCount - now; if (queryStatus != ServerQueryStatus.Failed) { if (!serverIn.Address.Equals(serverAddr.Address)) { this.queryStatus = ServerQueryStatus.Failed; throw new Exception("Got data from wrong host " + serverIn.Address.ToString() + " expected from " + serverAddr.Address.ToString()); } this.parseAndPopulate(data); this.queryStatus = ServerQueryStatus.Successful; } _udp.Close(); } catch (SocketException) { this.queryStatus = ServerQueryStatus.TimedOut; } catch (Exception) { this.queryStatus = ServerQueryStatus.Failed; } }
private async Task <ServerQueryResponse> QueryLegacyServerAsync(string hostname, ushort port) { var sw = Stopwatch.StartNew(); IPEndPoint endPoint = null; try { byte[] buffer = new byte[1024]; using (var client = new TcpClient()) { await client.ConnectAsync(hostname, port); sw.Stop(); endPoint = client.Client.RemoteEndPoint as IPEndPoint; using (var ns = client.GetStream()) { var payload = new byte[] { 0xFE, 0x01 }; await ns.WriteAsync(payload, 0, payload.Length); await ns.ReadAsync(buffer, 0, buffer.Length); } client.Close(); var serverData = Encoding.Unicode.GetString(buffer).Split("\u0000\u0000\u0000".ToCharArray()); if (serverData.Length >= 6) { var status = new ServerQueryStatus() { Delay = sw.ElapsedMilliseconds, Success = true, Query = new ServerQuery() { Version = new API.Services.Version() { Name = serverData[2] }, Players = new Players() { Online = int.Parse(serverData[4]), Max = int.Parse(serverData[5]) }, Description = new Description() { Text = serverData[3] } }, EndPoint = endPoint, Address = hostname, Port = port }; return(new ServerQueryResponse(true, status)); } } } catch (Exception ex) { if (sw.IsRunning) { sw.Stop(); } return(new ServerQueryResponse(false, ex.Message, new ServerQueryStatus() { Delay = sw.ElapsedMilliseconds, Success = false, EndPoint = endPoint, Address = hostname, Port = port })); } if (sw.IsRunning) { sw.Stop(); } return(new ServerQueryResponse(false, "Unknown Error", new ServerQueryStatus() { Delay = sw.ElapsedMilliseconds, Success = false, EndPoint = endPoint, Address = hostname, Port = port })); }
private static async Task QueryJavaServerAsync(string hostname, ushort port, PingServerDelegate pingCallback, ServerStatusDelegate statusCallBack) { IPEndPoint endPoint = null; var sw = Stopwatch.StartNew(); string jsonResponse = null; try { var result = await ResolveHostnameAsync(hostname); if (!result.Success) { statusCallBack?.Invoke(new ServerQueryResponse(false, "multiplayer.status.cannot_resolve", new ServerQueryStatus() { Delay = sw.ElapsedMilliseconds, Success = false, EndPoint = null, Address = hostname, Port = port })); return; } bool waitingOnPing = true; using (TcpClient client = new TcpClient()) { await client.ConnectAsync(result.Result, port); endPoint = client.Client.RemoteEndPoint as IPEndPoint; if (client.Connected) { //conn = new NetConnection(Direction.ClientBound, client.Client); //conn.LogExceptions = false; using (var conn = new NetConnection(Direction.ClientBound, client.Client) { LogExceptions = true }) { long pingId = Rnd.NextUInt(); EventWaitHandle ar = new EventWaitHandle(false, EventResetMode.AutoReset); conn.OnPacketReceived += (sender, args) => { if (args.Packet is ResponsePacket responsePacket) { jsonResponse = responsePacket.ResponseMsg; ar.Set(); } else if (args.Packet is PingPacket pong) { if (pong.Payload == pingId) { waitingOnPing = false; pingCallback?.Invoke(new ServerPingResponse(true, sw.ElapsedMilliseconds)); } else { waitingOnPing = false; pingCallback?.Invoke(new ServerPingResponse(true, sw.ElapsedMilliseconds)); } } }; bool connectionClosed = false; conn.OnConnectionClosed += (sender, args) => { connectionClosed = true; ar.Set(); }; conn.Initialize(); conn.SendPacket(new HandshakePacket() { NextState = ConnectionState.Status, ServerAddress = hostname, ServerPort = port, ProtocolVersion = JavaProtocol.ProtocolVersion }); conn.ConnectionState = ConnectionState.Status; conn.SendPacket(new RequestPacket()); if (await WaitHandleHelpers.FromWaitHandle(ar, TimeSpan.FromMilliseconds(10000)) && !connectionClosed && jsonResponse != null) { long timeElapsed = sw.ElapsedMilliseconds; // Log.Debug($"Server json: " + jsonResponse); var query = ServerQuery.FromJson(jsonResponse); if (pingCallback != null) { conn.SendPacket(new PingPacket() { Payload = pingId, }); sw.Restart(); } var r = new ServerQueryStatus() { Delay = timeElapsed, Success = true, WaitingOnPing = pingCallback != null && !waitingOnPing, EndPoint = endPoint, Address = hostname, Port = port, Query = query }; statusCallBack?.Invoke(new ServerQueryResponse(true, r)); } else { statusCallBack?.Invoke(new ServerQueryResponse(false, "multiplayer.status.cannot_connect", new ServerQueryStatus() { EndPoint = endPoint, Delay = sw.ElapsedMilliseconds, Success = false, /* Motd = motd.MOTD, * ProtocolVersion = motd.ProtocolVersion, * MaxNumberOfPlayers = motd.MaxPlayers, * Version = motd.ClientVersion, * NumberOfPlayers = motd.Players,*/ Address = hostname, Port = port, WaitingOnPing = false })); } } } } } catch (Exception ex) { if (sw.IsRunning) { sw.Stop(); } Log.Error($"Could not get server query result! Exception: {ex.ToString()}"); string msg = ex.Message; if (ex is SocketException) { msg = $"multiplayer.status.cannot_connect"; } statusCallBack?.Invoke(new ServerQueryResponse(false, msg, new ServerQueryStatus() { Delay = sw.ElapsedMilliseconds, Success = false, EndPoint = endPoint, Address = hostname, Port = port })); } finally { //conn?.Stop(); //conn?.Dispose(); //conn?.Dispose(); // client?.Close(); } }
public void update(Object threadContext) { if (threadContext != null) { sqh = (ServerQueryHandler)threadContext; } try { if (threadContext != null) { if (sqh.QueryCancelled) { return; } } _udp = new UdpClient(); _udp.Client.ReceiveTimeout = 2000; _udp.Client.SendTimeout = 2000; _udp.Connect(serverAddr); int now = Environment.TickCount; _udp.Send(status_packet, status_packet.Length); IPEndPoint serverIn = new IPEndPoint(IPAddress.Any, 0); byte[] data = _udp.Receive(ref serverIn); this.serverPing = Environment.TickCount - now; // grab the ping ASAP if (threadContext != null) { if (sqh.QueryCancelled) { this.queryStatus = ServerQueryStatus.Failed; _udp.Close(); ServerUpdated(this); return; } } if (queryStatus != ServerQueryStatus.Failed) { if (!serverIn.Address.Equals(serverAddr.Address)) { this.queryStatus = ServerQueryStatus.Failed; throw new Exception("Got data from wrong host " + serverIn.Address.ToString() + " expected from " + serverAddr.Address.ToString()); } this.parseAndPopulate(data); this.queryStatus = ServerQueryStatus.Successful; } _udp.Close(); } catch (SocketException) { this.queryStatus = ServerQueryStatus.TimedOut; } catch (Exception) { this.queryStatus = ServerQueryStatus.Failed; } finally { try { if (threadContext != null) { sqh.queryFinished(); // tell the handler that we've finished our query } ServerUpdated(this); } catch { /* o noes! */ } } }
public void update(Object threadContext) { if (threadContext != null) sqh = (ServerQueryHandler)threadContext; try { if (threadContext != null) if (sqh.QueryCancelled) return; _udp = new UdpClient(); _udp.Client.ReceiveTimeout = 2000; _udp.Client.SendTimeout = 2000; _udp.Connect(serverAddr); int now = Environment.TickCount; _udp.Send(status_packet, status_packet.Length); IPEndPoint serverIn = new IPEndPoint(IPAddress.Any, 0); byte[] data = _udp.Receive(ref serverIn); this.serverPing = Environment.TickCount - now; // grab the ping ASAP if (threadContext != null) { if (sqh.QueryCancelled) { this.queryStatus = ServerQueryStatus.Failed; _udp.Close(); ServerUpdated(this); return; } } if (queryStatus != ServerQueryStatus.Failed) { if (!serverIn.Address.Equals(serverAddr.Address)) { this.queryStatus = ServerQueryStatus.Failed; throw new Exception("Got data from wrong host " + serverIn.Address.ToString() + " expected from " + serverAddr.Address.ToString()); } this.parseAndPopulate(data); this.queryStatus = ServerQueryStatus.Successful; } _udp.Close(); } catch (SocketException) { this.queryStatus = ServerQueryStatus.TimedOut; } catch (Exception) { this.queryStatus = ServerQueryStatus.Failed; } finally { try { if (threadContext != null) sqh.queryFinished(); // tell the handler that we've finished our query ServerUpdated(this); } catch { /* o noes! */ } } }
private static async Task QueryJavaServerAsync(ServerConnectionDetails connectionDetails, PingServerDelegate pingCallback, ServerStatusDelegate statusCallBack) { CancellationTokenSource cts = new CancellationTokenSource(10000); using TcpClient client = new TcpClient(); IPEndPoint endPoint = null; var sw = Stopwatch.StartNew(); string jsonResponse = null; try { bool waitingOnPing = true; await client.ConnectAsync(connectionDetails.EndPoint.Address, connectionDetails.EndPoint.Port); endPoint = client.Client.RemoteEndPoint as IPEndPoint; if (client.Connected) { //conn = new NetConnection(Direction.ClientBound, client.Client); //conn.LogExceptions = false; using (var conn = new NetConnection(PacketDirection.ClientBound, client.Client) { LogExceptions = true }) { long pingId = Rnd.NextUInt(); long pingResult = 0; EventWaitHandle ar = new EventWaitHandle(false, EventResetMode.AutoReset); conn.OnPacketReceived += (sender, args) => { if (args.Packet is ResponsePacket responsePacket) { jsonResponse = responsePacket.ResponseMsg; if (pingCallback != null) { conn.SendPacket(new PingPacket() { Payload = pingId, }); sw.Restart(); } ar.Set(); } else if (args.Packet is PingPacket pong) { pingResult = sw.ElapsedMilliseconds; if (pong.Payload == pingId) { waitingOnPing = false; pingCallback?.Invoke(new ServerPingResponse(true, sw.ElapsedMilliseconds)); } else { waitingOnPing = false; pingCallback?.Invoke(new ServerPingResponse(true, sw.ElapsedMilliseconds)); } ar.Set(); } }; bool connectionClosed = false; conn.OnConnectionClosed += (sender, args) => { if (!cts.IsCancellationRequested) { cts.Cancel(); } connectionClosed = true; ar.Set(); }; conn.Initialize(); conn.SendPacket(new HandshakePacket() { NextState = ConnectionState.Status, ServerAddress = connectionDetails.Hostname, ServerPort = (ushort)connectionDetails.EndPoint.Port, ProtocolVersion = JavaProtocol.ProtocolVersion }); conn.ConnectionState = ConnectionState.Status; conn.SendPacket(new RequestPacket()); if (await WaitHandleHelpers.FromWaitHandle(ar, TimeSpan.FromMilliseconds(10000), cts.Token) && !connectionClosed && jsonResponse != null) { long timeElapsed = sw.ElapsedMilliseconds; // Log.Debug($"Server json: " + jsonResponse); var query = ServerQuery.FromJson(jsonResponse); if (query.Version.Protocol == JavaProtocol.ProtocolVersion) { query.Version.Compatibility = CompatibilityResult.Compatible; } else if (query.Version.Protocol < JavaProtocol.ProtocolVersion) { query.Version.Compatibility = CompatibilityResult.OutdatedServer; } else if (query.Version.Protocol > JavaProtocol.ProtocolVersion) { query.Version.Compatibility = CompatibilityResult.OutdatedClient; } var r = new ServerQueryStatus() { Delay = timeElapsed, Success = true, WaitingOnPing = pingCallback != null && waitingOnPing, EndPoint = endPoint, Address = connectionDetails.Hostname, Port = (ushort)connectionDetails.EndPoint.Port, Query = query }; statusCallBack?.Invoke(new ServerQueryResponse(true, r)); if (waitingOnPing && pingCallback != null) { await WaitHandleHelpers.FromWaitHandle(ar, TimeSpan.FromSeconds(1000)); } } else { statusCallBack?.Invoke(new ServerQueryResponse(false, "multiplayer.status.cannot_connect", new ServerQueryStatus() { EndPoint = endPoint, Delay = sw.ElapsedMilliseconds, Success = false, /* Motd = motd.MOTD, * ProtocolVersion = motd.ProtocolVersion, * MaxNumberOfPlayers = motd.MaxPlayers, * Version = motd.ClientVersion, * NumberOfPlayers = motd.Players,*/ Address = connectionDetails.Hostname, Port = (ushort)connectionDetails.EndPoint.Port, WaitingOnPing = false })); } } } } catch (Exception ex) { cts.Cancel(); if (sw.IsRunning) { sw.Stop(); } // client?.Dispose(); string msg = ex.Message; if (ex is SocketException) { msg = $"multiplayer.status.cannot_connect"; } else { Log.Error(ex, $"Could not get server query result!"); } statusCallBack?.Invoke(new ServerQueryResponse(false, msg, new ServerQueryStatus() { Delay = sw.ElapsedMilliseconds, Success = false, EndPoint = endPoint, Address = connectionDetails.Hostname, Port = (ushort)connectionDetails.EndPoint.Port })); } finally { //conn?.Stop(); //conn?.Dispose(); //conn?.Dispose(); // client?.Close(); } }