Example #1
0
        private void ProcessMessage(Stream.Message message)
        {
            byte[] data;
            if (!message.IsCompressed)
            {
                data = message.Data;
            }
            else
            {
                data = Snappy.Sharp.Snappy.Uncompress(message.Data);

                Preconditions.CheckArgument(message.DecompressedLength == data.Length);
            }

            using (var stream = Bitstream.CreateWith(data)) {
                while (stream.HasByte())
                {
                    HandleMessage(stream);
                }

                if (!stream.Eof)
                {
                    byte remain = (byte)stream.Remain;
                    int  expect = (1 << remain) - 1;
                    Preconditions.CheckArgument(stream.ReadBits(remain) == expect);
                }
            }
        }
Example #2
0
        private Events?Handle(CSVCMsg_PacketEntities message)
        {
            using (var stream = Bitstream.CreateWith(message.entity_data))
            {
                entityUpdater.Update(
                    stream,
                    (uint)message.baseline,
                    message.update_baseline,
                    (uint)message.updated_entries,
                    message.is_delta);
            }

            if (message.update_baseline)
            {
                var ack = new CCLCMsg_BaselineAck
                {
                    baseline_nr   = state.Baseline,
                    baseline_tick = (int)state.ServerTick
                };
                var ackMsg = DotaGameConnection.ConvertProtoToMessage(
                    (uint)CLC_Messages.clc_BaselineAck,
                    ack);
                connection.SendReliably(ackMsg);
                return(null);
            }
            return(null);
        }
Example #3
0
 public Events?Handle(DotaGameConnection.Message message)
 {
     using (var stream = Bitstream.CreateWith(message.Data))
     {
         if (message.Type == (uint)NET_Messages.net_NOP)
         {
             return(null);
         }
         if (message.Type == (uint)NET_Messages.net_Disconnect)
         {
             return(Handle(Serializer.Deserialize <CNETMsg_Disconnect>(stream)));
         }
         if (message.Type == (uint)NET_Messages.net_Tick)
         {
             return(Handle(Serializer.Deserialize <CNETMsg_Tick>(stream)));
         }
         if (message.Type == (uint)NET_Messages.net_SetConVar)
         {
             return(Handle(Serializer.Deserialize <CNETMsg_SetConVar>(stream)));
         }
         if (message.Type == (uint)NET_Messages.net_SignonState)
         {
             return(Handle(Serializer.Deserialize <CNETMsg_SignonState>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_ServerInfo)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_ServerInfo>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_SendTable)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_SendTable>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_ClassInfo)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_ClassInfo>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_PacketEntities)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_PacketEntities>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_CreateStringTable)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_CreateStringTable>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_UpdateStringTable)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_UpdateStringTable>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_Print)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_Print>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_GameEventList)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_GameEventList>(stream)));
         }
         return(null);
     }
 }
Example #4
0
        public void Update(StringTable table, int numEntries, byte[] data)
        {
            using (var stream = Bitstream.CreateWith(data)) {
                bool option = stream.ReadBool();
                if (option)
                {
                    throw new ArgumentException("Unknown option " + option);
                }

                List <string> keyHistory = new List <string>();

                uint entryId = UInt32.MaxValue;
                uint read    = 0;

                while (read < numEntries)
                {
                    if (!stream.ReadBool())
                    {
                        entryId = stream.ReadBits(table.EntryBits);
                    }
                    else
                    {
                        entryId = unchecked (entryId + 1);
                    }

                    Preconditions.CheckArgument(entryId < table.MaxEntries);

                    string key   = ReadKeyIfIncluded(stream, keyHistory);
                    byte[] value = ReadValueIfIncluded(stream, table.UserDataFixedSize,
                                                       table.UserDataSizeBits);

                    if (entryId < table.Count)
                    {
                        StringTable.Entry entry = table.Get(entryId);

                        if (key != null)
                        {
                            Preconditions.CheckArgument(key.Equals(entry.Key));
                        }

                        if (value != null)
                        {
                            entry.Value = value;
                        }
                    }
                    else
                    {
                        table.Put(entryId, new StringTable.Entry(key, value));
                    }

                    ++read;
                }
            }
        }
Example #5
0
        public void Update(StringTable table, int numEntries, byte[] data)
        {
            using (var stream = Bitstream.CreateWith(data))
            {
                var option = stream.ReadBool();
                if (option)
                {
                    throw new ArgumentException("Unknown option " + option);
                }

                var keyHistory = new List <string>();

                var  entryId = uint.MaxValue;
                uint read    = 0;

                while (read < numEntries)
                {
                    if (!stream.ReadBool())
                    {
                        entryId = stream.ReadBits(table.EntryBits);
                    }
                    else
                    {
                        entryId = unchecked (entryId + 1);
                    }

                    var key   = ReadKeyIfIncluded(stream, keyHistory);
                    var value = ReadValueIfIncluded(stream, table.UserDataFixedSize,
                                                    table.UserDataSizeBits);

                    if (entryId < table.Count)
                    {
                        var entry = table.Get(entryId);

                        if (value != null)
                        {
                            entry.Value = value;
                        }
                    }
                    else
                    {
                        table.Put(entryId, new StringTable.Entry(key, value));
                    }

                    ++read;
                }
            }
        }
Example #6
0
        public Events?Handle(byte[] response)
        {
            using (var stream = Bitstream.CreateWith(response))
            {
                var type = stream.ReadByte();

                if (type == S2C_CHALLENGE)
                {
                    if (stream.ReadUInt32() != SOURCE_PROTOCOL)
                    {
                        throw new ArgumentException("Not SOURCE_PROTOCOL!");
                    }
                    server_challenge = stream.ReadUInt32();
                    if (stream.ReadUInt32() != client_challenge)
                    {
                        throw new ArgumentException("Client challenge does not match!");
                    }
                    if (stream.ReadUInt32() != STEAM_VERSION)
                    {
                        throw new ArgumentException("STEAM_VERSION mismatch!");
                    }
                    server_id = stream.ReadUInt64();
                    stream.ReadByte(); // mystery byte
                    return(Events.HANDSHAKE_CHALLENGE);
                }
                if (type == S2C_ACCEPT)
                {
                    if (stream.ReadUInt32() != client_challenge)
                    {
                        throw new ArgumentException("Client challenge does not match!");
                    }
                    return(Events.HANDSHAKE_COMPLETE);
                }
                if (type == S2C_REJECT)
                {
                    if (stream.ReadUInt32() != client_challenge)
                    {
                        throw new ArgumentException("Client challenge does not match!");
                    }

                    rejected_reason = stream.ReadString();
                    return(Events.REJECTED);
                }
                throw new ArgumentException("Unknown response type " + type);
            }
        }
Example #7
0
 private Events?Handle(CSVCMsg_UserMessage message)
 {
     if (message.msg_type == (int)EBaseUserMessages.UM_SayText2)
     {
         using (var stream = Bitstream.CreateWith(message.msg_data))
         {
             return(Handle(Serializer.Deserialize <CUserMsg_SayText2>(stream)));
         }
     }
     if (message.msg_type == (int)EDotaUserMessages.DOTA_UM_ChatEvent)
     {
         using (var stream = Bitstream.CreateWith(message.msg_data))
         {
             return(Handle(Serializer.Deserialize <CDOTAUserMsg_ChatEvent>(stream)));
         }
     }
     return(null);
 }
Example #8
0
        private void ProcessMessage(Stream.Message message)
        {
            var data = !message.IsCompressed ? message.Data : new SnappyDecompressor().Decompress(message.Data, 0, message.Data.Length);

            using (var stream = Bitstream.CreateWith(data))
            {
                while (stream.HasByte())
                {
                    HandleMessage(stream);
                }

                if (!stream.Eof)
                {
                    var remain    = (byte)stream.Remain;
                    var expect    = (1 << remain) - 1;
                    var expectTru = stream.ReadBits(remain) == expect;
                }
            }
        }
Example #9
0
        private Events?Handle(CSVCMsg_PacketEntities message)
        {
            using (var stream = Bitstream.CreateWith(message.entity_data))
            {
                entityUpdater.Update(
                    stream,
                    (uint)message.baseline,
                    message.update_baseline,
                    (uint)message.updated_entries,
                    message.is_delta);
            }

            if (message.update_baseline)
            {
                state.Baseline = message.baseline;
                return(Events.BASELINE);
            }
            return(null);
        }
Example #10
0
 public Events?Handle(DotaGameConnection.Message message)
 {
     using (var stream = Bitstream.CreateWith(message.Data))
     {
         if (message.Type == (uint)NET_Messages.net_NOP)
         {
             return(null);
         }
         if (message.Type == (uint)NET_Messages.net_Disconnect)
         {
             return(Handle(Serializer.Deserialize <CNETMsg_Disconnect>(stream)));
         }
         if (message.Type == (uint)NET_Messages.net_StringCmd)
         {
             return(Handle(Serializer.Deserialize <CNETMsg_StringCmd>(stream)));
         }
         if (message.Type == (uint)NET_Messages.net_Tick)
         {
             return(Handle(Serializer.Deserialize <CNETMsg_Tick>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_PacketEntities)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_PacketEntities>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_UpdateStringTable)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_UpdateStringTable>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_UserMessage)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_UserMessage>(stream)));
         }
         if (message.Type == (uint)SVC_Messages.svc_GameEvent)
         {
             return(Handle(Serializer.Deserialize <CSVCMsg_GameEvent>(stream)));
         }
         return(null);
     }
 }
Example #11
0
        public void Auth()
        {
            var pb = new CMsgAuthTicket();

            pb.gameid       = App;
            pb.h_steam_pipe = 327684;

            using (var stream = Bitstream.CreateWith(PendingTicketForAuth.ToArray())) {
                pb.ticket_crc = CrcUtils.Compute32(stream);
            }

            pb.ticket = PendingTicketForAuth.ToArray();

            var msg = new ClientMsgProtobuf <CMsgClientAuthList>(EMsg.ClientAuthList);

            msg.Body.tokens_left = Bot.TokenCount;
            msg.Body.app_ids.Add(App);
            msg.Body.tickets.Add(pb);
            msg.Body.message_sequence = AuthSequence++;
            Bot.Client.Send(msg);
            log.Debug("Sent auth list with crc " + msg.Body.tickets[0].ticket_crc + "/" + msg.Body.message_sequence);
        }
Example #12
0
        private void Create(uint id, EntityClass clazz, uint baseline)
        {
            state.Created.Add(id);
            if (!state.Slots.ContainsKey(id))
            {
                state.Slots[id] = new DotaGameState.Slot(null);
            }

            var slot = state.Slots[id];

            slot.Live = true;
            if (slot.Baselines[baseline] != null && slot.Baselines[baseline].Class.Equals(clazz))
            {
                slot.Entity = slot.Baselines[baseline].Copy();
            }
            else
            {
                slot.Entity = Entity.CreateWith(id, clazz, state.FlatTables[(int)clazz.Id]);

                var table = state.Strings[state.StringsIndex["instancebaseline"]];
                using (var stream = Bitstream.CreateWith(table.Get(clazz.Id.ToString()).Value))
                {
                    ReadAndUnpackFields(slot.Entity, stream);
                }
            }

            foreach (var prop in slot.Entity.Properties)
            {
                var info   = prop.Info;
                var handle = new DotaGameState.PropertyHandle
                {
                    Entity = id,
                    Table  = info.Origin.NetTableName,
                    Name   = info.VarName
                };
                state.Properties[handle] = prop;
            }
        }
Example #13
0
        private void ProcessPacket(byte[] bytes, int length)
        {
            using (var stream = Bitstream.CreateWith(bytes, length))
            {
                var seq = stream.ReadUInt32();
                var ack = stream.ReadUInt32();

                var flags    = stream.ReadByte();
                var checksum = stream.ReadUInt16();

                var at       = stream.Position;
                var computed = CrcUtils.Compute16(stream);
                stream.Position = at;

                if (checksum != computed)
                {
                    return;
                }

                var reliableState = stream.ReadByte();

                if (seq < sequenceIn)
                {
                    // We no longer care.
                    return;
                }

                for (byte i = 0; i < subchannels.Length; ++i)
                {
                    var channel = subchannels[i];
                    var mask    = 1 << i;

                    if ((reliableStateOut & mask) == (reliableState & mask))
                    {
                        if (channel.Blocked)
                        {
                            channel.Clear();
                        }
                    }
                    else
                    {
                        if (channel.Blocked && channel.SentIn < ack)
                        {
                            reliableStateOut = Flip(reliableStateOut, i);
                            channel.Requeue();
                        }
                    }
                }

                if ((flags & (uint)PacketFlags.IsReliable) != 0)
                {
                    var bit = stream.ReadBits(3);
                    reliableStateIn = Flip(reliableStateIn, bit);

                    for (var i = 0; i < streams.Length; ++i)
                    {
                        var message = streams[i].Receive(stream);

                        if (message.HasValue)
                        {
                            ProcessMessage(message.Value);
                        }
                    }
                }

                while (stream.HasByte())
                {
                    HandleMessage(stream);
                }

                if (!stream.Eof)
                {
                    var remain      = (byte)stream.Remain;
                    var expect      = (1 << remain) - 1;
                    var expectedTru = stream.ReadBits(remain) == expect; // if false then probably something wrong
                }

                lastAckRecv = ack;
                sequenceIn  = seq;
            }
        }
Example #14
0
        private void ReceivePacket(byte[] bytes, int length)
        {
            ++receivedTotal;

            using (var stream = Bitstream.CreateWith(bytes, length))
            {
                var type = stream.ReadUInt32();

                if (type == COMPRESSED_PACKET)
                {
                    var method = stream.ReadUInt32();

                    var compressed = new byte[length - 8];
                    stream.Read(compressed, 0, compressed.Length);

                    var decompressed = Lzss.Decompress(compressed);
                    ProcessPacket(decompressed, decompressed.Length);
                }
                else if (type == SPLIT_PACKET)
                {
                    var request = stream.ReadUInt32();
                    var total   = stream.ReadByte();
                    var index   = stream.ReadByte();
                    var size    = stream.ReadUInt16();

                    SplitPacket split;
                    if (!splitPackets.ContainsKey(request))
                    {
                        split = new SplitPacket
                        {
                            Request  = request,
                            Total    = total,
                            Received = 0,
                            Data     = new byte[total][],
                            Present  = new bool[total]
                        };
                        splitPackets[request] = split;
                    }
                    else
                    {
                        split = splitPackets[request];
                    }

                    var buffer = new byte[Math.Min(size, (stream.Remain + 7) / 8)];
                    stream.Read(buffer, 0, buffer.Length);
                    split.Data[index] = buffer;

                    if (!split.Present[index])
                    {
                        ++split.Received;
                        split.Present[index] = true;
                    }

                    if (split.Received == split.Total)
                    {
                        var full = split.Data.SelectMany(b => b).ToArray();
                        ReceivePacket(full, full.Length);
                        splitPackets.Remove(request);
                    }
                }
                else if (type == OOB_PACKET)
                {
                    var data = new byte[stream.Length - 4];
                    stream.Read(data, 0, data.Length);

                    receivedOutOfBand.Enqueue(data);
                }
                else
                {
                    ProcessPacket(bytes, length);
                }
            }
        }
Example #15
0
        private void ProcessPacket(byte[] bytes, int length)
        {
            using (var stream = Bitstream.CreateWith(bytes, length)) {
                uint seq = stream.ReadUInt32();
                uint ack = stream.ReadUInt32();

                byte   flags    = stream.ReadByte();
                ushort checksum = stream.ReadUInt16();

                long   at       = stream.Position;
                ushort computed = CrcUtils.Compute16(stream);
                stream.Position = at;

                if (checksum != computed)
                {
                    log.WarnFormat(
                        "failed checksum:"
                        + "recv seq {0} ack {1} flags {2:x} checksum {3:x} computed {4:x}",
                        seq, ack, flags, checksum, computed);
                    return;
                }

                byte reliableState = stream.ReadByte();

                if ((flags & 0x10) == 0x10)
                {
                    log.WarnFormat(
                        "choke {0}: recv seq {1} ack {2} flags {3:x}",
                        stream.ReadByte(), seq, ack, flags);
                }

                if (seq < sequenceIn)
                {
                    // We no longer care.
                    log.WarnFormat("dropped: recv seq {0} ack {1}", seq, ack);
                    return;
                }

                for (byte i = 0; i < subchannels.Length; ++i)
                {
                    Subchannel channel = subchannels[i];
                    int        mask    = 1 << i;

                    if ((reliableStateOut & mask) == (reliableState & mask))
                    {
                        if (channel.Blocked)
                        {
                            Preconditions.CheckArgument(ack >= channel.SentIn);

                            channel.Clear();
                        }
                    }
                    else
                    {
                        if (channel.Blocked && channel.SentIn < ack)
                        {
                            reliableStateOut = Flip(reliableStateOut, i);
                            channel.Requeue();
                        }
                    }
                }

                if ((flags & (uint)PacketFlags.IsReliable) != 0)
                {
                    uint bit = stream.ReadBits(3);
                    //Debug.WriteLine("  reliable, flip {0}. {1} => {2}", bit, reliableStateIn, Flip(reliableStateIn, bit));
                    reliableStateIn = Flip(reliableStateIn, bit);

                    for (int i = 0; i < streams.Length; ++i)
                    {
                        Nullable <Stream.Message> message = streams[i].Receive(stream);

                        if (message.HasValue)
                        {
                            ProcessMessage(message.Value);
                        }
                    }
                }

                while (stream.HasByte())
                {
                    HandleMessage(stream);
                }

                if (!stream.Eof)
                {
                    byte remain = (byte)stream.Remain;
                    int  expect = (1 << remain) - 1;
                    Preconditions.CheckArgument(stream.ReadBits(remain) == expect);
                }

                lastAckRecv = ack;
                sequenceIn  = seq;
            }
        }
Example #16
0
        /// <summary>
        ///     Connect to the game server. Will use existing lobby on default.
        /// </summary>
        /// <param name="lobb"></param>
        public void Connect(CSODOTALobby lobb = null)
        {
            if (_connectDetails != null)
            {
                Disconnect();
            }

            lobb = lobb ?? DotaGc.Lobby;
            if (lobb == null)
            {
                Log("No lobby so not connecting.");
                return;
            }

            _connectLobby = lobb;
            if (_appOwnershipTicket == null)
            {
                Log("Waiting for ownership ticket...");
                _waitingForAuthTicket = true;
                FetchAppTicket();
                return;
            }

            _authTicket = AuthTicket.CreateAuthTicket(_gameConnectTokens.Dequeue(), publicIP);

            var ver = new CMsgAuthTicket
            {
                gameid       = (uint)DotaGc.GameID,
                h_steam_pipe = 327684,
                ticket       = _authTicket
            };

            using (var stream = Bitstream.CreateWith(_authTicket))
                ver.ticket_crc = CrcUtils.Compute32(stream);

            _connectDetails = new DOTAConnectDetails
            {
                AuthTicket       = _authTicket,
                ServerAuthTicket = AuthTicket.CreateServerTicket(DotaGc.SteamClient.SteamID, _authTicket, _appOwnershipTicket),
                ConnectInfo      = lobb.connect,
                ConnectID        = _connectAttempt++,
                AuthTicketCRC    = ver.ticket_crc,
                Name             = DotaGc.SteamClient.GetHandler <SteamFriends>().GetPersonaName(),
                PassKey          = lobb.pass_key,
                SteamId          = DotaGc.SteamClient.SteamID.ConvertToUInt64()
            };

            var msg = new ClientMsgProtobuf <CMsgClientAuthList>(EMsg.ClientAuthList)
            {
                Body =
                {
                    tokens_left      = (uint)_gameConnectTokens.Count,
                    app_ids          = { (uint)DotaGc.GameID },
                    tickets          = { ver },
                    message_sequence = 2 // Second in sequence.
                }
            };

            DotaGc.SteamClient.Send(msg);
            Log("Sent crc ticket auth list, hash: " + ver.ticket_crc + ".");
        }