예제 #1
0
 public void Dispose()
 {
     if (_nonceStream != null)
     {
         _nonceStream.Dispose();
         _nonceStream = null;
     }
 }
예제 #2
0
        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;
            }
        }
예제 #3
0
        /// <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();
                }
            }
        }