コード例 #1
0
ファイル: Server.cs プロジェクト: Stenudd/coldemoplayer
        private void RefreshThread()
        {
            using (TimedUdpClient client = new TimedUdpClient())
            {
                IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0);

                mainWindowInterface.SetServerProperty(this, "Title", "Connecting to Server");
                mainWindowInterface.SetServerProperty(this, "State", StateEnum.Querying);

                // reset properties
                mainWindowInterface.SetServerProperty(this, "Ping", null);
                mainWindowInterface.SetServerProperty(this, "GameName", null);
                mainWindowInterface.SetServerProperty(this, "Map", null);
                mainWindowInterface.SetServerProperty(this, "NumSpectators", null);
                mainWindowInterface.SetServerProperty(this, "MaxSpectators", null);
                mainWindowInterface.SetServerProperty(this, "PasswordProtected", null);

                try
                {
                    DateTime connectTime = DateTime.Now;

                    // attempt to connect
                    Int32 colonIndex = address.IndexOf(':');
                    // what's the timeout???
                    client.Connect(address.Remove(colonIndex), Convert.ToInt32(address.Substring(colonIndex + 1)));

                    // update title as "connected"
                    mainWindowInterface.SetServerProperty(this, "Title", "Connected");

                    if (abortRefresh)
                    {
                        Common.AbortThread(Thread);
                    }

                    // send A2S_INFO
                    // -1 (int), A2S_INFO, "Source Engine Query" (string)
                    DateTime sendTime = DateTime.Now;
                    client.Send(new Byte[] { 0xFF, 0xFF, 0xFF, 0xFF, A2S_INFO, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x45, 0x6E, 0x67, 0x69, 0x6E, 0x65, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x00 });

                    // receive A2S_INFO reply
                    Byte[] infoReply = client.Receive(ref ipEndPoint);
                    if (infoReply == null)
                    {
                        throw new ApplicationException("Server not responding.");
                    }

                    // calculate ping
                    TimeSpan ping = DateTime.Now - connectTime;
                    mainWindowInterface.SetServerProperty(this, "Ping", ping.Milliseconds);

                    // parse A2S_INFO reply
                    ParseInfoQueryReply(infoReply);

                    if (client.Available > 0) // fuuuuuuckkkk yoooooouuu Vaaaaaaalllvvvveeee
                    {
                        client.Receive(ref ipEndPoint);
                    }

                    // send A2S_SERVERQUERY_GETCHALLENGE
                    // -1 (int), A2S_SERVERQUERY_GETCHALLENGE

                    /*client.Send(new Byte[] { 0xFF, 0xFF, 0xFF, 0xFF, A2S_SERVERQUERY_GETCHALLENGE });
                     *
                     * // receive and parse A2S_SERVERQUERY_GETCHALLENGE reply
                     * Byte[] serverQueryGetChallengeReply = client.Receive(ref ipEndPoint);
                     * if (serverQueryGetChallengeReply == null)
                     * {
                     *  throw new ApplicationException("Server ignored challenge.");
                     * }*/

                    //Int32 challengeNumber = ParseServerQueryGetChallengeReply(serverQueryGetChallengeReply);
                    Int32 challengeNumber = -1;

                    while (true)
                    {
                        if (abortRefresh)
                        {
                            Common.AbortThread(Thread);
                        }

                        // send A2S_PLAYER
                        BitWriter bitWriter = new BitWriter();
                        bitWriter.WriteInt32(-1);
                        bitWriter.WriteByte(A2S_PLAYER);
                        bitWriter.WriteInt32(challengeNumber);
                        client.Send(bitWriter.Data);

                        // receive and parse A2S_PLAYER reply
                        Byte[] playerReply = client.Receive(ref ipEndPoint);
                        if (playerReply == null)
                        {
                            if (challengeNumber != -1)
                            {
                                // oh, it's a sourcetv server and valve are too incompetent to implement s2c_player
                                break;
                            }

                            throw new ApplicationException("Player query failed.");
                        }

                        // check for a challenge number (source servers)
                        BitBuffer bitBuffer = new BitBuffer(playerReply);

                        if (bitBuffer.ReadInt32() != -1)
                        {
                            throw new ApplicationException("Bad A2S_PLAYER reply");
                        }

                        Byte type = bitBuffer.ReadByte();

                        if (type == S2C_CHALLENGE)
                        {
                            challengeNumber = bitBuffer.ReadInt32();
                            continue;
                        }
                        else if (type == S2C_PLAYER)
                        {
                            ParsePlayerQueryReply(bitBuffer);
                        }
                        else
                        {
                            throw new ApplicationException(String.Format("Bad A2S_PLAYER type: {0}", type));
                        }

                        break;
                    }

                    mainWindowInterface.SetServerProperty(this, "State", StateEnum.Succeeded);
                }
                catch (ThreadAbortException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    if (!abortRefresh)
                    {
                        mainWindowInterface.SetServerProperty(this, "Title", ex.Message);
                        mainWindowInterface.SetServerProperty(this, "State", StateEnum.Failed);
                    }
                }
                finally
                {
                    client.Close();
                }
            }
        }