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); }
/// <summary>TS3 uses a new key and nonce for each packet sent and received. This method generates and caches these.</summary> /// <param name="fromServer">True if the packet is from server to client, false for client to server.</param> /// <param name="packetId">The id of the packet, host order.</param> /// <param name="generationId">Each time the packetId reaches 65535 the next packet will go on with 0 and the generationId will be increased by 1.</param> /// <param name="packetType">The packetType.</param> /// <returns>A tuple of (key, nonce)</returns> private Tuple <byte[], byte[]> GetKeyNonce(bool fromServer, ushort packetId, uint generationId, PacketType packetType) { if (!CryptoInitComplete) { return(DummyKeyAndNonceTuple); } // only the lower 4 bits are used for the real packetType byte packetTypeRaw = (byte)packetType; int cacheIndex = packetTypeRaw * (fromServer ? 1 : 2); if (cachedKeyNonces[cacheIndex] == null || cachedKeyNonces[cacheIndex].Item3 != generationId) { // this part of the key/nonce is fixed by the message direction and packetType byte[] tmpToHash = new byte[26]; if (fromServer) { tmpToHash[0] = 0x30; } else { tmpToHash[0] = 0x31; } tmpToHash[1] = packetTypeRaw; Array.Copy(BitConverter.GetBytes(NetUtil.H2N(generationId)), 0, tmpToHash, 2, 4); Array.Copy(ivStruct, 0, tmpToHash, 6, 20); var result = Hash256It(tmpToHash); cachedKeyNonces[cacheIndex] = new Tuple <byte[], byte[], uint>(result.Slice(0, 16).ToArray(), result.Slice(16, 16).ToArray(), generationId); } byte[] key = new byte[16]; byte[] nonce = new byte[16]; Array.Copy(cachedKeyNonces[cacheIndex].Item1, 0, key, 0, 16); Array.Copy(cachedKeyNonces[cacheIndex].Item2, 0, nonce, 0, 16); // finally the first two bytes get xor'd with the packet id key[0] ^= (byte)((packetId >> 8) & 0xFF); key[1] ^= (byte)((packetId) & 0xFF); return(new Tuple <byte[], byte[]>(key, nonce)); }
public void SendAudioGroupWhisper(ReadOnlySpan <byte> data, Codec codec, GroupWhisperType type, GroupWhisperTarget target, ulong targetId = 0) { // [X,X,Y,N,M,U,U,U,U,U,U,U,U,DATA] // > X is a ushort in H2N order of an own audio packet counter // it seems it can be the same as the packet counter so we will let the packethandler do it. // > Y is the codec byte (see Enum) // > N is a byte, specifying the GroupWhisperType // > M is a byte, specifying the GroupWhisperTarget // > U is a ulong in H2N order for the targeted channelId or groupId (0 if not applicable) byte[] tmpBuffer = new byte[data.Length + 13]; tmpBuffer[2] = (byte)codec; tmpBuffer[3] = (byte)type; tmpBuffer[4] = (byte)target; NetUtil.H2N(targetId, tmpBuffer, 5); data.CopyTo(new Span <byte>(tmpBuffer, 13)); packetHandler.AddOutgoingPacket(tmpBuffer, PacketType.VoiceWhisper, PacketFlags.Newprotocol); }
private void ReceivePing(IncomingPacket packet) { byte[] pongData = new byte[2]; NetUtil.H2N(packet.PacketId, pongData, 0); AddOutgoingPacket(pongData, PacketType.Pong); }
public void BuildHeader() { NetUtil.H2N(PacketId, Header, 0); NetUtil.H2N(ClientId, Header, 2); Header[4] = PacketTypeFlagged; }
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); } }
private void AddOutgoingPacket(OutgoingPacket packet, PacketFlags flags = PacketFlags.None) { 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); break; case PacketType.Command: case PacketType.CommandLow: packet.PacketFlags |= PacketFlags.Newprotocol; packetAckManager.Add(packet.PacketId, packet); break; case PacketType.Ping: lastSentPingId = packet.PacketId; packet.PacketFlags |= PacketFlags.Unencrypted; break; case PacketType.Pong: packet.PacketFlags |= PacketFlags.Unencrypted; break; case PacketType.Ack: case PacketType.AckLow: break; // Nothing to do case PacketType.Init1: packet.PacketFlags |= PacketFlags.Unencrypted; packetAckManager.Add(packet.PacketId, packet); break; default: throw Util.UnhandledDefault(packet.PacketType); } #if DIAGNOSTICS && DIAG_RAWPKG if (packet.PacketType != PacketType.Ping && packet.PacketType != PacketType.Pong) { Console.WriteLine($"[OT] {packet}"); } #endif ts3Crypt.Encrypt(packet); packet.FirstSendTime = Util.Now; SendRaw(packet); } }
internal byte[] ProcessInit1(byte[] data) { const int versionLen = 4; const int initTypeLen = 1; if (data == null) { var sendData = new byte[versionLen + initTypeLen + 4 + 4 + 8]; Array.Copy(Initversion, 0, sendData, 0, versionLen); // initVersion sendData[versionLen] = 0x00; // initType NetUtil.H2N(Util.UnixNow, sendData, versionLen + initTypeLen); // 4byte timestamp for (int i = 0; i < 4; i++) { sendData[i + versionLen + initTypeLen + 4] = (byte)Util.Random.Next(0, 256); // 4byte random } return(sendData); } if (data.Length < initTypeLen) { return(null); } int type = data[0]; if (type == 1) { var sendData = new byte[versionLen + initTypeLen + 16 + 4]; Array.Copy(Initversion, 0, sendData, 0, versionLen); // initVersion sendData[versionLen] = 0x02; // initType Array.Copy(data, 1, sendData, versionLen + initTypeLen, 20); return(sendData); } else if (type == 3) { byte[] alphaBytes = new byte[10]; Util.Random.NextBytes(alphaBytes); var alpha = Convert.ToBase64String(alphaBytes); string initAdd = Ts3Command.BuildToString("clientinitiv", new ICommandPart[] { new CommandParameter("alpha", alpha), new CommandParameter("omega", Identity.PublicKeyString), new CommandParameter("ip", string.Empty) }); var textBytes = Util.Encoder.GetBytes(initAdd); // Prepare solution int level = NetUtil.N2Hint(data, initTypeLen + 128); byte[] y = SolveRsaChallange(data, initTypeLen, level); // Copy bytes for this result: [Version..., InitType..., data..., y..., text...] var sendData = new byte[versionLen + initTypeLen + 232 + 64 + textBytes.Length]; // Copy this.Version Array.Copy(Initversion, 0, sendData, 0, versionLen); // Write InitType sendData[versionLen] = 0x04; // Copy data Array.Copy(data, initTypeLen, sendData, versionLen + initTypeLen, 232); // Copy y Array.Copy(y, 0, sendData, versionLen + initTypeLen + 232 + (64 - y.Length), y.Length); // Copy text Array.Copy(textBytes, 0, sendData, versionLen + initTypeLen + 232 + 64, textBytes.Length); return(sendData); } else { return(null); } }
public override void BuildHeader() { NetUtil.H2N(PacketId, Header, 0); Header[2] = PacketTypeFlagged; }