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); }
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); }
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)); } }
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); }
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); } }
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); } }