Ejemplo n.º 1
0
        /// <summary>
        ///     Sends encrypted message.
        /// </summary>
        /// <param name="messageData">Message inner data.</param>
        /// <param name="isContentRelated">
        ///     Indicates wether message is content-related message requiring an explicit
        ///     acknowledgment.
        /// </param>
        public void SendEncryptedMessage(byte[] messageData, bool isContentRelated = true)
        {
            ThrowIfDiconnected();

            if (!IsEncryptionSupported)
            {
                throw new InvalidOperationException("Encryption is not supported. Setup encryption first by calling SetupEncryption() method.");
            }

            var message = new EncryptedMessage(_authKey, _salt, _sessionId, GetNextMessageId(), GetNextSeqNo(isContentRelated), messageData, Sender.Client, _hashServices,
                                               _encryptionServices);

            SendMessage(message);
        }
Ejemplo n.º 2
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();
                }
            }
        }