コード例 #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();
                }
            }
        }
コード例 #2
0
ファイル: SourceDemo.cs プロジェクト: ripieces/coldemoplayer
        private void CalculateProtocol15Hack(Int32 dataLength)
        {
            /*
             * Valve broke network protocol 15 by changing the protocol without incrementing the protocol number.
             *
             * The change adds an extra bit after each message ID, so the only thing that's guaranteed to read correctly with every protocol 15 demo now if the header.
             *
             * The first message in the first sigon frame is always svc_print or svc_serverinfo, so if either of those are invalid, odds are that the demo uses the changed protocol.
             *
             */

            // read in data block
            Byte[] frameData = parser.Reader.ReadBytes(dataLength);
            BitBuffer bitBuffer = new BitBuffer(frameData);

            // parse messages
            SourceDemoParser.MessageId messageId = (SourceDemoParser.MessageId)bitBuffer.ReadUnsignedBits(5);

            if (messageId == SourceDemoParser.MessageId.SVC_Print)
            {
                String s = bitBuffer.ReadString();

                if (s.Contains("Map") || s.Contains("Build") || s.Contains("Players"))
                {
                    // Looks like a valid svc_print string.
                    return;
                }

                Protocol15Hack = true;
            }
            else if (messageId == SourceDemoParser.MessageId.SVC_ServerInfo)
            {
                UInt32 networkProtocol = bitBuffer.ReadUnsignedBits(16);

                if (networkProtocol != this.networkProtocol)
                {
                    // Should match header, must be invalid.
                    Protocol15Hack = true;
                }
            }
        }
コード例 #3
0
ファイル: Server.cs プロジェクト: Stenudd/coldemoplayer
        /// <summary>
        /// Parses S2C_PLAYER.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="si"></param>
        private void ParsePlayerQueryReply(BitBuffer bitBuffer)
        {
            Int32 nPlayers = bitBuffer.ReadByte();

            for (Int32 i = 0; i < nPlayers; i++)
            {
                bitBuffer.SeekBytes(1); // skip index

                Player player = new Player();
                player.Name = bitBuffer.ReadString();
                player.Score = bitBuffer.ReadInt32();
                Single time = bitBuffer.ReadSingle();
                player.Time = (time == -1 ? "BOT" : Common.DurationString(time));

                mainWindowInterface.AddPlayerToServer(this, player);
            }
        }
コード例 #4
0
ファイル: Server.cs プロジェクト: Stenudd/coldemoplayer
        /// <summary>
        /// Parses S2C_CHALLENGE and returns the challenge number.
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private Int32 ParseServerQueryGetChallengeReply(Byte[] data)
        {
            BitBuffer bitBuffer = new BitBuffer(data);

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

            Byte type = bitBuffer.ReadByte();

            if (type != S2C_CHALLENGE)
            {
                throw new ApplicationException(String.Format("Bad A2S_SERVERQUERY_GETCHALLENGE type: {0}", type));
            }

            return bitBuffer.ReadInt32();
        }
コード例 #5
0
        private void MessageClCorpse()
        {
            Byte length = parser.BitBuffer.ReadByte();
            Int32 messageDataOffset = parser.BitBuffer.CurrentByte;

            if (demo.ConvertNetworkProtocol() && demo.Game != null)
            {
                // Get the message data and create a BitBuffer for it.
                byte[] messageData = parser.BitBuffer.ReadBytes(length);
                BitBuffer messageBitBuffer = new BitBuffer(messageData);

                // Have the game handler convert the message.
                demo.Game.ConvertClCorpseMessageCallback(demo.GameVersion, messageBitBuffer);

                // Remove the old message data and insert the new converted message data.
                parser.Seek(messageDataOffset, SeekOrigin.Begin);
                parser.BitBuffer.RemoveBytes(length);
                parser.BitBuffer.InsertBytes(messageBitBuffer.Data);
            }
            else
            {
                parser.Seek(length);
            }
        }
コード例 #6
0
ファイル: Server.cs プロジェクト: Stenudd/coldemoplayer
        /// <summary>
        /// Parses S2C_INFO.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="si"></param>
        private void ParseInfoQueryReply(Byte[] data)
        {
            BitBuffer bitBuffer = new BitBuffer(data);

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

            // read reply type
            Byte type = bitBuffer.ReadByte();
            Boolean sourceEngine;

            if (type == S2C_INFO_SOURCE)
            {
                sourceEngine = true;
            }
            else if (type == S2C_INFO_GOLDSRC)
            {
                sourceEngine = false;
            }
            else
            {
                throw new ApplicationException(String.Format("Bad A2S_INFO type: {0}", type));
            }

            mainWindowInterface.SetServerProperty(this, "SourceEngine", sourceEngine);

            // read the rest
            if (!sourceEngine)
            {
                bitBuffer.ReadString();
                //si.Address = bitBuffer.ReadString(); // resolved hostname
            }
            else
            {
                bitBuffer.SeekBytes(1); // network version
            }

            mainWindowInterface.SetServerProperty(this, "Title", bitBuffer.ReadString()); // server name
            mainWindowInterface.SetServerProperty(this, "Map", bitBuffer.ReadString()); // map
            String gameFolder = bitBuffer.ReadString();
            mainWindowInterface.SetServerProperty(this, "GameFolder", gameFolder); // game folder
            String gameName = bitBuffer.ReadString(); // game name

            if (sourceEngine)
            {
                bitBuffer.SeekBytes(2); // app id
            }

            mainWindowInterface.SetServerProperty(this, "NumSpectators", bitBuffer.ReadByte()); // num spectators
            mainWindowInterface.SetServerProperty(this, "MaxSpectators", bitBuffer.ReadByte()); // max spectators
            bitBuffer.SeekBytes(1); // goldsrc: network version, source: num bots
            bitBuffer.SeekBytes(1); // dedicated
            bitBuffer.SeekBytes(1); // os
            mainWindowInterface.SetServerProperty(this, "PasswordProtected", (bitBuffer.ReadByte() == 1));

            // determine game name
            Game game = GameManager.Find((sourceEngine ? Game.Engines.Source : Game.Engines.HalfLife), gameFolder);

            if (game == null)
            {
                mainWindowInterface.SetServerProperty(this, "GameName", gameName);
            }
            else
            {
                mainWindowInterface.SetServerProperty(this, "GameName", game.Name);
            }
        }
コード例 #7
0
 private UInt32 ParseUnsignedInt(BitBuffer bitBuffer, Entry e)
 {
     return bitBuffer.ReadUnsignedBits((Int32)e.nBits) / (UInt32)e.Divisor;
 }
コード例 #8
0
        public void ProcessFirstGameDataFrame(ref Byte[] frameData)
        {
            // A svc_director message preceeds svc_spawnbaseline in newer HLTV demos. The director message is used to initialise and reset the HUD. Since old HLTV demos omit this message, it can be added here (and set the perspective to first-person too).
            if (demo.Perspective != Demo.Perspectives.Hltv || haveParsedDirectorMessage)
            {
                return;
            }

            const Byte DRC_CMD_START = 1;
            const Byte DRC_CMD_MODE = 3;
            const Byte OBS_IN_EYE = 4;

            // Create a svc_director message to initialise the HUD.
            BitWriter directorMessage = new BitWriter();
            directorMessage.WriteByte((Byte)HalfLifeDemoParser.MessageId.svc_director);
            directorMessage.WriteByte(1); // length
            directorMessage.WriteByte(DRC_CMD_START);

            // Create a svc_director message to set the perspective to first-person.
            directorMessage.WriteByte((Byte)HalfLifeDemoParser.MessageId.svc_director);
            directorMessage.WriteByte(2); // length
            directorMessage.WriteByte(DRC_CMD_MODE);
            directorMessage.WriteByte(OBS_IN_EYE);

            // Insert the new messages.
            BitBuffer bitBuffer = new BitBuffer(frameData);
            bitBuffer.InsertBytes(directorMessage.Data);

            frameData = bitBuffer.Data;
        }
コード例 #9
0
        private Object ParseEntry(BitBuffer bitBuffer, Entry e)
        {
            Boolean signed = ((e.Flags & EntryFlags.Signed) != 0);

            if ((e.Flags & EntryFlags.Byte) != 0)
            {
                if (signed)
                {
                    return (SByte)ParseInt(bitBuffer, e);
                }
                else
                {
                    return (Byte)ParseUnsignedInt(bitBuffer, e);
                }
            }

            if ((e.Flags & EntryFlags.Short) != 0)
            {
                if (signed)
                {
                    return (Int16)ParseInt(bitBuffer, e);
                }
                else
                {
                    return (UInt16)ParseUnsignedInt(bitBuffer, e);
                }
            }

            if ((e.Flags & EntryFlags.Integer) != 0)
            {
                if (signed)
                {
                    return (Int32)ParseInt(bitBuffer, e);
                }
                else
                {
                    return (UInt32)ParseUnsignedInt(bitBuffer, e);
                }
            }

            if ((e.Flags & EntryFlags.Float) != 0 || (e.Flags & EntryFlags.TimeWindow8) != 0 || (e.Flags & EntryFlags.TimeWindowBig) != 0)
            {
                Boolean negative = false;
                Int32 bitsToRead = (Int32)e.nBits;

                if (signed)
                {
                    negative = bitBuffer.ReadBoolean();
                    bitsToRead--;
                }

                return (Single)bitBuffer.ReadUnsignedBits(bitsToRead) / e.Divisor * (negative ? -1.0f : 1.0f);
            }

            if ((e.Flags & EntryFlags.Angle) != 0)
            {
                return (Single)(bitBuffer.ReadUnsignedBits((Int32)e.nBits) * (360.0f / (Single)(1 << (Int32)e.nBits)));
            }

            if ((e.Flags & EntryFlags.String) != 0)
            {
                return bitBuffer.ReadString();
            }

            throw new ApplicationException(String.Format("Unknown delta entry type {0}.", e.Flags));
        }
コード例 #10
0
 private Int32 ParseInt(BitBuffer bitBuffer, Entry e)
 {
     Boolean negative = bitBuffer.ReadBoolean();
     return (Int32)bitBuffer.ReadUnsignedBits((Int32)e.nBits - 1) / (Int32)e.Divisor * (negative ? -1 : 1);
 }
コード例 #11
0
        public void ReadDelta(BitBuffer bitBuffer, HalfLifeDelta delta, out Byte[] bitmaskBytes)
        {
            // read bitmask
            UInt32 nBitmaskBytes = bitBuffer.ReadUnsignedBits(3);
            // TODO: error check nBitmaskBytes against nEntries

            if (nBitmaskBytes == 0)
            {
                bitmaskBytes = null;
                return;
            }

            bitmaskBytes = new Byte[nBitmaskBytes];

            for (Int32 i = 0; i < nBitmaskBytes; i++)
            {
                bitmaskBytes[i] = bitBuffer.ReadByte();
            }

            for (Int32 i = 0; i < nBitmaskBytes; i++)
            {
                for (Int32 j = 0; j < 8; j++)
                {
                    Int32 index = j + i * 8;

                    if (index == entryList.Count)
                    {
                        return;
                    }

                    if ((bitmaskBytes[i] & (1 << j)) != 0)
                    {
                        Object value = ParseEntry(bitBuffer, entryList[index]);

                        if (delta != null)
                        {
                            delta.SetEntryValue(index, value);
                        }
                    }
                }
            }
        }
コード例 #12
0
        public void ReadDelta(BitBuffer bitBuffer, HalfLifeDelta delta)
        {
            Byte[] bitmaskBytes;

            ReadDelta(bitBuffer, delta, out bitmaskBytes);
        }
コード例 #13
0
        public void ParseGameDataMessages(Byte[] frameData, Function <Byte, Byte> userMessageCallback)
        {
            Int64 gameDataStartOffset = fileStream.Position - frameData.Length;

            // read game data frame into memory
            bitBuffer       = new BitBuffer(frameData);
            readingGameData = true;

            try
            {
                BeginMessageLog(gameDataStartOffset, frameData);

                // start parsing messages
                while (true)
                {
                    Int32  messageFrameOffset = bitBuffer.CurrentByte;
                    Byte   messageId          = bitBuffer.ReadByte();
                    String messageName        = Enum.GetName(typeof(MessageId), messageId);

                    if (messageName == null) // a user message, presumably
                    {
                        messageName = FindMessageIdString(messageId);
                    }

                    LogMessage(messageId, messageName, messageFrameOffset);

                    MessageHandler messageHandler = FindMessageHandler(messageId);

                    // Handle the conversion of user message id's.
                    // Used by demo writing to convert to the current network protocol.
                    if (messageId > 64 && userMessageCallback != null)
                    {
                        Byte newMessageId = userMessageCallback(messageId);

                        if (newMessageId != messageId)
                        {
                            // write the new id to the bitbuffer
                            bitBuffer.SeekBytes(-1);
                            bitBuffer.RemoveBytes(1);
                            bitBuffer.InsertBytes(new Byte[] { newMessageId });
                        }
                    }

                    // unknown message
                    if (messageHandler == null)
                    {
                        throw new ApplicationException(String.Format("Cannot find message handler for message id \"[{0}] {1}\"", messageId, messageName));
                    }

                    // callback takes priority over length
                    if (messageHandler.Callback != null)
                    {
                        messageHandler.Callback();
                    }
                    else if (messageHandler.Length != -1)
                    {
                        Seek(messageHandler.Length);
                    }
                    else
                    {
                        // user messages
                        if (messageId >= 64)
                        {
                            // All non-engine user messages start with a byte that is the number of bytes in the message remaining.
                            Byte length = bitBuffer.ReadByte();
                            Seek(length);
                        }
                        else
                        {
                            throw new ApplicationException(String.Format("Unknown message id \"{0}\"", messageId));
                        }
                    }

                    // Check if we've reached the end of the frame, or if any of the messages have called SkipGameDataFrame (readingGameData will be false).
                    if (bitBuffer.CurrentByte == bitBuffer.Length || !readingGameData)
                    {
                        break;
                    }
                }
            }
            finally
            {
                readingGameData = false;
            }
        }
コード例 #14
0
ファイル: Game.cs プロジェクト: Traderain/coldemoplayer
 // Counter-Strike and DOD specific.
 public virtual void ConvertClCorpseMessageCallback(Int32 gameVersion, BitBuffer bitBuffer)
 {
 }
コード例 #15
0
ファイル: Game.cs プロジェクト: Stenudd/coldemoplayer
 // Counter-Strike and DOD specific.
 public virtual void ConvertClCorpseMessageCallback(Int32 gameVersion, BitBuffer bitBuffer)
 {
 }