/// <summary>
        /// Sends the message to the remote host.
        /// Returns a response if the corresponding Security Session is established and the initial message is not one-way.
        /// </summary>
        /// <param name="message">Message to be sent or a null reference (if there is a queued message).</param>
        protected override void InternalSend(Message message)
        {
            SharedMemoryConnection sharedMemoryConnection = null;
            string uri      = message.Recipient.Url;
            bool   isServer = false;

            // get the connection
            lock (message.Recipient.PersistentConnectionEstablishingLock)
            {
                switch (message.Recipient.GenuinePersistentConnectionState)
                {
                case GenuinePersistentConnectionState.NotEstablished:
                    if (message.Recipient.Url == null)
                    {
                        throw GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.Uri);
                    }
                    message.Recipient.GenuinePersistentConnectionState = GenuinePersistentConnectionState.Opened;
                    break;

                case GenuinePersistentConnectionState.Accepted:
                    isServer = true;
                    uri      = message.Recipient.Uri;
                    break;
                }

                // if it's possible to establish a connection to the remote host
                if (!isServer)
                {
                    sharedMemoryConnection = this._persistent[uri] as SharedMemoryConnection;

                    if (sharedMemoryConnection == null)
                    {
                        // try to establish a persistent connection
                        string remoteUri;
                        int    remoteHostUniqueIdentifier;
                        sharedMemoryConnection = this.LowLevel_OpenConnection(message.Recipient, this.Local.Uri, out remoteUri, out remoteHostUniqueIdentifier);

                        // update remote host info
                        message.Recipient.UpdateUri(remoteUri, remoteHostUniqueIdentifier);
                        sharedMemoryConnection.Remote = message.Recipient;
                        sharedMemoryConnection.SignalState(GenuineEventType.GeneralConnectionEstablished, null, null);

                        // OK, connection established
                        this._persistent[uri] = sharedMemoryConnection;
                        this.Connection_InitiateReceiving(sharedMemoryConnection);
                    }
                }
                else
                {
                    // remote host is a client and if there is no connection to it, it's unreachable
                    sharedMemoryConnection = this._persistent[uri] as SharedMemoryConnection;
                    if (sharedMemoryConnection == null)
                    {
                        throw GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.Uri);
                    }
                }
            }

            this.SendSync(message, sharedMemoryConnection);
        }
        /// <summary>
        /// Releases all resources related to the specified connection.
        /// </summary>
        /// <param name="exception">The reason.</param>
        /// <param name="sharedMemoryConnection">The connection.</param>
        private void ConnectionFailed(Exception exception, SharedMemoryConnection sharedMemoryConnection)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            try
            {
                sharedMemoryConnection.IsValid = false;

                // LOG:
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0)
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "SharedMemoryConnectionManager.ConnectionFailed",
                                               LogMessageType.ConnectionFailed, exception, null, sharedMemoryConnection.Remote, null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                               null, null,
                                               sharedMemoryConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                               "Connection has failed.");
                }

                // unregister the connection
                if (sharedMemoryConnection.Remote.GenuinePersistentConnectionState == GenuinePersistentConnectionState.Accepted)
                {
                    this._persistent.Remove(sharedMemoryConnection.Remote.Uri);
                }
                else
                {
                    this._persistent.Remove(sharedMemoryConnection.Remote.Url);
                }

                // release all resources
                this.ITransportContext.KnownHosts.ReleaseHostResources(sharedMemoryConnection.Remote, exception);
                sharedMemoryConnection.ReleaseUnmanagedResources();
                sharedMemoryConnection.SignalState(GenuineEventType.GeneralConnectionClosed, exception, null);
            }
            catch (Exception ex)
            {
                // LOG:
                if (binaryLogWriter != null)
                {
                    binaryLogWriter.WriteImplementationWarningEvent("SharedMemoryConnectionManager.ConnectionFailed",
                                                                    LogMessageType.CriticalError, ex,
                                                                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                    "Unexpected exception inside the SharedMemoryClientConnectionManager.ConnectionFailed method. Most likely, something must be fixed.");
                }
            }
        }
        /// <summary>
        /// Accepts the incoming connection.
        /// </summary>
        /// <param name="shareName">The name of the share.</param>
        /// <param name="protocolVersion">The version of the protocol supported by the remote host.</param>
        internal void Connection_AcceptConnection(string shareName, byte protocolVersion)
        {
            try
            {
                // accept the connection
                string remoteUri = null;
                int    remoteHostUniqueIdentifier;
                SharedMemoryConnection connection = this.LowLevel_AcceptConnection_1(shareName, this.Local.Uri, protocolVersion, out remoteUri, out remoteHostUniqueIdentifier);

                connection.Remote = this.ITransportContext.KnownHosts[remoteUri];
                connection.Remote.ProtocolVersion = protocolVersion;
                connection.Remote.GenuinePersistentConnectionState = GenuinePersistentConnectionState.Accepted;
                connection.Remote.UpdateUri(remoteUri, remoteHostUniqueIdentifier);

                this._persistent[remoteUri] = connection;
                connection.SignalState(GenuineEventType.GeneralConnectionEstablished, null, null);

                // and process incoming messages
                this.Connection_InitiateReceiving(connection);
            }
            catch (Exception ex)
            {
                // LOG:
                BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
                if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0)
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "SharedMemoryConnectionManager.Connection_AcceptConnection",
                                               LogMessageType.ConnectionEstablished, ex, null, null, null,
                                               GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                               null, null,
                                               -1, 0, 0, 0, null, null, null, null,
                                               "The connection from the remote host \"{0}\" has been refused.", shareName);
                }

                this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GeneralListenerFailure, ex, null, shareName));
            }
        }
        /// <summary>
        /// Releases all resources related to the specified connection.
        /// </summary>
        /// <param name="exception">The reason.</param>
        /// <param name="sharedMemoryConnection">The connection.</param>
        private void ConnectionFailed(Exception exception, SharedMemoryConnection sharedMemoryConnection)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            try
            {
                sharedMemoryConnection.IsValid = false;

                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "SharedMemoryConnectionManager.ConnectionFailed",
                        LogMessageType.ConnectionFailed, exception, null, sharedMemoryConnection.Remote, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        null, null,
                        sharedMemoryConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                        "Connection has failed.");
                }

                // unregister the connection
                if (sharedMemoryConnection.Remote.GenuinePersistentConnectionState == GenuinePersistentConnectionState.Accepted)
                    this._persistent.Remove(sharedMemoryConnection.Remote.Uri);
                else
                    this._persistent.Remove(sharedMemoryConnection.Remote.Url);

                // release all resources
                this.ITransportContext.KnownHosts.ReleaseHostResources(sharedMemoryConnection.Remote, exception);
                sharedMemoryConnection.ReleaseUnmanagedResources();
                sharedMemoryConnection.SignalState(GenuineEventType.GeneralConnectionClosed, exception, null);
            }
            catch(Exception ex)
            {
                // LOG:
                if ( binaryLogWriter != null)
                {
                    binaryLogWriter.WriteImplementationWarningEvent("SharedMemoryConnectionManager.ConnectionFailed",
                        LogMessageType.CriticalError, ex,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        "Unexpected exception inside the SharedMemoryClientConnectionManager.ConnectionFailed method. Most likely, something must be fixed.");
                }
            }
        }