예제 #1
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);
            }
        }
예제 #2
0
        private IncomingPacket ReceiveAck(IncomingPacket packet)
        {
            if (packet.Data.Length < 2)
            {
                return(null);
            }
            ushort packetId = NetUtil.N2Hushort(packet.Data, 0);

            lock (sendLoopLock)
                packetAckManager.Remove(packetId);
            return(packet);
        }
예제 #3
0
        internal static IncomingPacket GetIncommingPacket(byte[] data)
        {
            if (data.Length < InHeaderLen + MacLen)
            {
                return(null);
            }

            return(new IncomingPacket(data)
            {
                PacketTypeFlagged = data[MacLen + 2],
                PacketId = NetUtil.N2Hushort(data, MacLen),
            });
        }
예제 #4
0
        private void ReceivePong(IncomingPacket packet)
        {
            ushort         answerId = NetUtil.N2Hushort(packet.Data, 0);
            OutgoingPacket sendPing;

            lock (sendLoopLock)
            {
                if (!packetPingManager.TryGetValue(answerId, out sendPing))
                {
                    return;
                }
                packetPingManager.Remove(answerId);
            }
            NetworkStats.AddPing(Util.Now - sendPing.LastSendTime);
        }
예제 #5
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);
        }
예제 #6
0
        internal IncomingPacket Decrypt(byte[] data)
        {
            if (data.Length < InHeaderLen + MacLen)
            {
                return(null);
            }

            var packet = new IncomingPacket(data)
            {
                PacketTypeFlagged = data[MacLen + 2],
                PacketId          = NetUtil.N2Hushort(data, MacLen),
            };

            if (packet.PacketType == PacketType.Init1)
            {
                if (!FakeDecrypt(packet, TS3InitMac))
                {
                    return(null);
                }
            }
            else
            {
                if (packet.UnencryptedFlag)
                {
                    if (!FakeDecrypt(packet, fakeSignature))
                    {
                        return(null);
                    }
                }
                else
                {
                    if (!Decrypt(packet))
                    {
                        return(null);
                    }
                }
            }

            return(packet);
        }
예제 #7
0
        public S2CPacket FetchPacket()
        {
            while (true)
            {
                if (Closed)
                {
                    return(null);
                }

                if (TryFetchPacket(receiveQueue, out var packet))
                {
                    return(packet);
                }
                if (TryFetchPacket(receiveQueueLow, out packet))
                {
                    return(packet);
                }

                var    dummy = new IPEndPoint(IPAddress.Any, 0);
                byte[] buffer;

                try { buffer = udpClient.Receive(ref dummy); }
                catch (IOException) { return(null); }
                catch (SocketException) { return(null); }

                if (dummy.Address.Equals(remoteAddress.Address) && dummy.Port != remoteAddress.Port)
                {
                    continue;
                }

                packet = Ts3Crypt.GetIncommingPacket(buffer);
                // Invalid packet, ignore
                if (packet == null)
                {
                    LoggerRaw.Debug("Dropping invalid packet: {0}", DebugUtil.DebugToHex(buffer));
                    continue;
                }

                GenerateGenerationId(packet);
                if (!ts3Crypt.Decrypt(packet))
                {
                    continue;
                }

                NetworkStats.LogInPacket(packet);

                switch (packet.PacketType)
                {
                case PacketType.Voice:
                case PacketType.VoiceWhisper:
                    LoggerRawVoice.ConditionalTrace("[I] {0}", packet);
                    break;

                case PacketType.Command:
                    LoggerRaw.Debug("[I] {0}", packet);
                    packet = ReceiveCommand(packet, receiveQueue, PacketType.Ack);
                    break;

                case PacketType.CommandLow:
                    LoggerRaw.Debug("[I] {0}", packet);
                    packet = ReceiveCommand(packet, receiveQueueLow, PacketType.AckLow);
                    break;

                case PacketType.Ping:
                    LoggerRaw.ConditionalTrace("[I] Ping {0}", packet.PacketId);
                    ReceivePing(packet);
                    break;

                case PacketType.Pong:
                    LoggerRaw.ConditionalTrace("[I] Pong {0}", NetUtil.N2Hushort(packet.Data, 0));
                    ReceivePong(packet);
                    break;

                case PacketType.Ack:
                    LoggerRaw.ConditionalDebug("[I] Acking: {0}", NetUtil.N2Hushort(packet.Data, 0));
                    packet = ReceiveAck(packet);
                    break;

                case PacketType.AckLow: break;

                case PacketType.Init1:
                    LoggerRaw.Debug("[I] InitID: {0}", packet.Data[0]);
                    LoggerRaw.Trace("[I] {0}", packet);
                    ReceiveInitAck(packet);
                    break;

                default: throw Util.UnhandledDefault(packet.PacketType);
                }

                if (packet != null)
                {
                    return(packet);
                }
            }
        }
예제 #8
0
        private void SendOutgoingData(ReadOnlySpan <byte> data, PacketType packetType, PacketFlags flags = PacketFlags.None)
        {
            var packet = new C2SPacket(data.ToArray(), packetType);

            lock (sendLoopLock)
            {
                var ids = GetPacketCounter(packet.PacketType);
                if (ts3Crypt.CryptoInitComplete)
                {
                    IncPacketCounter(packet.PacketType);
                }

                packet.PacketId     = ids.Id;
                packet.GenerationId = ids.Generation;
                packet.ClientId     = ClientId;
                packet.PacketFlags |= flags;

                switch (packet.PacketType)
                {
                case PacketType.Voice:
                case PacketType.VoiceWhisper:
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    NetUtil.H2N(packet.PacketId, packet.Data, 0);
                    LoggerRawVoice.ConditionalTrace("[O] {0}", packet);
                    break;

                case PacketType.Command:
                case PacketType.CommandLow:
                    packet.PacketFlags |= PacketFlags.Newprotocol;
                    packetAckManager.Add(packet.PacketId, packet);
                    LoggerRaw.Debug("[O] {0}", packet);
                    break;

                case PacketType.Ping:
                    lastSentPingId      = packet.PacketId;
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    LoggerRaw.ConditionalTrace("[O] Ping {0}", packet.PacketId);
                    break;

                case PacketType.Pong:
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    LoggerRaw.ConditionalTrace("[O] Pong {0}", NetUtil.N2Hushort(packet.Data, 0));
                    break;

                case PacketType.Ack:
                case PacketType.AckLow:
                    LoggerRaw.ConditionalDebug("[O] Acking {1}: {0}", NetUtil.N2Hushort(packet.Data, 0), packet.PacketType);
                    break;

                case PacketType.Init1:
                    packet.PacketFlags |= PacketFlags.Unencrypted;
                    initPacketCheck     = packet;
                    LoggerRaw.Debug("[O] InitID: {0}", packet.Data[4]);
                    LoggerRaw.Trace("[O] {0}", packet);
                    break;

                default: throw Util.UnhandledDefault(packet.PacketType);
                }

                ts3Crypt.Encrypt(packet);

                packet.FirstSendTime = Util.Now;
                SendRaw(packet);
            }
        }