예제 #1
0
        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;
            }
        }
예제 #2
0
 public void Clear()
 {
     serverHostname = null;
     serverStatus   = ServerQueryStatus.UNKNOWN;
     serverName     = null;
     numPlayers     = 0;
     maxPlayers     = 0;
     serverError    = null;
 }
예제 #3
0
        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;
            }
        }
예제 #4
0
        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
            }));
        }
예제 #5
0
        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();
            }
        }
예제 #6
0
        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! */ }
            }
        }
예제 #8
0
        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();
            }
        }