public void Dispose() { if (_nonceStream != null) { _nonceStream.Dispose(); _nonceStream = null; } }
private async Task ProcessReceivedDataAsync(ArraySegment <byte> buffer) { try { int bytesRead = 0; while (bytesRead < buffer.Count) { int startIndex = buffer.Offset + bytesRead; int bytesToRead = buffer.Count - bytesRead; if (_nextPacketBytesCountLeft == 0) { int tempLengthBytesToRead = PacketLengthBytesCount - _tempLengthBufferFill; tempLengthBytesToRead = (bytesToRead < tempLengthBytesToRead) ? bytesToRead : tempLengthBytesToRead; Buffer.BlockCopy(buffer.Array, startIndex, _tempLengthBuffer, _tempLengthBufferFill, tempLengthBytesToRead); _tempLengthBufferFill += tempLengthBytesToRead; if (_tempLengthBufferFill < PacketLengthBytesCount) { break; } startIndex += tempLengthBytesToRead; bytesToRead -= tempLengthBytesToRead; _tempLengthBufferFill = 0; _nextPacketBytesCountLeft = _tempLengthBuffer.ToInt32(); if (_nextPacketDataBuffer == null || _nextPacketDataBuffer.Length < _nextPacketBytesCountLeft || _nextPacketStreamer == null) { _nextPacketDataBuffer = new byte[_nextPacketBytesCountLeft]; _nextPacketStreamer = new TLStreamer(_nextPacketDataBuffer); } // Writing packet length. _nextPacketStreamer.Write(_tempLengthBuffer); _nextPacketBytesCountLeft -= PacketLengthBytesCount; bytesRead += PacketLengthBytesCount; } bytesToRead = bytesToRead > _nextPacketBytesCountLeft ? _nextPacketBytesCountLeft : bytesToRead; _nextPacketStreamer.Write(buffer.Array, startIndex, bytesToRead); bytesRead += bytesToRead; _nextPacketBytesCountLeft -= bytesToRead; if (_nextPacketBytesCountLeft > 0) { break; } var packet = new TcpTransportPacket(_nextPacketDataBuffer, 0, (int)_nextPacketStreamer.Position); await ProcessReceivedPacket(packet); _nextPacketBytesCountLeft = 0; _nextPacketStreamer.Position = 0; } } catch (Exception) { if (_nextPacketStreamer != null) { _nextPacketStreamer.Dispose(); _nextPacketStreamer = null; } _nextPacketDataBuffer = null; _nextPacketBytesCountLeft = 0; throw; } }
/// <summary> /// Processes incoming message bytes. /// </summary> /// <param name="messageBytes">Incoming bytes.</param> private async void ProcessIncomingMessageBytes(byte[] messageBytes) { TLStreamer streamer = null; try { Log.Debug("Processing incoming message."); streamer = new TLStreamer(messageBytes); if (messageBytes.Length == 4) { int error = streamer.ReadInt32(); Log.Debug("Received error code: {0}.", error); return; } else if (messageBytes.Length < 20) { throw new InvalidMessageException( string.Format("Invalid message length: {0} bytes. Expected to be at least 20 bytes for message or 4 bytes for error code.", messageBytes.Length)); } ulong authKeyId = streamer.ReadUInt64(); if (authKeyId == 0) { // Assume the message bytes has a plain (unencrypted) message. Log.Debug(string.Format("Auth key ID = 0x{0:X16}. Assume this is a plain (unencrypted) message.", authKeyId)); // Reading message ID. ulong messageId = streamer.ReadUInt64(); if (!IsIncomingMessageIdValid(messageId)) { throw new InvalidMessageException(string.Format("Message ID = 0x{0:X16} is invalid.", messageId)); } // Reading message data length. int messageDataLength = streamer.ReadInt32(); if (messageDataLength <= 0) { throw new InvalidMessageException("Message data length must be greater than zero."); } // Reading message data. var messageData = new byte[messageDataLength]; // TODO: consider reusing of byte arrays. int read = await streamer.ReadAsync(messageData, 0, messageDataLength, _connectionCancellationToken); if (read != messageDataLength) { throw new InvalidMessageException(string.Format("Actual message data length ({0}) is not as expected ({1}).", read, messageDataLength)); // TODO: read message data if read is less than expected. } // Notify in-messages subject. var message = new PlainMessage(messageId, messageData); Log.Debug(string.Format("Received plain message. Message ID = 0x{0:X16}. Message data length: {1} bytes.", messageId, messageDataLength)); _inMessages.OnNext(message); } else { // Assume the stream has an encrypted message. Log.Debug(string.Format("Auth key ID = 0x{0:X16}. Assume this is encrypted message.", authKeyId)); if (!IsEncryptionSupported) { Log.Debug("Encryption is not supported by this connection."); return; } var message = new EncryptedMessage(_authKey, messageBytes, Sender.Server, _hashServices, _encryptionServices); Log.Debug(string.Format("Received encrypted message. Message ID = 0x{0:X16}. Message data length: {1} bytes.", message.MessageId, message.MessageDataLength)); _inMessages.OnNext(message); } } catch (Exception e) { Log.Error(e, "Failed to receive a message."); } finally { if (streamer != null) { streamer.Dispose(); } } }