Beispiel #1
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);
 }
Beispiel #2
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);
        }
Beispiel #3
0
        private void Initialize(IPEndPoint address, bool connect)
        {
            lock (sendLoopLock)
            {
                ClientId           = 0;
                closed             = 0;
                smoothedRtt        = MaxRetryInterval;
                smoothedRttVar     = TimeSpan.Zero;
                currentRto         = MaxRetryInterval;
                lastSentPingId     = 0;
                lastReceivedPingId = 0;
                lastMessageTimer.Restart();

                initPacketCheck = null;
                packetAckManager.Clear();
                receiveQueueCommand.Clear();
                receiveQueueCommandLow.Clear();
                receiveWindowVoice.Reset();
                receiveWindowVoiceWhisper.Reset();
                Array.Clear(packetCounter, 0, packetCounter.Length);
                Array.Clear(generationCounter, 0, generationCounter.Length);
                NetworkStats.Reset();

                socket?.Dispose();
                try
                {
                    if (connect)
                    {
                        remoteAddress = address;
                        socket        = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                        socket.Bind(new IPEndPoint(address.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0));

                        var socketEventArgs = new SocketAsyncEventArgs();
                        socketEventArgs.SetBuffer(new byte[4096], 0, 4096);
                        socketEventArgs.Completed     += FetchPacketEvent;
                        socketEventArgs.UserToken      = this;
                        socketEventArgs.RemoteEndPoint = remoteAddress;
                        socket.ReceiveFromAsync(socketEventArgs);
                    }
                    else
                    {
                        remoteAddress = null;
                        socket        = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                        socket.Bind(address);
                        // TODO init socketevargs stuff
                    }
                }
                catch (SocketException ex) { throw new Ts3Exception("Could not connect", ex); }

                pingCheckRunning = 0;
                pingCheck        = Util.Now;
                if (resendTimer == null)
                {
                    resendTimer = new Timer((_) => { using (MappedDiagnosticsContext.SetScoped("BotId", id)) ResendLoop(); }, null, ClockResolution, ClockResolution);
                }
            }
        }
Beispiel #4
0
        private void Initialize(IPEndPoint address, bool connect)
        {
            var 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;
                lastMessageTimer.Restart();

                initPacketCheck = null;
                packetAckManager.Clear();
                receiveQueueCommand.Clear();
                receiveQueueCommandLow.Clear();
                receiveWindowVoice.Reset();
                receiveWindowVoiceWhisper.Reset();
                Array.Clear(packetCounter, 0, packetCounter.Length);
                Array.Clear(generationCounter, 0, generationCounter.Length);
                NetworkStats.Reset();

                udpClient?.Dispose();
                try
                {
                    if (connect)
                    {
                        remoteAddress = address;
                        udpClient     = new UdpClient(address.AddressFamily);
                        udpClient.Connect(address);
                    }
                    else
                    {
                        remoteAddress = null;
                        udpClient     = new UdpClient(address);
                    }
                }
                catch (SocketException ex) { throw new Ts3Exception("Could not connect", ex); }
            }

            try
            {
                resendThread.Start();
            }
            catch (SystemException ex) { throw new Ts3Exception("Error initializing internal stuctures", ex); }
        }
Beispiel #5
0
        private void ReceivePong(S2CPacket packet)
        {
            ushort answerId = BinaryPrimitives.ReadUInt16BigEndian(packet.Data);

            if (lastSentPingId == answerId)
            {
                var rtt = pingTimer.Elapsed;
                UpdateRto(rtt);
                NetworkStats.AddPing(rtt);
            }
        }
Beispiel #6
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);
            }
        }
Beispiel #7
0
        public PacketHandler(Ts3Crypt ts3Crypt)
        {
            packetAckManager  = new Dictionary <ushort, OutgoingPacket>();
            packetPingManager = new Dictionary <ushort, OutgoingPacket>();
            receiveQueue      = new RingQueue <IncomingPacket>(PacketBufferSize);
            receiveQueueLow   = new RingQueue <IncomingPacket>(PacketBufferSize);
            NetworkStats      = new NetworkStats();

            packetCounter  = new ushort[9];
            this.ts3Crypt  = ts3Crypt;
            resendThreadId = -1;
        }
Beispiel #8
0
        public PacketHandler(Ts3Crypt ts3Crypt)
        {
            packetAckManager = new Dictionary <ushort, C2SPacket>();
            receiveQueue     = new RingQueue <S2CPacket>(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveQueueLow  = new RingQueue <S2CPacket>(ReceivePacketWindowSize, ushort.MaxValue + 1);
            NetworkStats     = new NetworkStats();

            packetCounter     = new ushort[9];
            generationCounter = new uint[9];
            this.ts3Crypt     = ts3Crypt;
            resendThreadId    = -1;
        }
Beispiel #9
0
        public PacketHandler(Ts3Crypt ts3Crypt, Id id)
        {
            receiveQueueCommand       = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveQueueCommandLow    = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveWindowVoice        = new GenerationWindow(ushort.MaxValue + 1);
            receiveWindowVoiceWhisper = new GenerationWindow(ushort.MaxValue + 1);

            NetworkStats = new NetworkStats();

            packetCounter     = new ushort[Ts3Crypt.PacketTypeKinds];
            generationCounter = new uint[Ts3Crypt.PacketTypeKinds];
            this.ts3Crypt     = ts3Crypt;
            this.id           = id;
        }
Beispiel #10
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);
        }
Beispiel #11
0
        public PacketHandler(Ts3Crypt ts3Crypt)
        {
            Util.Init(out packetAckManager);
            receiveQueueCommand       = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveQueueCommandLow    = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveWindowVoice        = new GenerationWindow(ushort.MaxValue + 1);
            receiveWindowVoiceWhisper = new GenerationWindow(ushort.MaxValue + 1);

            NetworkStats = new NetworkStats();

            packetCounter     = new ushort[Ts3Crypt.PacketTypeKinds];
            generationCounter = new uint[Ts3Crypt.PacketTypeKinds];
            this.ts3Crypt     = ts3Crypt;
            resendThreadId    = -1;
        }
Beispiel #12
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);
        }
Beispiel #13
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);
        }
Beispiel #14
0
 private void SendRaw(OutgoingPacket packet)
 {
     packet.LastSendTime = Util.Now;
     NetworkStats.LogOutPacket(packet);
     udpClient.Send(packet.Raw, packet.Raw.Length);
 }
Beispiel #15
0
        public IncomingPacket FetchPacket()
        {
            while (true)
            {
                if (Closed)
                {
                    return(null);
                }

                IncomingPacket packet = null;
                if (TryFetchPacket(receiveQueue, out 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);
                if (IsCommandPacketSet(packet))
                {
                    continue;
                }

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

                NetworkStats.LogInPacket(packet);

                switch (packet.PacketType)
                {
                case PacketType.Voice: break;

                case PacketType.VoiceWhisper: break;

                case PacketType.Command: packet = ReceiveCommand(packet); break;

                case PacketType.CommandLow: packet = ReceiveCommand(packet); break;

                case PacketType.Ping: ReceivePing(packet); break;

                case PacketType.Pong: ReceivePong(packet); break;

                case PacketType.Ack: packet = ReceiveAck(packet); break;

                case PacketType.AckLow: break;

                case PacketType.Init1: ReceiveInitAck(); break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (packet != null)
                {
                    return(packet);
                }
            }
        }
Beispiel #16
0
        public IncomingPacket 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)
                {
                    ColorDbg.WritePkgRaw(buffer, "DROPPING");
                    continue;
                }

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

                NetworkStats.LogInPacket(packet);

                ColorDbg.WritePkgIn(packet);

                switch (packet.PacketType)
                {
                case PacketType.Voice: break;

                case PacketType.VoiceWhisper: break;

                case PacketType.Command: packet = ReceiveCommand(packet, receiveQueue, PacketType.Ack); break;

                case PacketType.CommandLow: packet = ReceiveCommand(packet, receiveQueueLow, PacketType.AckLow); break;

                case PacketType.Ping: ReceivePing(packet); break;

                case PacketType.Pong: ReceivePong(packet); break;

                case PacketType.Ack: packet = ReceiveAck(packet); break;

                case PacketType.AckLow: break;

                case PacketType.Init1: ReceiveInitAck(); break;

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

                if (packet != null)
                {
                    return(packet);
                }
            }
        }
Beispiel #17
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); }
                catch (ObjectDisposedException) { return(null); }

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

                packet = Ts3Crypt.GetS2CPacket(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.Trace("[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.Trace("[I] Ping {0}", packet.PacketId);
                    ReceivePing(packet);
                    break;

                case PacketType.Pong:
                    LoggerRaw.Trace("[I] Pong {0}", BinaryPrimitives.ReadUInt16BigEndian(packet.Data));
                    ReceivePong(packet);
                    break;

                case PacketType.Ack:
                    LoggerRaw.Debug("[I] Acking: {0}", BinaryPrimitives.ReadUInt16BigEndian(packet.Data));
                    packet = ReceiveAck(packet);
                    break;

                case PacketType.AckLow: break;

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

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

                if (packet != null)
                {
                    return(packet);
                }
            }
        }