internal MercuryPacket Receive(NetworkStream a, CancellationToken cts) { using (recvLock.Lock(cts)) { recvCipher.nonce(Utils.toByteArray(recvNonce)); Interlocked.Increment(ref recvNonce); var headerBytes = new byte[3]; a.ReadComplete(headerBytes, 0, headerBytes.Length); recvCipher.decrypt(headerBytes); var cmd = headerBytes[0]; var payloadLength = (short)((headerBytes[1] << 8) | (headerBytes[2] & 0xFF)); var payloadBytes = new byte[payloadLength]; a.ReadComplete(payloadBytes, 0, payloadBytes.Length); recvCipher.decrypt(payloadBytes); var mac = new byte[4]; a.ReadComplete(mac, 0, mac.Length); var expectedMac = new byte[4]; recvCipher.finish(expectedMac); return(new MercuryPacket((MercuryPacket.Type)cmd, payloadBytes)); } }
private void SendUnchecked(MercuryPacket.Type cmd, byte[] payload, CancellationToken cts) { using (sendLock.Lock(cts)) { var a = conn.Result.NetworkStream; var payloadLengthAsByte = BitConverter.GetBytes((short)payload.Length).Reverse().ToArray(); using var yetAnotherBuffer = new MemoryStream(3 + payload.Length); yetAnotherBuffer.WriteByte((byte)cmd); yetAnotherBuffer.Write(payloadLengthAsByte, 0, payloadLengthAsByte.Length); yetAnotherBuffer.Write(payload, 0, payload.Length); sendCipher.nonce(Utils.toByteArray(sendNonce)); Interlocked.Increment(ref sendNonce); var bufferBytes = yetAnotherBuffer.ToArray(); sendCipher.encrypt(bufferBytes); var fourBytesBuffer = new byte[4]; sendCipher.finish(fourBytesBuffer); a.Write(bufferBytes, 0, bufferBytes.Length); a.Write(fourBytesBuffer, 0, fourBytesBuffer.Length); a.Flush(); } }