/// <summary> /// Decrypts the packet data /// </summary> public void Decrypt(Span <byte> data) { if (!RecvCipher.Handshaken) { var pr = new BinaryReader(new MemoryStream(MapleCipher.Handshake(data).ToArray(), false), Encoding.ASCII); var version = pr.ReadInt16(); var subVersionLength = pr.ReadInt16(); var subVersion = new string(pr.ReadChars(subVersionLength)); var siv = pr.ReadUInt32(); var riv = pr.ReadUInt32(); var serverType = pr.ReadByte(); SendCipher.SetIv(siv); RecvCipher.SetIv(riv); HandshakeFinished?.Invoke(siv, riv, version, subVersion, serverType); } else { if (!RecvCipher.CheckHeader(data, !ToClient)) { throw new InvalidOperationException($"Packet header mismatch Size:{data.Length}"); } var decrypted = RecvCipher.Decrypt(data); if (decrypted.Length == 0) { return; } PacketFinished?.Invoke(decrypted.ToArray()); } }
/// <summary> /// Add binary data to the buffer /// </summary> /// <param name="data">data buffer to add</param> /// <param name="offset">data offset</param> /// <param name="length">data length</param> public void AddData(byte[] data, int offset, int length) { if (IsWaiting) { if (length < HeaderSize) // Packet error, not enough header byte { return; } PacketReader pr = new PacketReader(data); int packetLength = pr.ReadInt(); // Get packet length DataBuffer = new byte[packetLength + HeaderSize]; // Create new buffer with length = packetLength + HeaderSize Buffer.BlockCopy(data, 0, DataBuffer, 0, length); // Copy data to general buffer if (length < packetLength + HeaderSize) // If packet length including header size is smaller than actual size, wait for the remaining { WaitForData = packetLength + HeaderSize - length; IsWaiting = false; } else // Finish processing packet { PacketFinished?.Invoke(DataBuffer); // Invoke Finish handler } } else // Remaining received { Buffer.BlockCopy(data, 0, DataBuffer, DataBuffer.Length - WaitForData, length); // Add data in this buffer to general buffer WaitForData -= length; // Decrease data amount to be waited if (WaitForData <= 0) // Received all data { if (PacketFinished != null) { PacketFinished(DataBuffer); } IsWaiting = true; // Reset processor } } }