/// <summary>
        /// Puts the message into the message list.
        /// </summary>
        /// <param name="message">The message.</param>
        public void PutMessage(Message message)
        {
            lock (this)
            {
                // release the current available message
                Message previousMessage = this._messages[this._head] as Message;
                if (previousMessage != null)
                    previousMessage.Dispose();

                this._messages [ this._head++ ] = message;
                if (this._head >= this._messages.Length)
                    this._head = 0;
            }
        }
        /// <summary>
        /// Starts sending the message through the specified connection.
        /// </summary>
        /// <param name="message">The message being sent.</param>
        /// <param name="tcpSocketInfo">The connection.</param>
        private void LowLevel_StartSending(Message message, TcpSocketInfo tcpSocketInfo)
        {
            // PING: prevent the ping
            if (tcpSocketInfo.GenuineConnectionType == GenuineConnectionType.Persistent)
                tcpSocketInfo.LastTimeContentWasSent = GenuineUtility.TickCount;

            if (tcpSocketInfo.AsyncSendStream == null)
            {
                tcpSocketInfo.AsyncSendStream = message.SerializedContent;
                if (tcpSocketInfo.ConnectionLevelSecurity != null && message.SerializedContent != Stream.Null)
                {
                    GenuineChunkedStream encryptedContentStream = new GenuineChunkedStream(true);
                    tcpSocketInfo.ConnectionLevelSecurity.Encrypt(tcpSocketInfo.AsyncSendStream, encryptedContentStream);
                    tcpSocketInfo.AsyncSendStream = encryptedContentStream;
                }
            }

            // initiate the sending
            tcpSocketInfo.Message = message;
            if (tcpSocketInfo.AsyncSendBuffer == null)
                tcpSocketInfo.AsyncSendBuffer = new byte[tcpSocketInfo.MaxSendSize];
            tcpSocketInfo.AsyncSendBufferCurrentPosition = 0;
            tcpSocketInfo.AsyncSendBufferSizeOfValidContent = HEADER_SIZE + GenuineUtility.TryToReadFromStream(tcpSocketInfo.AsyncSendStream, tcpSocketInfo.AsyncSendBuffer, HEADER_SIZE, tcpSocketInfo.AsyncSendBuffer.Length - HEADER_SIZE);
            tcpSocketInfo.AsyncSendBuffer[0] = MessageCoder.COMMAND_MAGIC_CODE;
            MessageCoder.WriteInt32(tcpSocketInfo.AsyncSendBuffer, 1, tcpSocketInfo.AsyncSendBufferSizeOfValidContent - HEADER_SIZE);
            tcpSocketInfo.AsyncSendBufferIsLastPacket = tcpSocketInfo.AsyncSendBufferSizeOfValidContent < tcpSocketInfo.AsyncSendBuffer.Length - HEADER_SIZE;
            tcpSocketInfo.AsyncSendBuffer[5] = tcpSocketInfo.AsyncSendBufferIsLastPacket ? (byte) 1 : (byte) 0;

            // LOG:
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0 )
            {
                binaryLogWriter.WriteTransportContentEvent(LogCategory.Transport, "TcpConnectionManager.LowLevel_StartSending",
                    LogMessageType.AsynchronousSendingStarted, null, tcpSocketInfo.Message, tcpSocketInfo.Remote,
                    binaryLogWriter[LogCategory.Transport] > 1 ? new MemoryStream(GenuineUtility.CutOutBuffer(tcpSocketInfo.AsyncSendBuffer, tcpSocketInfo.AsyncSendBufferCurrentPosition, tcpSocketInfo.AsyncSendBufferSizeOfValidContent - tcpSocketInfo.AsyncSendBufferCurrentPosition)) : null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    tcpSocketInfo.DbgConnectionId, tcpSocketInfo.AsyncSendBufferSizeOfValidContent - tcpSocketInfo.AsyncSendBufferCurrentPosition, tcpSocketInfo.Remote.PhysicalAddress.ToString(), null, null,
                    "The chunk is being sent asynchronously.");
            }

            AsyncThreadStarter.QueueTask(new Async_InitiateSocketSending(tcpSocketInfo.Socket, tcpSocketInfo.AsyncSendBuffer, tcpSocketInfo.AsyncSendBufferCurrentPosition, tcpSocketInfo.AsyncSendBufferSizeOfValidContent - tcpSocketInfo.AsyncSendBufferCurrentPosition, this._onEndSending, tcpSocketInfo));
            //			tcpSocketInfo.Socket.BeginSend(tcpSocketInfo.AsyncSendBuffer, tcpSocketInfo.AsyncSendBufferCurrentPosition, tcpSocketInfo.AsyncSendBufferSizeOfValidContent - tcpSocketInfo.AsyncSendBufferCurrentPosition, SocketFlags.None, this._onEndSending, tcpSocketInfo);
        }
        /// <summary>
        /// Puts down a record describing a general Genuine Channels event.
        /// </summary>
        /// <param name="logCategory">The category of the event.</param>
        /// <param name="author">The author.</param>
        /// <param name="type">The type of the event(Subcategory).</param>
        /// <param name="exception">The exception associated with the event.</param>
        /// <param name="message">The message associated with the event.</param>
        /// <param name="remote">The remote host participating in the event.</param>
        /// <param name="content">The content associated with the record.</param>
        /// <param name="sourceThreadId">The id of the thread where the invocation was made.</param>
        /// <param name="sourceThreadName">The name of the thread.</param>
        /// <param name="securitySession">The Security Session.</param>
        /// <param name="securitySessionName">The name of the Security Session</param>
        /// <param name="writeDispatcherSettings">A value indicating whether it is necessary to put down broadcast dispatcher's settings.</param>
        /// <param name="dispatcher">The broadcast dispatcher.</param>
        /// <param name="resultCollector">The broadcast result collector.</param>
        /// <param name="writeReceiverInfoSettings">A value indicating whether it is necessary to put down information about the specified broadcast recipient.</param>
        /// <param name="receiverInfo">The broadcast recipient.</param>
        /// <param name="string1">The first string that elaborates the current event.</param>
        /// <param name="string2">The second string that elaborates the current event.</param>
        /// <param name="description">The description of the event.</param>
        /// <param name="parameters">Parameters to the description.</param>
        public void WriteBroadcastEngineEvent(LogCategory logCategory, string author, LogMessageType type, Exception exception, 
            Message message, HostInformation remote, Stream content, int sourceThreadId, string sourceThreadName,
            SecuritySession securitySession, string securitySessionName,
            bool writeDispatcherSettings, Dispatcher dispatcher, ResultCollector resultCollector, bool writeReceiverInfoSettings,
            ReceiverInfo receiverInfo, string string1, string string2, string description, params object[] parameters)
        {
            if (dispatcher == null)
            {
                this.WriteImplementationWarningEvent("BinaryLogWriter.WriteBroadcastEngineEvent", LogMessageType.Error, null,
                    sourceThreadId, sourceThreadName, "The reference is null. Stack trace: " + Environment.StackTrace);
                return ;
            }

            lock (this._streamLock)
            {
                this.WriteRecordHeader(BinaryRecordVersion.TransportBroadcastEngineRecord, logCategory, type, author);
                this.WriteException( exception );

                this.WriteMessageSeqNo( message );
                this.WriteHostInformationId( remote );
                this.WriteBinaryContent( content );

                this.BinaryWriter.Write( (int) sourceThreadId);
                this.WriteString( sourceThreadName );

                this.WriteSecuritySessionId( securitySession );
                this.WriteString( securitySessionName );

                this.WriteResultCollectorId(resultCollector);
                this.WriteDispatcherSettings(writeDispatcherSettings, dispatcher);
                this.WriteReceiverInfo(writeReceiverInfoSettings, receiverInfo);

                this.WriteString( string1 );
                this.WriteString( string2 );
                this.WriteStringWithParameters( description, parameters);

                this.BinaryWriter.Flush();
            }
        }
 /// <summary>
 /// Sends the message via specific broadcast transport.
 /// </summary>
 /// <param name="message">The message being sent.</param>
 /// <param name="resultCollector">The Result Ñollector to gather results of the invocation.</param>
 public abstract void SendMessage(Message message, ResultCollector resultCollector);
        /// <summary>
        /// Sends a message to the remote host.
        /// </summary>
        /// <param name="message">The message to be sent.</param>
        public void Send(Message message)
        {
            #if TRIAL
            _messagesBeingSent[message.MessageId] = message;
            #endif

            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            try
            {
                using (new ReaderAutoLocker(this._disposeLock))
                {
                    if (this._disposed)
                        throw OperationException.WrapException(this._disposeReason);
                }

                SecuritySession session = null;

                if (this._disposed)
                    throw OperationException.WrapException(this._disposeReason);

                // get the security session descriptor
                if (message.SecuritySessionParameters == null)
                {
                    SecuritySessionParameters securitySessionParameters = SecuritySessionServices.GetCurrentSecurityContext();
                    if (securitySessionParameters == null)
                        securitySessionParameters = message.Recipient.SecuritySessionParameters;
                    if (securitySessionParameters == null)
                        securitySessionParameters = this.ITransportContext.SecuritySessionParameters;
                    if (securitySessionParameters == null)
                        securitySessionParameters = SecuritySessionServices.DefaultSecuritySession;
                    message.SecuritySessionParameters = securitySessionParameters;
                }

                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0 )
                    binaryLogWriter.WriteSecuritySessionParametersEvent("ConnectionManager.Send",
                        LogMessageType.SecuritySessionParametersAssembled, null, message, message.Recipient,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        message.SecuritySessionParameters,
                        "Security Session Parameters have been assembled.");

                // determine the type of sending
                message.IsSynchronous = (message.SecuritySessionParameters.Attributes & SecuritySessionAttributes.ForceSync) != 0 ||
                    (message.IsSynchronous && (message.SecuritySessionParameters.Attributes & SecuritySessionAttributes.ForceAsync) == 0);

                // the time until invocation times out
                if (! message.FinishTime_Initialized)
                {
                    TimeSpan messageTimeout = message.SecuritySessionParameters.Timeout;
                    if (messageTimeout == TimeSpan.MinValue)
                        messageTimeout = (TimeSpan) this.ITransportContext.IParameterProvider[GenuineParameter.InvocationTimeout];
                    message.FinishTime = GenuineUtility.GetTimeout(messageTimeout);

                    message.FinishTime_Initialized = true;
                }

                // checks whether the message has been already processed by Security Session
                if (message.SerializedContent == null)
                {
                    session = message.Recipient.GetSecuritySession(message.SecuritySessionParameters.Name, this.ITransportContext.IKeyStore);
                    if (! session.IsEstablished)
                    {
                        if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0 )
                            binaryLogWriter.WriteEvent(LogCategory.Security, "ConnectionManager.Send",
                                LogMessageType.SecuritySessionHasNotBeenEstablishedYet, null, message, message.Recipient, null,
                                GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                session, session.Name, -1, 0, 0, 0, null, null, null, null,
                                "The requested Security Session is not established.");

                        session.InitiateEstablishingSecuritySession(message.SecuritySessionParameters);

                        // if it's a sync sending, then wait until security session will be established
                        if ( message.IsSynchronous )
                        {
                            int timeSpanToWait = GenuineUtility.GetMillisecondsLeft(message.FinishTime);
                            if (timeSpanToWait <= 0)
                                throw GenuineExceptions.Get_Send_ServerDidNotReply();

                            // wait until Security Session will be established or a failure will be detected
                            int firedEvent = 0;
                            if (message.CancelSending != null)
                                firedEvent = WaitHandle.WaitAny(new WaitHandle[] { session.IsEstablishedEvent, session.Failed, message.CancelSending }, timeSpanToWait, false);
                            else
                                firedEvent = WaitHandle.WaitAny(new WaitHandle[] { session.IsEstablishedEvent, session.Failed }, timeSpanToWait, false);

                            if (firedEvent == WaitHandle.WaitTimeout)
                                throw GenuineExceptions.Get_Send_ServerDidNotReply();

                            // analyze the problem, if any
                            Exception exception = session.ReasonOfFailure;
                            if (firedEvent == 1)
                            {
                                if (exception != null)
                                    throw OperationException.WrapException(exception);
                                else
                                    throw GenuineExceptions.Get_Security_ContextWasNotEstablished(session.Name);
                            }

                            // if the message has been cancelled, let the sender to understand the reason
                            if (firedEvent == 2)
                                return ;
                        }
                        else if (! session.IsEstablished)
                        {
                            // it's async and SS still isn't established
                            session.PutMessageToAwaitingQueue(message);
                            return;
                        }
                    }
                }

                // if serialization is necessary
                if (message.SerializedContent == null)
                {
                    // serialize the message
                    GenuineChunkedStream serializedMessageStream = new GenuineChunkedStream(false);
                    MessageCoder.Serialize(serializedMessageStream, message, (message.SecuritySessionParameters.Attributes & SecuritySessionAttributes.EnableCompression) != 0);

                    // save the name of the Security Session
                    GenuineChunkedStream resultStream = new GenuineChunkedStream(false);
                    BinaryWriter writer = new BinaryWriter(resultStream);
                    writer.Write(message.SecuritySessionParameters.Name);
                    session.Encrypt(serializedMessageStream, resultStream);
                    message.SerializedContent = resultStream;

                    // LOG: put down the log record
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0 )
                    {
                        binaryLogWriter.WriteEvent(LogCategory.Security, "ConnectionManager.Send",
                            LogMessageType.SecuritySessionApplied, null, message, message.Recipient,
                            binaryLogWriter[LogCategory.Security] > 1 ? message.SerializedContent : null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, session,
                            session.Name, -1, 0, 0, 0, null, null, null, null,
                            "The message has been processed by the established Security Session.");
                    }
                }

            #if TRIAL
                if (message.MessageId > 3005)
                    throw GenuineExceptions.Get_Channel_TrialConditionExceeded("The maximum number of messages restriction has been exceeded. You can not send more than 3000 messages using TRIAL version.");
            #endif

                message.Sender = this.Local;
                this.InternalSend(message);
            }
            catch(Exception ex)
            {
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0 )
                    binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "ConnectionManager.Send",
                        LogMessageType.Error, ex, message, message.Recipient, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        null, null, -1, 0, 0, 0, null, null, null, null,
                        "An exception occurred while processing the message.");

                throw;
            }
        }
        /// <summary>
        /// Establishes a connection to the remote host.
        /// </summary>
        /// <param name="remote">The HostInformation of the remote host.</param>
        /// <param name="genuineConnectionType">Type of the connection.</param>
        /// <param name="localUri">Local URI.</param>
        /// <param name="localPort">Local port.</param>
        /// <param name="connectionName">The name of the connection or a null reference.</param>
        /// <param name="remoteUri">Remote URI.</param>
        /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param>
        /// <returns>A connection.</returns>
        internal TcpSocketInfo LowLevel_OpenConnection(HostInformation remote, GenuineConnectionType genuineConnectionType, string localUri, int localPort, string connectionName, out string remoteUri, out int remoteHostUniqueIdentifier)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            using (new ReaderAutoLocker(this._disposeLock))
            {
                if (this._disposed)
                    throw OperationException.WrapException(this._disposeReason);
            }

            remoteUri = null;
            Stream inputStream = null;
            Stream outputStream = null;
            remoteHostUniqueIdentifier = 0;
            string url = remote.Url;

            // parse provided url and fetch a port and IP address
            int portNumber;
            string hostName = GenuineUtility.SplitToHostAndPort(url, out portNumber);

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.LowLevel_OpenConnection",
                    LogMessageType.ConnectionEstablishing, null, null, remote, null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                    -1, 0, 0, 0, null, null, null, null,
                    "The connection is being established to {0}.", hostName);
            }

            Socket socket = null;

            // the time we should finish connection establishing before
            int timeout = GenuineUtility.GetTimeout( (TimeSpan) this.ITransportContext.IParameterProvider[GenuineParameter.ConnectTimeout] );
            using (ConnectionEstablishingClosure connectionEstablishingClosure = new ConnectionEstablishingClosure(hostName, portNumber, this.ITransportContext.IParameterProvider))
            {
                connectionEstablishingClosure.StartOperation();
                if (! connectionEstablishingClosure.Completed.WaitOne( GenuineUtility.GetMillisecondsLeft(timeout), false))
                    throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(url, "Timeout expired.");

                if (connectionEstablishingClosure.Exception != null)
                    throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(url, connectionEstablishingClosure.Exception.Message);

                socket = connectionEstablishingClosure.CompleteOperation();
            }

            if (! socket.Connected)
                throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(url, "Socket.Connected property is false after connecting.");

            if (connectionName == null)
                connectionName = "$/__GC/" + hostName;
            TcpSocketInfo tcpSocketInfo = new TcpSocketInfo(socket, this.ITransportContext, connectionName
            #if DEBUG
                ,"Opened connection"
            #endif
                );
            tcpSocketInfo.GenuineConnectionType = genuineConnectionType;

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
            {
                binaryLogWriter.WriteConnectionParameterEvent(LogCategory.Connection, "TcpConnectionManager.LowLevel_OpenConnection",
                    LogMessageType.ConnectionParameters, null, remote, this.ITransportContext.IParameterProvider,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, tcpSocketInfo.DbgConnectionId,
                    "The connection is being established to \"{0}\".", hostName);
            }

            // send protocol version and the type of the connection
            Message message = new Message(null, null, -1, new TransportHeaders(), Stream.Null);
            message.FinishTime = timeout;
            message.SerializedContent = MessageCoder.SerializeConnectionHeader(MessageCoder.PROTOCOL_VERSION, genuineConnectionType, tcpSocketInfo.ConnectionName).BaseStream;
            LowLevel_SendSync(message, tcpSocketInfo);
            tcpSocketInfo.MessagesSentSynchronously.ReleaseAllMessages();

            // get connection-level SS
            string connectionLevelSSName = null;
            switch(genuineConnectionType)
            {
                case GenuineConnectionType.Persistent:
                    connectionLevelSSName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForPersistentConnections] as string;
                    break;

                case GenuineConnectionType.Named:
                    connectionLevelSSName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForNamedConnections] as string;
                    break;

                case GenuineConnectionType.Invocation:
                    connectionLevelSSName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForInvocationConnections] as string;
                    break;
            }

            SecuritySession securitySession = null;
            if (connectionLevelSSName != null)
                securitySession = this.ITransportContext.IKeyStore.GetKey(connectionLevelSSName).CreateSecuritySession(connectionLevelSSName, null);

            // establish it
            if (securitySession != null && ! securitySession.IsEstablished)
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.LowLevel_OpenConnection",
                        LogMessageType.ConnectionSecurityIsEstablished, null, null, tcpSocketInfo.Remote, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, securitySession, connectionLevelSSName,
                        tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                        "The Connection Level Security Session is being established.");
                }

                bool firstPass = true;
                for ( ; ; )
                {
                    inputStream = Stream.Null;

                    try
                    {
                        // prepare streams
                        if (! firstPass)
                            inputStream = this.LowLevel_ReadSync(tcpSocketInfo, timeout, false);
                        else
                            firstPass = false;

                        outputStream = securitySession.EstablishSession(inputStream, true);

                        if (outputStream == null)
                            break;

                        // send a packet to the remote host
                        message = new Message(null, null, -1, new TransportHeaders(), Stream.Null);
                        message.FinishTime = timeout;
                        message.SerializedContent = outputStream;
                        LowLevel_SendSync(message, tcpSocketInfo);
                        tcpSocketInfo.MessagesSentSynchronously.ReleaseAllMessages();

                        if (securitySession.IsEstablished)
                            break;
                    }
                    finally
                    {
                        if (inputStream != null)
                            inputStream.Close();
                        if (outputStream != null)
                            outputStream.Close();
                    }
                }
            }

            tcpSocketInfo.ConnectionLevelSecurity = securitySession;

            // now send connection info through the established connection
            using (GenuineChunkedStream serializedLocalInfo = new GenuineChunkedStream(false))
            {
                // serialize local info
                BinaryWriter binaryWriter = new BinaryWriter(serializedLocalInfo);
                binaryWriter.Write((string) localUri);

                // 2.5.2 fix
                //				binaryWriter.Write((int) localPort);
                binaryWriter.Write((int) -1);
                binaryWriter.Write((byte) genuineConnectionType);
                binaryWriter.Write((int) remote.LocalHostUniqueIdentifier);

                // and send it
                message = new Message(null, null, -1, new TransportHeaders(), Stream.Null);
                message.FinishTime = timeout;
                message.SerializedContent = serializedLocalInfo;
                LowLevel_SendSync(message, tcpSocketInfo);
                tcpSocketInfo.MessagesSentSynchronously.ReleaseAllMessages();

                // read remote info
                using (Stream remoteUriStream = this.LowLevel_ReadSync(tcpSocketInfo, timeout, false))
                {
                    BinaryReader binaryReader = new BinaryReader(remoteUriStream);
                    remoteUri = binaryReader.ReadString();
                    remoteHostUniqueIdentifier = binaryReader.ReadInt32();
                }
            }

            tcpSocketInfo.IsServer = false;
            return tcpSocketInfo;
        }
        /// <summary>
        /// Accepts an incoming TCP connection.
        /// </summary>
        /// <param name="socket">The socket.</param>
        /// <param name="localUri">URI of the local host.</param>
        /// <param name="remoteUri">Uri of the remote host.</param>
        /// <param name="remoteAddress">Address of the remote host.</param>
        /// <param name="connectionName">The name of the connection.</param>
        /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param>
        /// <param name="reasonOfStateLost">The reason why the remote host has lost its state (if it's happened).</param>
        /// <returns>An instance of the TcpSocketInfo class.</returns>
        internal TcpSocketInfo LowLevel_AcceptConnection(Socket socket, string localUri, out string remoteUri, out string remoteAddress, out string connectionName, out int remoteHostUniqueIdentifier, out Exception reasonOfStateLost)
        {
            using (new ReaderAutoLocker(this._disposeLock))
            {
                if (this._disposed)
                    throw OperationException.WrapException(this._disposeReason);
            }

            // set the remote end point and local end point
            using (new ThreadDataSlotKeeper(OccupiedThreadSlots.SocketDuringEstablishing, socket))
            {
                remoteUri = null;
                remoteAddress = null;
                remoteHostUniqueIdentifier = 0;

                Stream inputStream = null;
                Stream outputStream = null;

                // the time we should finish connection establishing before
                int timeout = GenuineUtility.GetTimeout( (TimeSpan) this.ITransportContext.IParameterProvider[GenuineParameter.ConnectTimeout]);

                // setup a socket
                LingerOption lingerOption = new LingerOption(true, 3);
                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);

                if ((bool) this.ITransportContext.IParameterProvider[GenuineParameter.TcpDisableNagling])
                    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);

                // create a connection
                TcpSocketInfo tcpSocketInfo = new TcpSocketInfo(socket, this.ITransportContext, null
            #if DEBUG
                    ,"Accepted connection"
            #endif
                    );

                // LOG:
                BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0 )
                    binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "TcpConnectionManager.LowLevel_AcceptConnection",
                        LogMessageType.ConnectionAccepting, null, null, null, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        null, null, tcpSocketInfo.DbgConnectionId, 0, 0, 0, socket.RemoteEndPoint.ToString(), socket.LocalEndPoint.ToString(), null, null,
                        "An inbound connection is being accepted. Remote end point: {0}.", socket.RemoteEndPoint.ToString());

                // receive and analyze protocol version and the type of the connection
                GenuineConnectionType genuineConnectionType;
                byte protocolVersion;
                using (Stream readingStream = this.LowLevel_ReadSync(tcpSocketInfo, timeout, false))
                {
                    BinaryReader binaryReader = new BinaryReader(readingStream);
                    MessageCoder.DeserializeConnectionHeader(binaryReader, out protocolVersion, out genuineConnectionType, out connectionName);
                }

                // define the connection logic
                tcpSocketInfo.GenuineConnectionType = genuineConnectionType;
                tcpSocketInfo.ConnectionName = connectionName;

                // get connection-level SS
                string connectionLevelSSName = null;
                switch (tcpSocketInfo.GenuineConnectionType)
                {
                    case GenuineConnectionType.Persistent:
                        connectionLevelSSName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForPersistentConnections] as string;
                        break;

                    case GenuineConnectionType.Named:
                        connectionLevelSSName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForNamedConnections] as string;
                        break;

                    case GenuineConnectionType.Invocation:
                        connectionLevelSSName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForInvocationConnections] as string;
                        break;
                }

                SecuritySession securitySession = null;
                if (connectionLevelSSName != null)
                    securitySession = this.ITransportContext.IKeyStore.GetKey(connectionLevelSSName).CreateSecuritySession(connectionLevelSSName, null);

                // establish a SS
                if (securitySession != null && ! securitySession.IsEstablished)
                {
                    // LOG:
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0 )
                        binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "TcpConnectionManager.LowLevel_AcceptConnection",
                            LogMessageType.ConnectionSecurityIsEstablished, null, null, null, null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                            securitySession, connectionLevelSSName, tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                            "The Connection Level Security Session must be established prior to connection is accepted.");

                    for ( ; ; )
                    {
                        inputStream = null;

                        try
                        {
                            // prepare streams
                            inputStream = this.LowLevel_ReadSync(tcpSocketInfo, timeout, false);
                            outputStream = securitySession.EstablishSession(inputStream, true);

                            if (outputStream == null)
                                break;

                            // send a packet to the remote host
                            Message message = new Message(null, null, -1, new TransportHeaders(), Stream.Null);
                            message.FinishTime = timeout;
                            message.SerializedContent = outputStream;
                            LowLevel_SendSync(message, tcpSocketInfo);
                            tcpSocketInfo.MessagesSentSynchronously.ReleaseAllMessages();

                            if (securitySession.IsEstablished)
                                break;
                        }
                        finally
                        {
                            if (inputStream != null)
                                inputStream.Close();
                            if (outputStream != null)
                                outputStream.Close();
                        }
                    }
                }

                tcpSocketInfo.ConnectionLevelSecurity = securitySession;

                // exchange with connection info
                int remotePort = 0;

                // read remote info
                using (Stream headerStream = this.LowLevel_ReadSync(tcpSocketInfo, timeout, false))
                {
                    //				this.SkipPacketHeader(headerStream, connectionLevelSSName);
                    BinaryReader binaryReader = new BinaryReader(headerStream);

                    remoteUri = binaryReader.ReadString();
                    remotePort = binaryReader.ReadInt32();
                    tcpSocketInfo.GenuineConnectionType = (GenuineConnectionType) binaryReader.ReadByte();

                    if (protocolVersion >= 0x1)
                        remoteHostUniqueIdentifier = binaryReader.ReadInt32();
                }

                HostInformation remote = this.ITransportContext.KnownHosts[remoteUri];
                remote.ProtocolVersion = protocolVersion;

                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteConnectionParameterEvent(LogCategory.Connection, "TcpConnectionManager.LowLevel_AcceptConnection",
                        LogMessageType.ConnectionParameters, null, remote, this.ITransportContext.IParameterProvider,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, tcpSocketInfo.DbgConnectionId,
                        "The connection is accepted. Protocol version: \"{0}\".", protocolVersion);
                }

                reasonOfStateLost = remote.UpdateUri(remoteUri, remoteHostUniqueIdentifier, tcpSocketInfo.GenuineConnectionType == GenuineConnectionType.Persistent);

                using (GenuineChunkedStream serializedLocalInfo = new GenuineChunkedStream(false))
                {
                    // serialize local info
                    BinaryWriter binaryWriter = new BinaryWriter(serializedLocalInfo);
                    binaryWriter.Write((string) localUri);

                    if (protocolVersion >= 0x1)
                        binaryWriter.Write((int) remote.LocalHostUniqueIdentifier);

                    // and send it
                    Message message = new Message(null, null, -1, new TransportHeaders(), Stream.Null);
                    message.FinishTime = timeout;
                    message.SerializedContent = serializedLocalInfo;
                    LowLevel_SendSync(message, tcpSocketInfo);
                    tcpSocketInfo.MessagesSentSynchronously.ReleaseAllMessages();
                }

                // build network address of the remote host
                if (remotePort > 0)
                {
                    IPEndPoint remoteHostIpEndPoint = (IPEndPoint) socket.RemoteEndPoint;
                    remoteAddress = "gtcp://" + remoteHostIpEndPoint.Address.ToString() + ":" + remotePort;
                }

                tcpSocketInfo.IsServer = true;
                return tcpSocketInfo;
            }
        }
        /// <summary>
        /// Sends the message to the remote host.
        /// Returns a response if corresponding Security Session parameters are set and 
        /// the initial message is not one-way.
        /// </summary>
        /// <param name="message">Message to be sent synchronously.</param>
        /// <param name="tcpSocketInfo">Socket connection.</param>
        private void SendSync(Message message, TcpSocketInfo tcpSocketInfo)
        {
            SyncMessageSlot syncMessageSlot = null;

            // try to acquire the read access
            bool sendAccessGranted = true;
            lock (tcpSocketInfo)
            {
                if (tcpSocketInfo.LockForSending)
                {
                    // wait until the current sending finishes
                    syncMessageSlot = new SyncMessageSlot();
                    tcpSocketInfo.MessageContainer.AddMessage(syncMessageSlot, false);
                    sendAccessGranted = false;
                }
                else
                    tcpSocketInfo.LockForSending = true;
            }

            if (! sendAccessGranted)
            {
                // allow SyncSinkStackProcess to influence on the message processing
                WaitHandle[] waitHandles = null;
                if (message.CancelSending != null)
                {
                    waitHandles = new WaitHandle[2];
                    waitHandles[1] = message.CancelSending;
                }
                else
                    waitHandles = new WaitHandle[1];
                waitHandles[0] = syncMessageSlot.ConnectionAvailable;

                // wait for any of events
                int milliseconds = GenuineUtility.GetMillisecondsLeft(message.FinishTime);
                if (milliseconds <= 0)
                    throw GenuineExceptions.Get_Send_ServerDidNotReply();

                int resultFlag = WaitHandle.WaitAny(waitHandles, milliseconds, false);
                if ( resultFlag == WaitHandle.WaitTimeout )
                {
                    lock (syncMessageSlot)
                    {
                        syncMessageSlot.IsValid = false;
                        // initiate sending of the next message
                        if (syncMessageSlot.TcpSocketInfo != null)
                            this.Pool_StartSending(syncMessageSlot.TcpSocketInfo);
                    }
                    throw GenuineExceptions.Get_Send_ServerDidNotReply();
                }

                if (resultFlag == 1)
                    throw GenuineExceptions.Get_Send_Timeout();

                // rethrow the exception
                if (syncMessageSlot.SyncWaitException != null)
                    throw OperationException.WrapException(syncMessageSlot.SyncWaitException);
                tcpSocketInfo = syncMessageSlot.TcpSocketInfo;
            }

            // send it
            this.LowLevel_SendSync(message, tcpSocketInfo);

            switch(tcpSocketInfo.GenuineConnectionType)
            {
                case GenuineConnectionType.Persistent:
                case GenuineConnectionType.Named:
                    message.IsResendAfterFail = false;
                    this.Pool_StartSending(tcpSocketInfo);
                    break;

                case GenuineConnectionType.Invocation:
                    // it's necessary to provide correct infomation, de bene esse
                    lock (tcpSocketInfo)
                    {
                        tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ClientReceiving;
                        tcpSocketInfo.Renew();
                    }

                    //					if (! tcpSocketInfo.IsServer && ! message.IsOneWay)
                    //					{
                    //						// read the response
                    //						using (Stream stream = this.LowLevel_ReadSync(tcpSocketInfo, message.FinishTime))
                    //							this.ITransportContext.IIncomingStreamHandler.HandleMessage(stream, tcpSocketInfo.Remote, tcpSocketInfo.GenuineConnectionType, tcpSocketInfo.ConnectionName, true, null, tcpSocketInfo.ConnectionLevelSecurity, null);
                    //					}

                    lock (tcpSocketInfo)
                    {
                        tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ClientAvailable;
                        tcpSocketInfo.Renew();
                    }
                    break;
            }
        }
 /// <summary>
 /// Puts down the message id.
 /// </summary>
 /// <param name="message">The message.</param>
 private void WriteMessageSeqNo(Message message)
 {
     this.BinaryWriter.Write( (bool) (message != null) );
     if (message != null)
         this.BinaryWriter.Write( (int) message.SeqNo );
 }
        /// <summary>
        /// Puts down a structure describing the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="isSent">Whether it will be executed on a remote host.</param>
        /// <param name="invocationTarget">The target of the invocation.</param>
        /// <param name="methodName">The name of the method.</param>
        private void WriteMessage(Message message, bool isSent, string invocationTarget, string methodName)
        {
            this.BinaryWriter.Write((int) message.SeqNo);
            this.BinaryWriter.Write((int) message.MessageId);
            this.BinaryWriter.Write((int) message.ReplyToId);
            this.BinaryWriter.Write( (bool) isSent);
            this.BinaryWriter.Write( (bool) message.IsOneWay);
            this.BinaryWriter.Write( (bool) message.IsSynchronous);
            this.BinaryWriter.Write( (int) message.GenuineMessageType);
            this.BinaryWriter.Write( (int) GenuineUtility.GetMillisecondsLeft(message.FinishTime));
            this.WriteString(invocationTarget);
            this.WriteString(methodName);

            // the size of the message
            if (message.Stream != null && message.Stream.CanSeek)
            {
                try
                {
                    this.BinaryWriter.Write( (int) message.Stream.Length);
                }
                catch
                {
                    this.BinaryWriter.Write( (int) 0);
                }
            }
            else
                this.BinaryWriter.Write( (int) 0);
        }
        /// <summary>
        /// Puts down a record describing the transport sending or receiving content actions.
        /// </summary>
        /// <param name="logCategory">The category of the event.</param>
        /// <param name="author">The author.</param>
        /// <param name="type">The type of the event(Subcategory).</param>
        /// <param name="exception">The exception associated with the event.</param>
        /// <param name="message">The message associated with the event.</param>
        /// <param name="remote">The remote host participating in the event.</param>
        /// <param name="content">The content associated with the record.</param>
        /// <param name="sourceThreadId">The id of the thread where the invocation was made.</param>
        /// <param name="sourceThreadName">The name of the thread.</param>
        /// <param name="connectionId">The identifier of the connection.</param>
        /// <param name="contentSize">The size of the content.</param>
        /// <param name="remoteHostAddress">The address of the remote host.</param>
        /// <param name="string1">The first string that elaborates the current event.</param>
        /// <param name="string2">The second string that elaborates the current event.</param>
        /// <param name="description">The description of the event.</param>
        /// <param name="parameters">Parameters to the description.</param>
        public void WriteTransportContentEvent(LogCategory logCategory, string author, LogMessageType type, Exception exception, 
            Message message, HostInformation remote, Stream content, int sourceThreadId, string sourceThreadName,
            int connectionId, int contentSize, string remoteHostAddress, string string1, string string2,
            string description, params object[] parameters)
        {
            lock (this._streamLock)
            {
                this.WriteRecordHeader(BinaryRecordVersion.TransportContentRecord, logCategory, type, author);
                this.WriteException( exception );

                this.WriteMessageSeqNo( message );
                this.WriteHostInformationId( remote );
                this.WriteBinaryContent( content );

                this.BinaryWriter.Write( (int) sourceThreadId);
                this.WriteString( sourceThreadName );

                this.BinaryWriter.Write( (int) connectionId );
                this.BinaryWriter.Write( (int) contentSize );
                this.WriteString( remoteHostAddress );

                this.WriteString( string1 );
                this.WriteString( string2 );
                this.WriteStringWithParameters( description, parameters);

                this.BinaryWriter.Flush();
            }
        }
        /// <summary>
        /// Puts down a record representing an event connected with the specified Security Session Parameters.
        /// </summary>
        /// <param name="author">The author.</param>
        /// <param name="type">The type of the event(Subcategory).</param>
        /// <param name="exception">The exception associated with the event.</param>
        /// <param name="message">The message associated with the event.</param>
        /// <param name="remote">The remote host participating in the event.</param>
        /// <param name="sourceThreadId">The id of the thread where the invocation was made.</param>
        /// <param name="sourceThreadName">The name of the thread.</param>
        /// <param name="securitySessionParameters">The Security Session Parameters.</param>
        /// <param name="description">The description of the event.</param>
        /// <param name="parameters">Parameters to the description.</param>
        public void WriteSecuritySessionParametersEvent(string author, LogMessageType type, Exception exception, 
            Message message, HostInformation remote, int sourceThreadId, string sourceThreadName,
            SecuritySessionParameters securitySessionParameters, string description, params object[] parameters)
        {
            if (message == null || securitySessionParameters == null)
            {
                this.WriteImplementationWarningEvent("BinaryLogWriter.WriteMessageCreatedEvent", LogMessageType.Error, null,
                    sourceThreadId, sourceThreadName, "The message or SSP is not provided. Stack trace: " + Environment.StackTrace);
                return ;
            }

            lock (this._streamLock)
            {
                this.WriteRecordHeader(BinaryRecordVersion.SecuritySessionParameters, LogCategory.Security, type, author);
                this.WriteException( exception );

                this.WriteMessageSeqNo(message);
                this.WriteHostInformationId(remote);

                this.BinaryWriter.Write( (int) sourceThreadId);
                this.WriteString( sourceThreadName );

                this.WriteSecuritySessionParameters( securitySessionParameters );
                this.WriteStringWithParameters( description, parameters);

                this.BinaryWriter.Flush();
            }
        }
        /// <summary>
        /// Puts down a record representing an event describing a Message Processing event.
        /// </summary>
        /// <param name="author">The author.</param>
        /// <param name="type">The type of the event(Subcategory).</param>
        /// <param name="exception">The exception associated with the event.</param>
        /// <param name="message">The message associated with the event.</param>
        /// <param name="isSent">Whether the message is a request to the remote service (or a response from that service).</param>
        /// <param name="remote">The remote host participating in the event.</param>
        /// <param name="content">The content associated with the record.</param>
        /// <param name="invocationTarget">The target of the request (a null reference if it's a response).</param>
        /// <param name="methodName">The name of the method.</param>
        /// <param name="sourceThreadId">The id of the thread where the invocation was made.</param>
        /// <param name="sourceThreadName">The name of the thread.</param>
        /// <param name="transportName">The name of the transport.</param>
        /// <param name="connectionId">The identifier of the connection.</param>
        /// <param name="clssId">The identifier of the Security Session used on the connection level.</param>
        /// <param name="clssName">The name of the Security Session used on the connection level.</param>
        /// <param name="ilssId">The identifier of the Security Session used on the invocation level.</param>
        /// <param name="ilssName">The name of the Security Session used on the invocation level.</param>
        /// <param name="description">The description of the event.</param>
        /// <param name="parameters">Parameters to the description.</param>
        public void WriteMessageCreatedEvent(string author, LogMessageType type, Exception exception, Message message, bool isSent,
            HostInformation remote, Stream content, string invocationTarget, string methodName, int sourceThreadId,
            string sourceThreadName, string transportName, int connectionId,
            int clssId, string clssName, int ilssId, string ilssName, string description, params object[] parameters)
        {
            if (message == null)
            {
                this.WriteImplementationWarningEvent("BinaryLogWriter.WriteMessageCreatedEvent", LogMessageType.Error, null,
                    sourceThreadId, sourceThreadName, "The message is not provided. Stack trace: " + Environment.StackTrace);
                return ;
            }

            lock (this._streamLock)
            {
                this.WriteRecordHeader(BinaryRecordVersion.MessageRecord, LogCategory.MessageProcessing, type, author);
                this.WriteException( exception );

                this.WriteMessage( message, isSent, invocationTarget, methodName );
                this.WriteHostInformationId( remote );
                this.WriteBinaryContent( content );

                this.BinaryWriter.Write( (int) sourceThreadId);
                this.WriteString( sourceThreadName );

                this.WriteString( transportName);
                this.BinaryWriter.Write( (int) connectionId );
                this.BinaryWriter.Write( (int) clssId );
                this.WriteString( clssName );
                this.BinaryWriter.Write( (int) ilssId );
                this.WriteString( ilssName );
                this.WriteStringWithParameters( description, parameters);

                this.BinaryWriter.Flush();
            }
        }
        /// <summary>
        /// Puts down a record describing a general Genuine Channels event.
        /// </summary>
        /// <param name="logCategory">The category of the event.</param>
        /// <param name="author">The author.</param>
        /// <param name="type">The type of the event(Subcategory).</param>
        /// <param name="exception">The exception associated with the event.</param>
        /// <param name="message">The message associated with the event.</param>
        /// <param name="remote">The remote host participating in the event.</param>
        /// <param name="content">The content associated with the record.</param>
        /// <param name="sourceThreadId">The id of the thread where the invocation was made.</param>
        /// <param name="sourceThreadName">The name of the thread.</param>
        /// <param name="securitySession">The Security Session.</param>
        /// <param name="securitySessionName">The name of the Security Session</param>
        /// <param name="connectionId">The identifier of the connection.</param>
        /// <param name="number1">An additional integer parameter.</param>
        /// <param name="number2">An additional integer parameter.</param>
        /// <param name="number3">An additional integer parameter.</param>
        /// <param name="string1">The first string that elaborates the current event.</param>
        /// <param name="string2">The second string that elaborates the current event.</param>
        /// <param name="string3">The third string that elaborates the current event.</param>
        /// <param name="string4">The fourth string that elaborates the current event.</param>
        /// <param name="description">The description of the event.</param>
        /// <param name="parameters">Parameters to the description.</param>
        public void WriteEvent(LogCategory logCategory, string author, LogMessageType type, Exception exception, 
            Message message, HostInformation remote, Stream content, int sourceThreadId, string sourceThreadName,
            SecuritySession securitySession, string securitySessionName,
            int connectionId, int number1, int number2, int number3, string string1, string string2, string string3, string string4, string description, params object[] parameters)
        {
            lock (this._streamLock)
            {
                this.WriteRecordHeader(BinaryRecordVersion.GeneralRecord, logCategory, type, author);
                this.WriteException( exception );

                this.WriteMessageSeqNo( message );
                this.WriteHostInformationId( remote );
                this.WriteBinaryContent( content );

                this.BinaryWriter.Write( (int) sourceThreadId);
                this.WriteString( sourceThreadName );

                this.WriteSecuritySessionId( securitySession );
                this.WriteString( securitySessionName );

                this.BinaryWriter.Write( (int) connectionId );

                this.BinaryWriter.Write( (int) number1 );
                this.BinaryWriter.Write( (int) number2 );
                this.BinaryWriter.Write( (int) number3 );

                this.WriteString( string1 );
                this.WriteString( string2 );
                this.WriteString( string3 );
                this.WriteString( string4 );

                this.WriteStringWithParameters( description, parameters);

                this.BinaryWriter.Flush();
            }
        }
        /// <summary>
        /// Sends the message to the remote host.
        /// Returns a response if corresponding Security Session is established and the initial message is not one-way.
        /// </summary>
        /// <param name="message">The message to be sent asynchronously.</param>
        /// <param name="tcpSocketInfo">The connection.</param>
        private void SendAsync(Message message, TcpSocketInfo tcpSocketInfo)
        {
            try
            {
                // try to acquire read access
                bool sendAccessGranted = true;
                lock (tcpSocketInfo)
                {
                    if (tcpSocketInfo.LockForSending)
                    {
                        sendAccessGranted = false;
                        tcpSocketInfo.MessageContainer.AddMessage(message, false);
                    }
                    else
                        tcpSocketInfo.LockForSending = true;
                }

                if (sendAccessGranted)
                {
                    tcpSocketInfo.Message = message;
                    tcpSocketInfo.AsyncSendStream = null;

                    // LOG:
                    BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0 )
                        binaryLogWriter.WriteEvent(LogCategory.Transport, "TcpConnectionManager.SendAsync",
                            LogMessageType.MessageIsSentAsynchronously, null, message, message.Recipient, null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                            tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity,
                            tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                            tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                            "The connection has been obtained and the message is being sent asynchronously.");

                    LowLevel_StartSending(message, tcpSocketInfo);
                }
            }
            catch(Exception ex)
            {
                this.SocketFailed(ex, tcpSocketInfo);
            }
        }
        /// <summary>
        /// Sends a ping through the specified connection.
        /// </summary>
        /// <param name="tcpSocketInfoAsObject">The connection.</param>
        private void SendPing(object tcpSocketInfoAsObject)
        {
            TcpSocketInfo tcpSocketInfo = null;

            try
            {
                tcpSocketInfo = (TcpSocketInfo) tcpSocketInfoAsObject;

                // TODO: 2.5.5 fix. Don't send ping messages if there is a least one message in the queue
                lock (tcpSocketInfo)
                {
                    if (tcpSocketInfo.MessageContainer.IsMessageAvailable)
                        return ;
                }

                Message message = new Message(this.ITransportContext, tcpSocketInfo.Remote, GenuineReceivingHandler.PING_MESSAGE_REPLYID, new TransportHeaders(), Stream.Null);
                message.IsSynchronous = false;
                message.IsOneWay = true;
                message.SerializedContent = Stream.Null;

                // LOG:
                BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0 )
                    binaryLogWriter.WriteMessageCreatedEvent("TcpConnectionManager.SendPing",
                        LogMessageType.MessageCreated, null, message, true, tcpSocketInfo.Remote, null,
                        "TCP PING", "TCP PING",
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, tcpSocketInfo.DbgConnectionId,
                        -1, null, -1, null,
                        "TCP ping is created and sent.");

                this.SendAsync(message, tcpSocketInfo);
            }
            catch(Exception ex)
            {
                // LOG:
                BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.SendPing",
                        LogMessageType.ConnectionPingSending, ex, null, tcpSocketInfo == null ? null : tcpSocketInfo.Remote, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null,
                        "Cannot send a ping.");
            }
        }
        /// <summary>
        /// Handles the incoming request.
        /// </summary>
        /// <param name="message">The response.</param>
        /// <returns>The response.</returns>
        public Stream HandleRequest(Message message)
        {
            // fetch the name of the server service
            IServerServiceEntry iServerServiceEntry = null;
            string entryName = message.DestinationMarshalByRef as string;
            if (entryName != null)
                iServerServiceEntry = this._services[entryName] as IServerServiceEntry;

            // there is no service registered in the local collection, try the global collection
            if (entryName != null && iServerServiceEntry == null)
                iServerServiceEntry = _globalServices[entryName] as IServerServiceEntry;

            if (iServerServiceEntry == null)
            {
                // no services are registered to handle this request
            //				message.ITransportContext.IEventLogger.Log(LogMessageCategory.Error, null, "DirectExchangeManager.HandlerRequest",
            //					null, "There are no services associated with the \"{0}\" name. Incoming request is ignored.", entryName == null ? "<null!>" : entryName);
                message.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.UnknownServerService, null, message.Sender, entryName));

                throw GenuineExceptions.Get_Receive_NoServices(entryName);
            }

            return iServerServiceEntry.HandleMessage(message.Stream, message.Sender);
        }
        /// <summary>
        /// Sends a message synchronously. Does not process exceptions!
        /// </summary>
        /// <param name="message">Message.</param>
        /// <param name="tcpSocketInfo">Acquired connection.</param>
        public void LowLevel_SendSync(Message message, TcpSocketInfo tcpSocketInfo)
        {
            Stream stream = null;
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0 )
                binaryLogWriter.WriteEvent(LogCategory.Transport, "TcpConnectionManager.LowLevel_SendSync",
                    LogMessageType.MessageIsSentSynchronously, null, message, message.Recipient, null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity,
                    tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                    tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                    "The connection has been obtained and the message is being sent synchronously.");

            try
            {
                // PING: prevent a ping
                if (tcpSocketInfo.GenuineConnectionType == GenuineConnectionType.Persistent)
                    tcpSocketInfo.LastTimeContentWasSent = GenuineUtility.TickCount;

                tcpSocketInfo.SetupWriting(message.FinishTime);

                // create a stream
                bool finished = false;

                // enable connection-level security encryption
                stream = message.SerializedContent;
                if (tcpSocketInfo.ConnectionLevelSecurity != null)
                {
                    GenuineChunkedStream encryptedContentStream = new GenuineChunkedStream(true);
                    tcpSocketInfo.ConnectionLevelSecurity.Encrypt(stream, encryptedContentStream);
                    stream = encryptedContentStream;
                }

                // send it in chunks
                while ( ! finished )
                {
                    int currentPosition = HEADER_SIZE;

                    // read data
                    int size = 0;
                    while ( tcpSocketInfo._sendBuffer.Length > currentPosition &&
                        (size = stream.Read(tcpSocketInfo._sendBuffer, currentPosition, tcpSocketInfo._sendBuffer.Length - currentPosition)) > 0)
                    {
                        if (size <= 0)
                            break;

                        currentPosition += size;
                    }

                    finished = currentPosition < tcpSocketInfo._sendBuffer.Length;
                    int totalSize = currentPosition;

                    // prepare header
                    tcpSocketInfo._sendBuffer[0] = MessageCoder.COMMAND_MAGIC_CODE;
                    MessageCoder.WriteInt32(tcpSocketInfo._sendBuffer, 1, totalSize - HEADER_SIZE);
                    tcpSocketInfo._sendBuffer[5] = finished ? (byte) 1 : (byte) 0;

                    // and send it
                    currentPosition = 0;
                    tcpSocketInfo.Write(tcpSocketInfo._sendBuffer, currentPosition, totalSize);
                    this.IncreaseBytesSent(totalSize);
                }

                // the message can be resent only if the persistent pattern is used
                if (tcpSocketInfo.GenuineConnectionType == GenuineConnectionType.Persistent  && ! (bool) this.ITransportContext.IParameterProvider[GenuineParameter.TcpDoNotResendMessages])
                    tcpSocketInfo.MessagesSentSynchronously.PutMessage(message);
            }
            catch(Exception ex)
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0 )
                    binaryLogWriter.WriteEvent(LogCategory.Transport, "TcpConnectionManager.LowLevel_SendSync",
                        LogMessageType.MessageIsSentSynchronously, ex, message, message.Recipient, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity,
                        tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                        tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                        "The exception occurred while synchronous sending.");

                throw;
            }
            finally
            {
                lock (tcpSocketInfo)
                    tcpSocketInfo.LockForSending = false;
            }

            // the message was sent
            // PING: schedule a ping
            if (tcpSocketInfo.GenuineConnectionType == GenuineConnectionType.Persistent)
                tcpSocketInfo.LastTimeContentWasSent = GenuineUtility.TickCount;
        }
        /// <summary>
        /// Sends the content to the specified remote host and redirects a response to the callback.
        /// </summary>
        /// <param name="destination">The remote host.</param>
        /// <param name="serviceName">The name of the service.</param>
        /// <param name="content">The content.</param>
        /// <param name="iStreamResponseHandler">The response handler.</param>
        /// <param name="tag">The object that contains data about this invocation.</param>
        public void SendAsync(HostInformation destination, string serviceName, Stream content, IStreamResponseHandler iStreamResponseHandler, object tag)
        {
            // create the message
            Message message = new Message(this.ITransportContext, destination, 0, new TransportHeaders(), content);
            message.IsSynchronous = false;
            message.GenuineMessageType = GenuineMessageType.ExternalStreamConsumer;
            message.DestinationMarshalByRef = serviceName;
            message.Tag = tag;

            // register the response catcher
            UniversalAsyncResponseProcessor universalAsyncResponseProcessor = new UniversalAsyncResponseProcessor(message, null, iStreamResponseHandler);
            this.ITransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, universalAsyncResponseProcessor);

            // and send the message
            this.ITransportContext.ConnectionManager.Send(message);
        }
        /// <summary>
        /// Sends a small synchronous packet to the server in order to prevent delayed ack.
        /// </summary>
        /// <param name="tcpSocketInfoAsObject">The TCP connection.</param>
        internal void LowLevel_Client_PreventDelayedAck(object tcpSocketInfoAsObject)
        {
            TcpSocketInfo tcpSocketInfo = (TcpSocketInfo) tcpSocketInfoAsObject;

            try
            {
                Message message = new Message(this.ITransportContext, tcpSocketInfo.Remote, GenuineReceivingHandler.PING_MESSAGE_REPLYID, new TransportHeaders(), Stream.Null);
                message.IsSynchronous = true;
                message.SerializedContent = Stream.Null;
                this.SendSync(message, tcpSocketInfo);
            }
            catch(Exception ex)
            {
                BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Transport, "TcpConnectionManager.LowLevel_Client_PreventDelayedAck",
                        LogMessageType.SynchronousSendingFinished, ex, null, tcpSocketInfo.Remote, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        tcpSocketInfo.ConnectionLevelSecurity,
                        tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                        tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                        "The exception occurred while sending a synchronous message.");
                }
            }
        }
        /// <summary>
        /// Sends one-way message to the remote host. Ignores all exceptions and does not 
        /// receive the response.
        /// </summary>
        /// <param name="destination">The remote host.</param>
        /// <param name="serviceName">The name of the entry.</param>
        /// <param name="content">The content.</param>
        public void SendOneWay(HostInformation destination, string serviceName, Stream content)
        {
            try
            {
                // create the message
                Message message = new Message(this.ITransportContext, destination, 0, new TransportHeaders(), content);
                message.IsOneWay = true;
                message.GenuineMessageType = GenuineMessageType.ExternalStreamConsumer;
                message.DestinationMarshalByRef = serviceName;

                // and send the message
                this.ITransportContext.ConnectionManager.Send(message);
            }
            catch (Exception)
            {
            }
        }
 /// <summary>
 /// Sends a broadcast message thru IP multicasting.
 /// </summary>
 /// <param name="message">The message being sent.</param>
 /// <param name="resultCollector">The result collector that gathers results of the invocation.</param>
 public override void SendMessage(Message message, ResultCollector resultCollector)
 {
     message.Recipient = this.ITransportContext.KnownHosts["_gbudp://" + this.Court];
     message.DestinationMarshalByRef = this.Court;
     this.ITransportContext.ConnectionManager.Send(message);
 }
        /// <summary>
        /// Sends the content to the specified remote host and returns a response sent by the remote
        /// host in reply.
        /// </summary>
        /// <param name="destination">The remote host.</param>
        /// <param name="serviceName">The name of the service.</param>
        /// <param name="content">The content.</param>
        /// <returns>The response.</returns>
        public Stream SendSync(HostInformation destination, string serviceName, Stream content)
        {
            // create the message
            Message message = new Message(this.ITransportContext, destination, 0, new TransportHeaders(), content);
            message.IsSynchronous = true;
            message.GenuineMessageType = GenuineMessageType.ExternalStreamConsumer;
            message.DestinationMarshalByRef = serviceName;

            // register the response catcher
            SyncResponseProcessorWithEvent syncResponseProcessorWithEvent = new SyncResponseProcessorWithEvent(message);
            this.ITransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, syncResponseProcessorWithEvent);

            // and send the message
            this.ITransportContext.ConnectionManager.Send(message);

            int timeSpanInMilliseconds = GenuineUtility.GetMillisecondsLeft(message.FinishTime);
            if (timeSpanInMilliseconds <= 0)
                throw GenuineExceptions.Get_Send_ServerDidNotReply();
            if (! syncResponseProcessorWithEvent.IsReceivedEvent.WaitOne(timeSpanInMilliseconds, false))
                throw GenuineExceptions.Get_Send_ServerDidNotReply();

            if (syncResponseProcessorWithEvent.DispatchedException != null)
                throw OperationException.WrapException(syncResponseProcessorWithEvent.DispatchedException);
            return syncResponseProcessorWithEvent.Response.Stream;
        }
 /// <summary>
 /// Sends the message to the remote host. Services messages with serialized content only,
 /// after Security Session completes its job.
 /// </summary>
 /// <param name="message">The message.</param>
 protected abstract void InternalSend(Message message);
        /// <summary>
        /// Sends the message to the remote host.
        /// Returns a response if corresponding Security Session is established and the initial message is not one-way.
        /// </summary>
        /// <param name="message">The message to be sent or a null reference (if there is a queued message).</param>
        protected override void InternalSend(Message message)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            TcpSocketInfo tcpSocketInfo = null;

            if (message.IsSynchronous)
            {
                for ( ; ; )
                {
                    // get the available connection
                    tcpSocketInfo = this.GetConnectionForSending(message);

                    // LOG:
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                    {
                        binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.InternalSend",
                            LogMessageType.ConnectionSelected, null, null, tcpSocketInfo.Remote, null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                            tcpSocketInfo.ConnectionLevelSecurity,
                            tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                            tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                            "TCP connection has been selected. Stack trace: {0}", Environment.StackTrace);
                    }

                    try
                    {
                        // register a message
                        if (tcpSocketInfo.MessageContainer != null)
                            tcpSocketInfo.MessageContainer.AddMessage(message, true);

                        SendSync(message, tcpSocketInfo);
                        return ;
                    }
                    catch (Exception ex)
                    {
                        this.SocketFailed(ex, tcpSocketInfo);

                        // if it's a transport problem, change the transport
                        OperationException operationException = ex as OperationException;
                        if (operationException != null && operationException.OperationErrorMessage.ErrorIdentifier == "GenuineChannels.Exception.Send.TransportProblem")
                        {
                            message.SerializedContent.Position = 0;
                            continue;
                        }

                        // otherwise, deliver the exception back to the caller
                        throw;
                    }
                    finally
                    {
                        // unregister the message
                        if (tcpSocketInfo.MessageContainer != null)
                            tcpSocketInfo.MessageContainer.UnregisterSyncMessage(message);
                    }
                }
            }
            else
            {
                tcpSocketInfo = this.GetConnectionForSending(message);
                SendAsync(message, tcpSocketInfo);
            }
        }
        /// <summary>
        /// Acquires a connection according to message parameters or throw the corresponding exception
        /// if it's impossible.
        /// </summary>
        /// <param name="message">The message being sent.</param>
        /// <returns>The acquired connection.</returns>
        private TcpSocketInfo GetConnectionForSending(Message message)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            TcpSocketInfo tcpSocketInfo = null;
            string uri = null;
            bool isServer = false;
            string remoteUri = null;
            int remoteHostUniqueIdentifier;

            using (new ReaderAutoLocker(this._disposeLock))
            {
                if (this._disposed)
                    throw OperationException.WrapException(this._disposeReason);

                switch (message.SecuritySessionParameters.GenuineConnectionType)
                {
                    case GenuineConnectionType.Persistent:
                        uri = message.Recipient.Url;
                        if (message.ConnectionName == null)
                            message.ConnectionName = message.SecuritySessionParameters.ConnectionName;

                        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)
                            {
                                tcpSocketInfo = this._persistent.Get(uri, message.ConnectionName) as TcpSocketInfo;

                                if (tcpSocketInfo != null && !tcpSocketInfo.IsValid)
                                {
                                    this._persistent.Remove(uri, message.ConnectionName);
                                    tcpSocketInfo = null;
                                }

                                if (tcpSocketInfo == null)
                                {
                                    // try to establish a persistent connection
                                    tcpSocketInfo = LowLevel_OpenConnection(message.Recipient, GenuineConnectionType.Persistent, this.Local.Uri, this.LocalPort, message.ConnectionName, out remoteUri, out remoteHostUniqueIdentifier);

                                    // update remote host info
                                    message.Recipient.UpdateUri(remoteUri, remoteHostUniqueIdentifier);
                                    message.Recipient.PhysicalAddress = tcpSocketInfo.Socket.RemoteEndPoint;
                                    message.Recipient.LocalPhysicalAddress = tcpSocketInfo.Socket.LocalEndPoint;
                                    tcpSocketInfo.Remote = message.Recipient;

                                    // LOG:
                                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.HostInformation] > 0 )
                                    {
                                        binaryLogWriter.WriteHostInformationEvent("TcpConnectionManager.LowLevel_OpenConnection",
                                            LogMessageType.HostInformationCreated, null, message.Recipient,
                                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, tcpSocketInfo.ConnectionLevelSecurity,
                                            tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                                            tcpSocketInfo.DbgConnectionId,
                                            "HostInformation is ready for actions.");
                                    }

                                    // OK, connection established
                                    tcpSocketInfo.MessageContainer = new MessageContainer(this.ITransportContext);
                                    this._persistent.Set(uri, tcpSocketInfo.ConnectionName, tcpSocketInfo);

                                    tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.ClosePersistentConnectionAfterInactivity]);
                                    tcpSocketInfo.Renew();
                                    tcpSocketInfo.SignalState(GenuineEventType.GeneralConnectionEstablished, null, null);

                                    // LOG:
                                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                    {
                                        binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.GetConnectionForSending",
                                            LogMessageType.ConnectionEstablished, null, null, tcpSocketInfo.Remote, null,
                                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                            tcpSocketInfo.ConnectionLevelSecurity,
                                            tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                                            tcpSocketInfo.DbgConnectionId, (int) message.SecuritySessionParameters.GenuineConnectionType, 0, 0, this.GetType().Name, message.Recipient.LocalPhysicalAddress.ToString(), message.Recipient.PhysicalAddress.ToString(), null,
                                            "The connection to the remote host is established.");
                                    }

                                    this.Pool_StartSending(tcpSocketInfo);
                                    this.Pool_InitiateReceiving(tcpSocketInfo, this.ITransportContext.IParameterProvider);
                                }
                            }
                            else
                            {
                                // remote host is a client and if there is no connection to it, it's unreachable
                                tcpSocketInfo = this._persistent.Get(uri, message.ConnectionName) as TcpSocketInfo;
                                if (tcpSocketInfo == null)
                                    throw GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.Uri);
                            }
                        }
                        break;

                    case GenuineConnectionType.Named:
                        if (message.ConnectionName == null)
                            message.ConnectionName = message.SecuritySessionParameters.ConnectionName;

                        isServer = message.Recipient.Url == null;
                        string fullConnectionName = this.GetNamedConnectionName(isServer, message.Recipient, message.ConnectionName);

                        try
                        {
                            // if it's possible to establish a connection to the remote host
                            if (! isServer)
                            {
                                bool shouldBeEstablished = false;
                                lock (this._named)
                                {
                                    tcpSocketInfo = this._named[fullConnectionName] as TcpSocketInfo;

                                    // if it's necessary to establish a connection
                                    if (tcpSocketInfo == null)
                                    {
                                        shouldBeEstablished = true;

                                        // register a message queue for this connection
                                        tcpSocketInfo = new TcpSocketInfo(null, this.ITransportContext, message.ConnectionName
            #if DEBUG
                                            ,"Stub for the named connection while it's being established."
            #endif
                                            );
                                        tcpSocketInfo.Remote = message.Recipient;
                                        tcpSocketInfo.GenuineConnectionType = GenuineConnectionType.Named;
                                        tcpSocketInfo.LockForSending = true;
                                        tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.ConnectTimeout]);
                                        tcpSocketInfo.MessageContainer = new MessageContainer(this.ITransportContext);
                                        tcpSocketInfo.Renew();
                                        this._named[fullConnectionName] = tcpSocketInfo;
                                    }
                                }

                                if (shouldBeEstablished)
                                {
                                    // try to establish named connection
                                    tcpSocketInfo = LowLevel_OpenConnection(message.Recipient, GenuineConnectionType.Named, this.Local.Uri, this.LocalPort, message.ConnectionName, out remoteUri, out remoteHostUniqueIdentifier);

                                    // update remote host info
                                    message.Recipient.UpdateUri(remoteUri, remoteHostUniqueIdentifier);
                                    message.Recipient.PhysicalAddress = tcpSocketInfo.Socket.RemoteEndPoint;
                                    message.Recipient.LocalPhysicalAddress = tcpSocketInfo.Socket.LocalEndPoint;
                                    tcpSocketInfo.Remote = message.Recipient;

                                    // calculate the time to close the connection after
                                    if (message.SecuritySessionParameters.CloseAfterInactivity == TimeSpan.MinValue)
                                        tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.CloseNamedConnectionAfterInactivity]);
                                    else
                                        tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(message.SecuritySessionParameters.CloseAfterInactivity);
                                    tcpSocketInfo.Renew();

                                    // and exchange it with the registered queue
                                    lock (this._named)
                                    {
                                        TcpSocketInfo stubWithQueue = (TcpSocketInfo) this._named[fullConnectionName];
                                        this._named[fullConnectionName] = tcpSocketInfo;
                                        tcpSocketInfo.MessageContainer = stubWithQueue.MessageContainer;
                                    }

                                    // LOG:
                                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                    {
                                        binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.GetConnectionForSending",
                                            LogMessageType.ConnectionEstablished, null, null, tcpSocketInfo.Remote, null,
                                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                            tcpSocketInfo.ConnectionLevelSecurity,
                                            tcpSocketInfo.ConnectionLevelSecurity == null ? null : tcpSocketInfo.ConnectionLevelSecurity.Name,
                                            tcpSocketInfo.DbgConnectionId, (int) message.SecuritySessionParameters.GenuineConnectionType, 0, 0, this.GetType().Name, message.Recipient.LocalPhysicalAddress.ToString(), message.Recipient.PhysicalAddress.ToString(), null,
                                            "The connection to the remote host is established.");
                                    }

                                    this.Pool_StartSending(tcpSocketInfo);
                                    this.Pool_InitiateReceiving(tcpSocketInfo, this.ITransportContext.IParameterProvider);
                                }
                            }
                            else
                            {
                                // remote host is a client and if there are no connection to it, it's unreachable
                                lock (this._named)
                                    tcpSocketInfo = this._named[fullConnectionName] as TcpSocketInfo;
                                if (tcpSocketInfo == null)
                                {
                                    Exception exception = GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.Uri);

                                    // LOG:
                                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                                    {
                                        binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.GetConnectionForSending",
                                            LogMessageType.ConnectionEstablished, exception, message, message.Recipient, null,
                                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                            null, null, -1, (int) message.SecuritySessionParameters.GenuineConnectionType, 0, 0, this.GetType().Name, null, null, null,
                                            "The connection to the remote host cannot be established.");
                                    }

                                    throw exception;
                                }
                            }
                        }
                        catch(Exception ex)
                        {
                            tcpSocketInfo.Remote = message.Recipient;
                            this.SocketFailed(ex, tcpSocketInfo);

                            TcpSocketInfo existingConnection = null;
                            lock (this._named)
                                existingConnection = this._named[fullConnectionName] as TcpSocketInfo;

                            this.SocketFailed(ex, existingConnection);
            //
            //							MessageContainer messageContainerToBeClearedUp = null;
            //							lock (this._named)
            //							{
            //								TcpSocketInfo existingConnection = this._named[fullConnectionName] as TcpSocketInfo;
            //								if (existingConnection != null)
            //									messageContainerToBeClearedUp = existingConnection.MessageContainer;
            //								this._named.Remove(fullConnectionName);
            //							}
            //
            //							if (messageContainerToBeClearedUp != null)
            //								messageContainerToBeClearedUp.Dispose(ex);
            //
            //							if (ConnectionManager.IsExceptionCritical(ex as OperationException))
            //								message.Recipient.Dispose(ex);
                            throw;
                        }
                        break;

                    case GenuineConnectionType.Invocation:

                        // TODO: remove it after updating this code
                        throw new ApplicationException("This version of Genuine Channels does not support the Invocation Connection Pattern.");

                        //						// if it's a request, it's necessary to open the connection
                        //						if (message.ConnectionId == null || ! message.ConnectionId.StartsWith("~"))
                        //						{
                        //							// try to find inactive one
                        //							ArrayList invocationConnections = null;
                        //							lock (this._invocationConnections.SyncRoot)
                        //							{
                        //								invocationConnections = this._invocationConnections[message.Recipient.Url] as ArrayList;
                        //								if (invocationConnections == null)
                        //									this._invocationConnections[message.Recipient.Url] = invocationConnections = new ArrayList();
                        //							}
                        //
                        //							lock (invocationConnections)
                        //								for ( int i = 0; i < invocationConnections.Count ; i++ )
                        //								{
                        //									tcpSocketInfo = (TcpSocketInfo) invocationConnections[i];
                        //									if (tcpSocketInfo.IsValid && tcpSocketInfo.TcpInvocationFiniteAutomatonState == TcpInvocationFiniteAutomatonState.ClientAvailable)
                        //									{
                        //										// connection may be broken
                        //										message.IsResendAfterFail = true;
                        //										tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ClientSending;
                        //										tcpSocketInfo.InitialMessage = message;
                        //										break;
                        //									}
                        //									else
                        //										tcpSocketInfo = null;
                        //								}
                        //
                        //							if (tcpSocketInfo == null)
                        //							{
                        //								// it is necessary to open a new one
                        //								tcpSocketInfo = LowLevel_OpenConnection(message.Recipient, GenuineConnectionType.Invocation, this.Local.Uri, this.LocalPort, null, out remoteUri);
                        //								tcpSocketInfo.Remote = message.Recipient;
                        //
                        //								// update remote host info
                        //								message.Recipient.UpdateUri(remoteUri);
                        //								tcpSocketInfo.Remote = message.Recipient;
                        //								tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ClientSending;
                        //								tcpSocketInfo.InitialMessage = message;
                        //								message.IsResendAfterFail = false;
                        //
                        //								// calculate the time to close the connection after
                        //								if (message.SecuritySessionParameters.CloseAfterInactivity == TimeSpan.MinValue)
                        //									tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.CloseInvocationConnectionAfterInactivity]);
                        //								else
                        //									tcpSocketInfo.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(message.SecuritySessionParameters.CloseAfterInactivity);
                        //								tcpSocketInfo.Renew();
                        //
                        //								// add opened connection to connection pool
                        //								lock (this._invocationConnections.SyncRoot)
                        //								{
                        //									ArrayList connections = (ArrayList) this._invocationConnections[message.Recipient.Url];
                        //									lock (connections)
                        //										connections.Add(tcpSocketInfo);
                        //								}
                        //
                        //								this.Pool_InitiateReceiving(tcpSocketInfo, this.ITransportContext.IParameterProvider);
                        //							}
                        //						}
                        //						else
                        //						{
                        //							// it's a reply, it's necessary just to send the response through
                        //							// the existent connection with the given name
                        //							tcpSocketInfo = this._knownInvocationConnections[message.ConnectionId] as TcpSocketInfo;
                        //							if (tcpSocketInfo == null)
                        //								throw GenuineExceptions.Get_Send_NoNamedConnectionFound(message.ConnectionId);
                        //							tcpSocketInfo.TcpInvocationFiniteAutomatonState = TcpInvocationFiniteAutomatonState.ServerSending;
                        //							tcpSocketInfo.InitialMessage = message;
                        //						}
                        //
                        //						tcpSocketInfo.Renew();
                        //						break;

                    default:
                        throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(message.Recipient.PrimaryUri, "Invalid type of connection requested.");
                }
            }

            return tcpSocketInfo;
        }
        /// <summary>
        /// Sets up correct security context and invokes a target.
        /// This method may not throw any exceptions.
        /// </summary>
        /// <param name="message">The message to be performed.</param>
        /// <param name="connectionLevel">Indicates whether Security Session is used on the connection level.</param>
        public override void Invoke(Message message, bool connectionLevel)
        {
            bool impersonateContext = (this.KeyProvider_SspiServer.RequiredFeatures & SspiFeatureFlags.Impersonation) != 0 ||
                (this.KeyProvider_SspiServer.RequiredFeatures & SspiFeatureFlags.Delegation) != 0;

            try
            {
                if (impersonateContext)
                    SspiApi.ImpersonateSecurityContext(this.SspiSecurityContext._phContext);

                base.Invoke(message, connectionLevel);
            }
            finally
            {
                if (impersonateContext)
                    SspiApi.RevertSecurityContext(this.SspiSecurityContext._phContext);
            }
        }