예제 #1
0
        private void ReceivePong(S2CPacket packet)
        {
            ushort answerId = BinaryPrimitives.ReadUInt16BigEndian(packet.Data);

            if (lastSentPingId == answerId)
            {
                var rtt = pingTimer.Elapsed;
                UpdateRto(rtt);
                NetworkStats.AddPing(rtt);
            }
        }
예제 #2
0
        private void ReceivePong(S2CPacket packet)
        {
            ushort answerId = NetUtil.N2Hushort(packet.Data, 0);

            if (lastSentPingId == answerId)
            {
                var rtt = pingTimer.Elapsed;
                UpdateRto(rtt);
                NetworkStats.AddPing(rtt);
            }
        }
예제 #3
0
        internal void LogInPacket(S2CPacket packet)
        {
            var kind = TypeToKind(packet.PacketType);

            inPackets[(int)kind]++;
            inBytes[(int)kind] += packet.Raw.Length;
            lock (queueLock)
            {
                DropOver(inBytesTime, TimeMinute);
                inBytesTime.Enqueue(new PacketData(packet.Raw.Length, Util.Now, kind));
            }
        }
예제 #4
0
        // These methods are for low level packet processing which the
        // rather high level TS3FullClient should not worry about.

        private void GenerateGenerationId(S2CPacket packet)
        {
            // TODO rework this for all packet types
            RingQueue <S2CPacket> packetQueue;

            switch (packet.PacketType)
            {
            case PacketType.Command: packetQueue = receiveQueue; break;

            case PacketType.CommandLow: packetQueue = receiveQueueLow; break;

            default: return;
            }

            packet.GenerationId = packetQueue.GetGeneration(packet.PacketId);
        }
예제 #5
0
        private void ReceivePing(S2CPacket packet)
        {
            var idDiff = packet.PacketId - lastReceivedPingId;

            if (idDiff > 1 && idDiff < ReceivePacketWindowSize)
            {
                NetworkStats.LogLostPings(idDiff - 1);
            }
            if (idDiff > 0 || idDiff < -ReceivePacketWindowSize)
            {
                lastReceivedPingId = packet.PacketId;
            }
            byte[] pongData = new byte[2];
            NetUtil.H2N(packet.PacketId, pongData, 0);
            AddOutgoingPacket(pongData, PacketType.Pong);
        }
예제 #6
0
        private void ReceivePing(S2CPacket packet)
        {
            var idDiff = packet.PacketId - lastReceivedPingId;

            if (idDiff > 1 && idDiff < ReceivePacketWindowSize)
            {
                NetworkStats.LogLostPings(idDiff - 1);
            }
            if (idDiff > 0 || idDiff < -ReceivePacketWindowSize)
            {
                lastReceivedPingId = packet.PacketId;
            }
            byte[] pongData = new byte[2];             // stackalloc
            BinaryPrimitives.WriteUInt16BigEndian(pongData.AsSpan(), packet.PacketId);
            AddOutgoingPacket(pongData, PacketType.Pong);
        }
예제 #7
0
        private S2CPacket ReceiveAck(S2CPacket packet)
        {
            if (packet.Data.Length < 2)
            {
                return(null);
            }
            ushort packetId = BinaryPrimitives.ReadUInt16BigEndian(packet.Data);

            lock (sendLoopLock)
            {
                if (packetAckManager.TryGetValue(packetId, out var ackPacket))
                {
                    UpdateRto(Util.Now - ackPacket.LastSendTime);
                    packetAckManager.Remove(packetId);
                }
            }
            return(packet);
        }
예제 #8
0
        private S2CPacket ReceiveAck(S2CPacket packet)
        {
            if (packet.Data.Length < 2)
            {
                return(null);
            }
            ushort packetId = NetUtil.N2Hushort(packet.Data, 0);

            lock (sendLoopLock)
            {
                if (packetAckManager.TryGetValue(packetId, out var ackPacket))
                {
                    UpdateRto(Util.Now - ackPacket.LastSendTime);
                    packetAckManager.Remove(packetId);
                }
            }
            return(packet);
        }
예제 #9
0
        private S2CPacket ReceiveCommand(S2CPacket packet, RingQueue <S2CPacket> packetQueue, PacketType ackType)
        {
            var setStatus = packetQueue.IsSet(packet.PacketId);

            // Check if we cannot accept this packet since it doesn't fit into the receive window
            if (setStatus == ItemSetStatus.OutOfWindowNotSet)
            {
                return(null);
            }

            packet.GenerationId = packetQueue.GetGeneration(packet.PacketId);
            SendAck(packet.PacketId, ackType);

            // Check if we already have this packet and only need to ack it.
            if (setStatus == ItemSetStatus.InWindowSet || setStatus == ItemSetStatus.OutOfWindowSet)
            {
                return(null);
            }

            packetQueue.Set(packet.PacketId, packet);
            return(TryFetchPacket(packetQueue, out var retPacket) ? retPacket : null);
        }
예제 #10
0
 private void ReceiveInitAck(S2CPacket packet, bool done = false)
 {
     lock (sendLoopLock)
     {
         if (initPacketCheck == null || packet == null)
         {
             if (done)
             {
                 initPacketCheck = null;
             }
             return;
         }
         // optional: add random number check from init data
         var forwardData = ts3Crypt.ProcessInit1(packet.Data);
         if (!forwardData.Ok)
         {
             LoggerRaw.Debug("Error init: {0}", forwardData.Error);
             return;
         }
         initPacketCheck = null;
         AddOutgoingPacket(forwardData.Value, PacketType.Init1);
     }
 }
예제 #11
0
        private static bool TryFetchPacket(RingQueue <S2CPacket> packetQueue, out S2CPacket packet)
        {
            if (packetQueue.Count <= 0)
            {
                packet = null; return(false);
            }

            int  take     = 0;
            int  takeLen  = 0;
            bool hasStart = false;
            bool hasEnd   = false;

            for (int i = 0; i < packetQueue.Count; i++)
            {
                if (packetQueue.TryPeekStart(i, out var peekPacket))
                {
                    take++;
                    takeLen += peekPacket.Size;
                    if (peekPacket.FragmentedFlag)
                    {
                        if (!hasStart)
                        {
                            hasStart = true;
                        }
                        else
                        {
                            hasEnd = true; break;
                        }
                    }
                    else
                    {
                        if (!hasStart)
                        {
                            hasStart = true; hasEnd = true; break;
                        }
                    }
                }
                else
                {
                    break;
                }
            }

            if (!hasStart || !hasEnd)
            {
                packet = null; return(false);
            }

            // GET
            if (!packetQueue.TryDequeue(out packet))
            {
                throw new InvalidOperationException("Packet in queue got missing (?)");
            }

            // MERGE
            if (take > 1)
            {
                var preFinalArray = new byte[takeLen];

                // for loop at 0th element
                int curCopyPos = packet.Size;
                Array.Copy(packet.Data, 0, preFinalArray, 0, packet.Size);

                for (int i = 1; i < take; i++)
                {
                    if (!packetQueue.TryDequeue(out S2CPacket nextPacket))
                    {
                        throw new InvalidOperationException("Packet in queue got missing (?)");
                    }

                    Array.Copy(nextPacket.Data, 0, preFinalArray, curCopyPos, nextPacket.Size);
                    curCopyPos += nextPacket.Size;
                }
                packet.Data = preFinalArray;
            }

            // DECOMPRESS
            if (packet.CompressedFlag)
            {
                try
                {
                    packet.Data = QuickerLz.Decompress(packet.Data, MaxDecompressedSize);
                }
                catch (Exception)
                {
                    Debug.WriteLine("Got invalid compressed data.");
                    return(false);
                }
            }
            return(true);
        }