예제 #1
0
        public void Connect(IPEndPoint address)
        {
            resendThread = new Thread(ResendLoop)
            {
                Name = "PacketHandler"
            };
            resendThreadId = resendThread.ManagedThreadId;

            lock (sendLoopLock)
            {
                ClientId           = 0;
                ExitReason         = null;
                smoothedRtt        = MaxRetryInterval;
                smoothedRttVar     = TimeSpan.Zero;
                currentRto         = MaxRetryInterval;
                lastSentPingId     = 0;
                lastReceivedPingId = 0;

                initPacketCheck = null;
                packetAckManager.Clear();
                receiveQueue.Clear();
                receiveQueueLow.Clear();
                Array.Clear(packetCounter, 0, packetCounter.Length);
                Array.Clear(generationCounter, 0, generationCounter.Length);
                NetworkStats.Reset();

                ConnectUdpClient(address);
            }

            resendThread.Start();

            AddOutgoingPacket(ts3Crypt.ProcessInit1(null).Value, PacketType.Init1);
        }
예제 #2
0
 private void SendRaw(C2SPacket packet)
 {
     packet.LastSendTime = Util.Now;
     NetworkStats.LogOutPacket(packet);
     LoggerRaw.Trace("[O] Raw: {0}", DebugUtil.DebugToHex(packet.Raw));
     udpClient.Send(packet.Raw, packet.Raw.Length);
 }
예제 #3
0
        internal void LogOutPacket(C2SPacket packet)
        {
            var kind = TypeToKind(packet.PacketType);

            outPackets[(int)kind]++;
            outBytes[(int)kind] += packet.Raw.Length;
            lock (queueLock)
            {
                DropOver(outBytesTime, TimeMinute);
                outBytesTime.Enqueue(new PacketData(packet.Raw.Length, Util.Now, kind));
            }
        }
예제 #4
0
        private bool ResendPacket(C2SPacket packet, DateTime now)
        {
            // Check if the packet timed out completely
            if (packet.FirstSendTime < now - PacketTimeout)
            {
                LoggerTimeout.Debug("TIMEOUT: {0}", packet);
                return(true);
            }

            // Check if we should retransmit a packet because it probably got lost
            if (packet.LastSendTime < now - currentRto)
            {
                LoggerTimeout.Debug("RESEND: {0}", packet);
                currentRto = currentRto + currentRto;
                if (currentRto > MaxRetryInterval)
                {
                    currentRto = MaxRetryInterval;
                }
                SendRaw(packet);
            }

            return(false);
        }
예제 #5
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);
     }
 }
예제 #6
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;
                    BinaryPrimitives.WriteUInt16BigEndian(packet.Data.AsSpan(), packet.PacketId);
                    LoggerRawVoice.Trace("[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.Trace("[O] Ping {0}", packet.PacketId);
                    break;

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

                case PacketType.Ack:
                case PacketType.AckLow:
                    LoggerRaw.Debug("[O] Acking {1}: {0}", BinaryPrimitives.ReadUInt16BigEndian(packet.Data), 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);
            }
        }