/// <summary>
        /// The thread main of the message reading and processing thread.
        /// </summary>
        private void MessageReader()
        {
            try
            {
                object messageEnvelope = null;

                while ((messageEnvelope = _messageObjectStream.Read()) != null)
                {
                    MessageBase message = GetMessageFromEnvelope(messageEnvelope);

                    if (message == null)
                    {
                        this.Error("Received unexpected message envelope of type '{0}' -> ignore it.", messageEnvelope.GetType().Name);
                        continue;
                    }

                    if (message.GetType().Name == "KeepAliveRequest")
                    {
                        var response = new KeepAliveResponseEnvelope()
                        {
                            KeepAliveResponse = new KeepAliveResponse()
                            {
                                Id          = message.Id,
                                Source      = message.Destination,
                                Destination = message.Source
                            }
                        };

                        _messageObjectStream.Write(response);
                        continue;
                    }

                    lock (_activeInterceptors)
                    {
                        foreach (var interceptor in _activeInterceptors)
                        {
                            if (interceptor.InterceptMessage(message))
                            {
                                message = null;
                                break;
                            }
                        }
                    }

                    if ((message != null) && (this.MessageArrived != null))
                    {
                        this.Trace(
                            "MessageArrived event is raised: a new message arrived that is not handled by any pending message interceptors.");
                        this.MessageArrived(this, new MessageArrivedArgs()
                        {
                            Message = message
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                this.Error("Reading and dispatching messages failed!", ex);
            }
            finally
            {
                lock (_activeInterceptors)
                {
                    foreach (var interceptor in _activeInterceptors)
                    {
                        interceptor.Cancel();
                    }
                }

                _threadDownEvent.Set();
            }

            try
            {
                if (this.MessageStreamDown != null)
                {
                    this.MessageStreamDown(this, null);
                }
            }
            catch (Exception ex)
            {
                this.Error("Throwing final message stream down event failed!", ex);
            }
        }
        /// <summary>
        /// Reads the next Mosaic message from the underlying connection and returns it. This method will block until a new Mosaic message
        /// has been read, the converter stream has been cancelled or an error occurred.
        /// </summary>
        /// <returns>
        /// Read Mosaic message if successful; <c>null</c> otherwise.
        /// </returns>
        public MosaicMessage Read()
        {
            while (true)
            {
                IMessageConversion message = null;

                while (message == null)
                {
                    object readMessage = _objectStream.Read();

                    if (readMessage == null)
                    {
                        return(null);
                    }

                    if (readMessage.GetType() == typeof(KeepAliveRequestEnvelope))
                    {
                        var request  = (KeepAliveRequestEnvelope)readMessage;
                        var response = new KeepAliveResponseEnvelope()
                        {
                            KeepAliveResponse = new KeepAliveResponse()
                            {
                                Id          = request.KeepAliveRequest.Id,
                                Source      = _configuration.SubscriberID,
                                Destination = request.KeepAliveRequest.Source
                            }
                        };

                        if (_objectStream.Write(response) == false)
                        {
                            this.Error("Sending keep alive response with ID '{0}' failed.", request.KeepAliveRequest.Id);
                            return(null);
                        }

                        continue;
                    }

                    if (readMessage.GetType() == typeof(KeepAliveResponseEnvelope))
                    {
                        var response = (KeepAliveResponseEnvelope)readMessage;

                        if (TypeConverter.ConvertInt(response.KeepAliveResponse.Id) == _keepAliveID)
                        {
                            System.Threading.Interlocked.Exchange(ref _lastKeepAlive, 0);
                            continue;
                        }

                        this.Error("Received orphan keep alive response with ID '{0}' but expected ID '{1}'.",
                                   response.KeepAliveResponse.Id, _keepAliveID);
                        return(null);
                    }

                    message = readMessage as IMessageConversion;

                    if (message == null)
                    {
                        this.Error("Ignored unsupported message of type '{0}'.", readMessage.GetType().FullName);
                        continue;
                    }
                }

                var mosaicMessage = message.ToMosaicMessage(this);

                if (mosaicMessage != null)
                {
                    mosaicMessage.TenantID = _tenantID;
                }

                return(mosaicMessage);
            }
        }