public void GetKillCursorsMessageEncoder_should_return_a_KillCursorsMessageBinaryEncoder()
 {
     using (var stream = new MemoryStream())
     {
         var encoderFactory = new BinaryMessageEncoderFactory(stream, null);
         var encoder = encoderFactory.GetKillCursorsMessageEncoder();
         encoder.Should().BeOfType<KillCursorsMessageBinaryEncoder>();
     }
 }
 public void GetInsertMessageEncoder_should_return_a_InsertMessageBinaryEncoder()
 {
     using (var stream = new MemoryStream())
     {
         var encoderFactory = new BinaryMessageEncoderFactory(stream, null);
         var encoder = encoderFactory.GetInsertMessageEncoder<BsonDocument>(BsonDocumentSerializer.Instance);
         encoder.Should().BeOfType<InsertMessageBinaryEncoder<BsonDocument>>();
     }
 }
            public IByteBuffer EncodeMessages(CancellationToken cancellationToken)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var serializationStopwatch = Stopwatch.StartNew();
                var outputBufferChunkSource = new OutputBufferChunkSource(BsonChunkPool.Default);
                var buffer = new MultiChunkBuffer(outputBufferChunkSource);
                using (var stream = new ByteBufferStream(buffer, ownsBuffer: false))
                {
                    var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings);
                    foreach (var message in _messages)
                    {
                        if (message.ShouldBeSent == null || message.ShouldBeSent())
                        {
                            var encoder = message.GetEncoder(encoderFactory);
                            encoder.WriteMessage(message);
                            message.WasSent = true;
                        }

                        // Encoding messages includes serializing the
                        // documents, so encoding message could be expensive
                        // and worthy of us honoring cancellation here.
                        cancellationToken.ThrowIfCancellationRequested();
                    }
                    buffer.Length = (int)stream.Length;
                    buffer.MakeReadOnly();
                }
                serializationStopwatch.Stop();
                _serializationDuration = serializationStopwatch.Elapsed;

                return buffer;
            }
            public ResponseMessage DecodeMessage(IByteBuffer buffer, IMessageEncoderSelector encoderSelector, CancellationToken cancellationToken)
            {
                cancellationToken.ThrowIfCancellationRequested();

                _stopwatch.Stop();
                _networkDuration = _stopwatch.Elapsed;

                ResponseMessage message;
                _stopwatch.Restart();
                using (var stream = new ByteBufferStream(buffer, ownsBuffer: false))
                {
                    var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings);
                    var encoder = encoderSelector.GetEncoder(encoderFactory);
                    message = (ResponseMessage)encoder.ReadMessage();
                }
                _stopwatch.Stop();
                _deserializationDuration = _stopwatch.Elapsed;

                return message;
            }
        private void ProcessReplyMessage(CommandState state, ResponseMessage message, IByteBuffer buffer, ConnectionId connectionId, MessageEncoderSettings encoderSettings)
        {
            state.Stopwatch.Stop();
            bool disposeOfDocuments = false;
            var replyMessage = message as ReplyMessage<RawBsonDocument>;
            if (replyMessage == null)
            {
                // ReplyMessage is generic, which means that we can't use it here, so, we need to use a different one...
                using (var stream = new ByteBufferStream(buffer, ownsBuffer: false))
                {
                    var encoderFactory = new BinaryMessageEncoderFactory(stream, encoderSettings);
                    replyMessage = (ReplyMessage<RawBsonDocument>)encoderFactory
                        .GetReplyMessageEncoder(RawBsonDocumentSerializer.Instance)
                        .ReadMessage();
                    disposeOfDocuments = true;
                }
            }

            try
            {
                if (replyMessage.CursorNotFound ||
                    replyMessage.QueryFailure ||
                    (state.ExpectedResponseType != ExpectedResponseType.Query && replyMessage.Documents.Count == 0))
                {
                    var queryFailureDocument = replyMessage.QueryFailureDocument;
                    if (__securitySensitiveCommands.Contains(state.CommandName))
                    {
                        queryFailureDocument = new BsonDocument();
                    }
                    if (_failedEvent != null)
                    {
                        _failedEvent(new CommandFailedEvent(
                            state.CommandName,
                            new MongoCommandException(
                                connectionId,
                                string.Format("{0} command failed", state.CommandName),
                                null,
                                queryFailureDocument),
                            state.OperationId,
                            replyMessage.ResponseTo,
                            connectionId,
                            state.Stopwatch.Elapsed));
                    }
                }
                else
                {
                    switch (state.ExpectedResponseType)
                    {
                        case ExpectedResponseType.Command:
                            ProcessCommandReplyMessage(state, replyMessage, connectionId);
                            break;
                        case ExpectedResponseType.GLE:
                            ProcessGLEReplyMessage(state, replyMessage, connectionId);
                            break;
                        case ExpectedResponseType.Query:
                            ProcessQueryReplyMessage(state, replyMessage, connectionId);
                            break;
                    }
                }
            }
            finally
            {
                if (disposeOfDocuments && replyMessage.Documents != null)
                {
                    replyMessage.Documents.ForEach(d => d.Dispose());
                }
            }
        }
        public async Task SendMessagesAsync(IEnumerable<RequestMessage> messages, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken)
        {
            Ensure.IsNotNull(messages, nameof(messages));
            ThrowIfDisposedOrNotOpen();

            var messagesToSend = messages.ToList();
            var requestIds = messagesToSend.Select(x => x.RequestId).ToList();
            try
            {
                if (_sendingMessagesEventHandler != null)
                {
                    _sendingMessagesEventHandler(new ConnectionSendingMessagesEvent(_connectionId, requestIds, EventContext.OperationId));
                }

                cancellationToken.ThrowIfCancellationRequested();

                var stopwatch = Stopwatch.StartNew();
                var outputBufferChunkSource = new OutputBufferChunkSource(BsonChunkPool.Default);
                using (var buffer = new MultiChunkBuffer(outputBufferChunkSource))
                {
                    using (var stream = new ByteBufferStream(buffer, ownsBuffer: false))
                    {
                        var encoderFactory = new BinaryMessageEncoderFactory(stream, messageEncoderSettings);
                        foreach (var message in messagesToSend)
                        {
                            if (message.ShouldBeSent == null || message.ShouldBeSent())
                            {
                                var encoder = message.GetEncoder(encoderFactory);
                                encoder.WriteMessage(message);
                                message.WasSent = true;
                            }

                            // Encoding messages includes serializing the
                            // documents, so encoding message could be expensive
                            // and worthy of us honoring cancellation here.
                            cancellationToken.ThrowIfCancellationRequested();
                        }
                        buffer.Length = (int)stream.Length;
                        buffer.MakeReadOnly();
                    }

                    var serializationDuration = stopwatch.Elapsed;

                    if (_commandEventHelper.ShouldCallBeforeSending)
                    {
                        _commandEventHelper.BeforeSending(
                            messages,
                            _connectionId,
                            buffer,
                            messageEncoderSettings,
                            stopwatch);
                    }

                    var stopwatchCheckPoint = stopwatch.Elapsed;

                    await SendBufferAsync(buffer, cancellationToken).ConfigureAwait(false);

                    var networkDuration = stopwatch.Elapsed - stopwatchCheckPoint;

                    if (_commandEventHelper.ShouldCallAfterSending)
                    {
                        _commandEventHelper.AfterSending(messages, _connectionId);
                    }

                    if (_sentMessagesEventHandler != null)
                    {
                        _sentMessagesEventHandler(new ConnectionSentMessagesEvent(_connectionId, requestIds, buffer.Length, networkDuration, serializationDuration, EventContext.OperationId));
                    }
                }
            }
            catch (Exception ex)
            {
                if (_commandEventHelper.ShouldCallErrorSending)
                {
                    _commandEventHelper.ErrorSending(messages, _connectionId, ex);
                }

                if (_failedSendingMessagesEvent != null)
                {
                    _failedSendingMessagesEvent(new ConnectionSendingMessagesFailedEvent(_connectionId, requestIds, ex, EventContext.OperationId));
                }

                throw;
            }
        }
        public async Task<ResponseMessage> ReceiveMessageAsync(
            int responseTo,
            IMessageEncoderSelector encoderSelector,
            MessageEncoderSettings messageEncoderSettings,
            CancellationToken cancellationToken)
        {
            Ensure.IsNotNull(encoderSelector, nameof(encoderSelector));
            ThrowIfDisposedOrNotOpen();

            try
            {
                if (_receivingMessageEventHandler != null)
                {
                    _receivingMessageEventHandler(new ConnectionReceivingMessageEvent(_connectionId, responseTo, EventContext.OperationId));
                }

                ResponseMessage reply;
                var stopwatch = Stopwatch.StartNew();
                using (var buffer = await ReceiveBufferAsync(responseTo, cancellationToken).ConfigureAwait(false))
                {
                    stopwatch.Stop();
                    var networkDuration = stopwatch.Elapsed;

                    cancellationToken.ThrowIfCancellationRequested();

                    stopwatch.Restart();
                    using (var stream = new ByteBufferStream(buffer))
                    {
                        var encoderFactory = new BinaryMessageEncoderFactory(stream, messageEncoderSettings);
                        var encoder = encoderSelector.GetEncoder(encoderFactory);
                        reply = (ResponseMessage)encoder.ReadMessage();
                    }
                    stopwatch.Stop();

                    if (_commandEventHelper.ShouldCallAfterReceiving)
                    {
                        _commandEventHelper.AfterReceiving(reply, buffer, _connectionId, messageEncoderSettings);
                    }

                    if (_receivedMessageEventHandler != null)
                    {
                        _receivedMessageEventHandler(new ConnectionReceivedMessageEvent(_connectionId, responseTo, buffer.Length, networkDuration, stopwatch.Elapsed, EventContext.OperationId));
                    }
                }

                return reply;
            }
            catch (Exception ex)
            {
                if (_commandEventHelper.ShouldCallErrorReceiving)
                {
                    _commandEventHelper.ErrorReceiving(responseTo, _connectionId, ex);
                }

                if (_failedReceivingMessageEventHandler != null)
                {
                    _failedReceivingMessageEventHandler(new ConnectionReceivingMessageFailedEvent(_connectionId, responseTo, ex, EventContext.OperationId));
                }

                throw;
            }
        }
예제 #8
0
        private void ProcessReplyMessage(CommandState state, ResponseMessage message, IByteBuffer buffer, ConnectionId connectionId, MessageEncoderSettings encoderSettings)
        {
            state.Stopwatch.Stop();
            bool disposeOfDocuments = false;
            var  replyMessage       = message as ReplyMessage <RawBsonDocument>;

            if (replyMessage == null)
            {
                // ReplyMessage is generic, which means that we can't use it here, so, we need to use a different one...
                using (var stream = new ByteBufferStream(buffer, ownsBuffer: false))
                {
                    var encoderFactory = new BinaryMessageEncoderFactory(stream, encoderSettings);
                    replyMessage = (ReplyMessage <RawBsonDocument>)encoderFactory
                                   .GetReplyMessageEncoder(RawBsonDocumentSerializer.Instance)
                                   .ReadMessage();
                    disposeOfDocuments = true;
                }
            }

            try
            {
                if (replyMessage.CursorNotFound ||
                    replyMessage.QueryFailure ||
                    (state.ExpectedResponseType != ExpectedResponseType.Query && replyMessage.Documents.Count == 0))
                {
                    var queryFailureDocument = replyMessage.QueryFailureDocument;
                    if (__securitySensitiveCommands.Contains(state.CommandName))
                    {
                        queryFailureDocument = new BsonDocument();
                    }
                    if (_failedEvent != null)
                    {
                        _failedEvent(new CommandFailedEvent(
                                         state.CommandName,
                                         new MongoCommandException(
                                             connectionId,
                                             string.Format("{0} command failed", state.CommandName),
                                             null,
                                             queryFailureDocument),
                                         state.OperationId,
                                         replyMessage.ResponseTo,
                                         connectionId,
                                         state.Stopwatch.Elapsed));
                    }
                }
                else
                {
                    switch (state.ExpectedResponseType)
                    {
                    case ExpectedResponseType.Command:
                        ProcessCommandReplyMessage(state, replyMessage, connectionId);
                        break;

                    case ExpectedResponseType.GLE:
                        ProcessGLEReplyMessage(state, replyMessage, connectionId);
                        break;

                    case ExpectedResponseType.Query:
                        ProcessQueryReplyMessage(state, replyMessage, connectionId);
                        break;
                    }
                }
            }
            finally
            {
                if (disposeOfDocuments && replyMessage.Documents != null)
                {
                    replyMessage.Documents.ForEach(d => d.Dispose());
                }
            }
        }
        private TCommandResult ProcessReply(ConnectionId connectionId, ReplyMessage <RawBsonDocument> reply)
        {
            if (reply.NumberReturned == 0)
            {
                throw new MongoCommandException(connectionId, "Command returned no documents.", _command);
            }
            if (reply.NumberReturned > 1)
            {
                throw new MongoCommandException(connectionId, "Command returned multiple documents.", _command);
            }
            if (reply.QueryFailure)
            {
                var failureDocument = reply.QueryFailureDocument;
                throw ExceptionMapper.Map(connectionId, failureDocument) ?? new MongoCommandException(connectionId, "Command failed.", _command, failureDocument);
            }

            using (var rawDocument = reply.Documents[0])
            {
                if (!rawDocument.GetValue("ok", false).ToBoolean())
                {
                    var materializedDocument = new BsonDocument(rawDocument);
                    var commandName          = _command.GetElement(0).Name;
                    if (commandName == "$query")
                    {
                        commandName = _command["$query"].AsBsonDocument.GetElement(0).Name;
                    }

                    var notPrimaryOrNodeIsRecoveringException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, materializedDocument, "errmsg");
                    if (notPrimaryOrNodeIsRecoveringException != null)
                    {
                        throw notPrimaryOrNodeIsRecoveringException;
                    }

                    string    message;
                    BsonValue errmsgBsonValue;
                    if (materializedDocument.TryGetValue("errmsg", out errmsgBsonValue) && errmsgBsonValue.IsString)
                    {
                        var errmsg = errmsgBsonValue.ToString();
                        message = string.Format("Command {0} failed: {1}.", commandName, errmsg);
                    }
                    else
                    {
                        message = string.Format("Command {0} failed.", commandName);
                    }

                    var mappedException = ExceptionMapper.Map(connectionId, materializedDocument);
                    if (mappedException != null)
                    {
                        throw mappedException;
                    }

                    throw new MongoCommandException(connectionId, message, _command, materializedDocument);
                }

                using (var stream = new ByteBufferStream(rawDocument.Slice, ownsByteBuffer: false))
                {
                    var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings);
                    var encoder        = (ReplyMessageBinaryEncoder <TCommandResult>)encoderFactory.GetReplyMessageEncoder <TCommandResult>(_resultSerializer);
                    using (var reader = encoder.CreateBinaryReader())
                    {
                        var context = BsonDeserializationContext.CreateRoot(reader);
                        return(_resultSerializer.Deserialize(context));
                    }
                }
            }
        }
예제 #10
0
        private TCommandResult ProcessReply(ConnectionId connectionId, ReplyMessage <RawBsonDocument> reply)
        {
            if (reply.NumberReturned == 0)
            {
                throw new MongoCommandException(connectionId, "Command returned no documents.", _command);
            }
            if (reply.NumberReturned > 1)
            {
                throw new MongoCommandException(connectionId, "Command returned multiple documents.", _command);
            }
            if (reply.QueryFailure)
            {
                var failureDocument = reply.QueryFailureDocument;
                throw ExceptionMapper.Map(connectionId, failureDocument) ?? new MongoCommandException(connectionId, "Command failed.", _command, failureDocument);
            }

            using (var rawDocument = reply.Documents[0])
            {
                var binaryReaderSettings = new BsonBinaryReaderSettings();
                if (_messageEncoderSettings != null)
                {
                    binaryReaderSettings.Encoding = _messageEncoderSettings.GetOrDefault <UTF8Encoding>(MessageEncoderSettingsName.ReadEncoding, Utf8Encodings.Strict);
#pragma warning disable 618
                    if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
                    {
                        binaryReaderSettings.GuidRepresentation = _messageEncoderSettings.GetOrDefault <GuidRepresentation>(MessageEncoderSettingsName.GuidRepresentation, GuidRepresentation.CSharpLegacy);
                    }
#pragma warning restore 618
                }
                ;

                BsonValue clusterTime;
                if (rawDocument.TryGetValue("$clusterTime", out clusterTime))
                {
                    // note: we are assuming that _session is an instance of ClusterClockAdvancingClusterTime
                    // and that calling _session.AdvanceClusterTime will have the side effect of advancing the cluster's ClusterTime also
                    var materializedClusterTime = ((RawBsonDocument)clusterTime).Materialize(binaryReaderSettings);
                    _session.AdvanceClusterTime(materializedClusterTime);
                }
                BsonValue operationTime;
                if (rawDocument.TryGetValue("operationTime", out operationTime))
                {
                    _session.AdvanceOperationTime(operationTime.AsBsonTimestamp);
                }

                if (!rawDocument.GetValue("ok", false).ToBoolean())
                {
                    var materializedDocument = rawDocument.Materialize(binaryReaderSettings);

                    var commandName = _command.GetElement(0).Name;
                    if (commandName == "$query")
                    {
                        commandName = _command["$query"].AsBsonDocument.GetElement(0).Name;
                    }

                    var notPrimaryOrNodeIsRecoveringException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, _command, materializedDocument, "errmsg");
                    if (notPrimaryOrNodeIsRecoveringException != null)
                    {
                        throw notPrimaryOrNodeIsRecoveringException;
                    }

                    string    message;
                    BsonValue errmsgBsonValue;
                    if (materializedDocument.TryGetValue("errmsg", out errmsgBsonValue) && errmsgBsonValue.IsString)
                    {
                        var errmsg = errmsgBsonValue.ToString();
                        message = string.Format("Command {0} failed: {1}.", commandName, errmsg);
                    }
                    else
                    {
                        message = string.Format("Command {0} failed.", commandName);
                    }

                    var mappedException = ExceptionMapper.Map(connectionId, materializedDocument);
                    if (mappedException != null)
                    {
                        throw mappedException;
                    }

                    throw new MongoCommandException(connectionId, message, _command, materializedDocument);
                }

                if (rawDocument.Contains("writeConcernError"))
                {
                    var materializedDocument = rawDocument.Materialize(binaryReaderSettings);
                    var writeConcernError    = materializedDocument["writeConcernError"].AsBsonDocument;
                    var message            = writeConcernError.AsBsonDocument.GetValue("errmsg", null)?.AsString;
                    var writeConcernResult = new WriteConcernResult(materializedDocument);
                    throw new MongoWriteConcernException(connectionId, message, writeConcernResult);
                }

                using (var stream = new ByteBufferStream(rawDocument.Slice, ownsBuffer: false))
                {
                    var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings);
                    var encoder        = (ReplyMessageBinaryEncoder <TCommandResult>)encoderFactory.GetReplyMessageEncoder <TCommandResult>(_resultSerializer);
                    using (var reader = encoder.CreateBinaryReader())
                    {
                        var context = BsonDeserializationContext.CreateRoot(reader);
                        return(_resultSerializer.Deserialize(context));
                    }
                }
            }
        }
 public void GetDeleteMessageEncoder_should_return_a_DeleteMessageBinaryEncoder()
 {
     using (var stream = new MemoryStream())
     using (var binaryWriter = new BsonBinaryWriter(stream))
     {
         var encoderFactory = new BinaryMessageEncoderFactory(null, binaryWriter);
         var encoder = encoderFactory.GetDeleteMessageEncoder();
         encoder.Should().BeOfType<DeleteMessageBinaryEncoder>();
     }
 }
 public void GetReplyMessageEncoder_should_return_a_ReplyMessageBinaryEncoder()
 {
     using (var stream = new MemoryStream())
     using (var binaryWriter = new BsonBinaryWriter(stream))
     {
         var encoderFactory = new BinaryMessageEncoderFactory(null, binaryWriter);
         var encoder = encoderFactory.GetReplyMessageEncoder<BsonDocument>(BsonDocumentSerializer.Instance);
         encoder.Should().BeOfType<ReplyMessageBinaryEncoder<BsonDocument>>();
     }
 }
예제 #13
0
        public async Task SendMessagesAsync(IEnumerable <RequestMessage> messages, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken)
        {
            Ensure.IsNotNull(messages, nameof(messages));
            ThrowIfDisposedOrNotOpen();

            var messagesToSend = messages.ToList();
            var requestIds     = messagesToSend.Select(x => x.RequestId).ToList();

            try
            {
                if (_sendingMessagesEventHandler != null)
                {
                    _sendingMessagesEventHandler(new ConnectionSendingMessagesEvent(_connectionId, requestIds, EventContext.OperationId));
                }

                cancellationToken.ThrowIfCancellationRequested();

                var stopwatch = Stopwatch.StartNew();
                var outputBufferChunkSource = new OutputBufferChunkSource(BsonChunkPool.Default);
                using (var buffer = new MultiChunkBuffer(outputBufferChunkSource))
                {
                    using (var stream = new ByteBufferStream(buffer, ownsBuffer: false))
                    {
                        var encoderFactory = new BinaryMessageEncoderFactory(stream, messageEncoderSettings);
                        foreach (var message in messagesToSend)
                        {
                            if (message.ShouldBeSent == null || message.ShouldBeSent())
                            {
                                var encoder = message.GetEncoder(encoderFactory);
                                encoder.WriteMessage(message);
                                message.WasSent = true;
                            }

                            // Encoding messages includes serializing the
                            // documents, so encoding message could be expensive
                            // and worthy of us honoring cancellation here.
                            cancellationToken.ThrowIfCancellationRequested();
                        }
                        buffer.Length = (int)stream.Length;
                        buffer.MakeReadOnly();
                    }

                    var serializationDuration = stopwatch.Elapsed;

                    if (_commandEventHelper.ShouldCallBeforeSending)
                    {
                        _commandEventHelper.BeforeSending(
                            messages,
                            _connectionId,
                            buffer,
                            messageEncoderSettings,
                            stopwatch);
                    }

                    var stopwatchCheckPoint = stopwatch.Elapsed;

                    await SendBufferAsync(buffer, cancellationToken).ConfigureAwait(false);

                    var networkDuration = stopwatch.Elapsed - stopwatchCheckPoint;

                    if (_commandEventHelper.ShouldCallAfterSending)
                    {
                        _commandEventHelper.AfterSending(messages, _connectionId);
                    }

                    if (_sentMessagesEventHandler != null)
                    {
                        _sentMessagesEventHandler(new ConnectionSentMessagesEvent(_connectionId, requestIds, buffer.Length, networkDuration, serializationDuration, EventContext.OperationId));
                    }
                }
            }
            catch (Exception ex)
            {
                if (_commandEventHelper.ShouldCallErrorSending)
                {
                    _commandEventHelper.ErrorSending(messages, _connectionId, ex);
                }

                if (_failedSendingMessagesEvent != null)
                {
                    _failedSendingMessagesEvent(new ConnectionSendingMessagesFailedEvent(_connectionId, requestIds, ex, EventContext.OperationId));
                }

                throw;
            }
        }
예제 #14
0
        public async Task <ResponseMessage> ReceiveMessageAsync(
            int responseTo,
            IMessageEncoderSelector encoderSelector,
            MessageEncoderSettings messageEncoderSettings,
            CancellationToken cancellationToken)
        {
            Ensure.IsNotNull(encoderSelector, nameof(encoderSelector));
            ThrowIfDisposedOrNotOpen();

            try
            {
                if (_receivingMessageEventHandler != null)
                {
                    _receivingMessageEventHandler(new ConnectionReceivingMessageEvent(_connectionId, responseTo, EventContext.OperationId));
                }

                ResponseMessage reply;
                var             stopwatch = Stopwatch.StartNew();
                using (var buffer = await ReceiveBufferAsync(responseTo, cancellationToken).ConfigureAwait(false))
                {
                    stopwatch.Stop();
                    var networkDuration = stopwatch.Elapsed;

                    cancellationToken.ThrowIfCancellationRequested();

                    stopwatch.Restart();
                    using (var stream = new ByteBufferStream(buffer))
                    {
                        var encoderFactory = new BinaryMessageEncoderFactory(stream, messageEncoderSettings);
                        var encoder        = encoderSelector.GetEncoder(encoderFactory);
                        reply = (ResponseMessage)encoder.ReadMessage();
                    }
                    stopwatch.Stop();

                    if (_commandEventHelper.ShouldCallAfterReceiving)
                    {
                        _commandEventHelper.AfterReceiving(reply, buffer, _connectionId, messageEncoderSettings);
                    }

                    if (_receivedMessageEventHandler != null)
                    {
                        _receivedMessageEventHandler(new ConnectionReceivedMessageEvent(_connectionId, responseTo, buffer.Length, networkDuration, stopwatch.Elapsed, EventContext.OperationId));
                    }
                }

                return(reply);
            }
            catch (Exception ex)
            {
                if (_commandEventHelper.ShouldCallErrorReceiving)
                {
                    _commandEventHelper.ErrorReceiving(responseTo, _connectionId, ex);
                }

                if (_failedReceivingMessageEventHandler != null)
                {
                    _failedReceivingMessageEventHandler(new ConnectionReceivingMessageFailedEvent(_connectionId, responseTo, ex, EventContext.OperationId));
                }

                throw;
            }
        }