/// <summary>
        /// Creates and returns the Connection Level Security Session.
        /// </summary>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <returns>The created Security Session.</returns>
        internal SecuritySession CreateConnectionLevelSecuritySession(GenuineConnectionType genuineConnectionType)
        {
            // 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;
            }

            // create and return the Security Session
            if (connectionLevelSSName != null)
            {
                return(this.ITransportContext.IKeyStore.GetKey(connectionLevelSSName).CreateSecuritySession(connectionLevelSSName, null));
            }

            return(null);
        }
示例#2
0
        /// <summary>
        /// Returns a stream containing version of the using protocol and type of the connection being established.
        /// </summary>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="genuineConnectionType">Type of the connection.</param>
        /// <param name="connectionId">The identifier of the connection.</param>
        /// <returns>BinaryWriter containing a stream with serialized data.</returns>
        public static BinaryWriter SerializeConnectionHeader(byte protocolVersion, GenuineConnectionType genuineConnectionType, string connectionId)
        {
            GenuineChunkedStream stream       = new GenuineChunkedStream(false);
            BinaryWriter         binaryWriter = new BinaryWriter(stream);

            binaryWriter.Write((byte)protocolVersion);
            binaryWriter.Write((byte)genuineConnectionType);
            binaryWriter.Write((string)connectionId);

            return(binaryWriter);
        }
        /// <summary>
        /// Closes the specified connections to the remote host and releases acquired resources.
        /// </summary>
        /// <param name="hostInformation">The host information.</param>
        /// <param name="genuineConnectionType">A value indicating what kind of connections will be affected by this operation.</param>
        /// <param name="reason">The reason of resource releasing.</param>
        public override void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            reason = GenuineExceptions.Get_Channel_ConnectionShutDown(reason);

            // LOG:
            if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0)
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "SharedMemoryConnectionManager.ReleaseConnections",
                                           LogMessageType.ReleaseConnections, reason, null, hostInformation, null,
                                           GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                           null, null, -1, 0, 0, 0, Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null, null, null,
                                           "Connections \"{0}\" will be terminated.", Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null);
            }

            if (hostInformation == null)
            {
                this.InternalDispose(reason);
                return;
            }

            SharedMemoryConnection sharedMemoryConnection = null;

            if (hostInformation.Url != null)
            {
                sharedMemoryConnection = this._persistent[hostInformation.Url] as SharedMemoryConnection;
            }
            if (sharedMemoryConnection != null)
            {
                this.ConnectionFailed(reason, sharedMemoryConnection);
            }

            sharedMemoryConnection = null;
            if (hostInformation.Uri != null)
            {
                sharedMemoryConnection = this._persistent[hostInformation.Uri] as SharedMemoryConnection;
            }
            if (sharedMemoryConnection != null)
            {
                this.ConnectionFailed(reason, sharedMemoryConnection);
            }
        }
        /// <summary>
        /// Parses the HTTP header.
        /// </summary>
        /// <param name="binaryReader">The source binary reader.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="genuineConnectionType">The type of connection.</param>
        /// <param name="hostId">The identifier of the remote host.</param>
        /// <param name="httpPacketType">The type of the packet.</param>
        /// <param name="sequenceNo">The packet number.</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>
        public static void ReadRequestHeader(BinaryReader binaryReader, out byte protocolVersion, out GenuineConnectionType genuineConnectionType, out Guid hostId, out HttpPacketType httpPacketType, out int sequenceNo, out string connectionName, out int remoteHostUniqueIdentifier)
        {
            if (binaryReader.ReadByte() != MessageCoder.COMMAND_MAGIC_CODE)
                throw GenuineExceptions.Get_Receive_IncorrectData();

            protocolVersion = binaryReader.ReadByte();
            genuineConnectionType = (GenuineConnectionType) binaryReader.ReadByte();
            hostId = new Guid(binaryReader.ReadBytes(16));
            httpPacketType = (HttpPacketType) binaryReader.ReadByte();
            sequenceNo = binaryReader.ReadInt32();

            connectionName = "$/__GC/" + hostId;
            remoteHostUniqueIdentifier = 0;

            if (protocolVersion >= 0x1)
            {
                connectionName = binaryReader.ReadString();
                remoteHostUniqueIdentifier = binaryReader.ReadInt32();
            }
        }
        /// <summary>
        /// Constructs an instance of the SecuritySessionParameters class.
        /// </summary>
        /// <param name="securitySessionName">The name of the Security Session.</param>
        /// <param name="securitySessionAttributes">Security Session parameters.</param>
        /// <param name="timeout">The invocation timeout or the TimeSpan.MinValue value to inherit the timeout from channel or Transport Context settings.</param>
        /// <param name="remoteTransportUser">For load balancing or dispatching the invocation to the specific known appdomain.</param>
        public SecuritySessionParameters(string securitySessionName, SecuritySessionAttributes securitySessionAttributes, TimeSpan timeout, string remoteTransportUser)
        {
            this.Name = securitySessionName;
            this.Attributes = securitySessionAttributes;
            this.Timeout = timeout;

            this._genuineConnectionType = GenuineConnectionType.Persistent;
            this.RemoteTransportUser = remoteTransportUser;
        }
        /// <summary>
        /// Constructs an instance of the SecuritySessionParameters class.
        /// </summary>
        /// <param name="securitySessionName">The name of the Security Session.</param>
        /// <param name="securitySessionAttributes">Security Session parameters.</param>
        /// <param name="timeout">The invocation timeout or the TimeSpan.MinValue value to inherit the timeout from channel or Transport Context settings.</param>
        /// <param name="genuineConnectionType">Type of the connection being used. The connection type must be support by the corresponding connection manager.</param>
        /// <param name="connecitonName">The name of the connection if named connection type is specified.</param>
        /// <param name="closeAfterInactivity">The time of inactivity to close a connection or TimeSpan.MinValue to inherit this value from channel or Transport Context parameters.</param>
        /// <param name="remoteTransportUser">For load balancing or dispatching the invocation to the specific known appdomain.</param>
        public SecuritySessionParameters(string securitySessionName, SecuritySessionAttributes securitySessionAttributes, TimeSpan timeout, GenuineConnectionType genuineConnectionType, string connecitonName, TimeSpan closeAfterInactivity, string remoteTransportUser)
        {
            this.Name = securitySessionName;
            this.Attributes = securitySessionAttributes;
            this.Timeout = timeout;

            this._genuineConnectionType = genuineConnectionType;
            this._connectionName = connecitonName;
            this.CloseAfterInactivity = closeAfterInactivity;
            this.RemoteTransportUser = remoteTransportUser;
        }
        /// <summary>
        /// Processes incoming requests and responses.
        /// </summary>
        /// <param name="stream">The stream containing a request or a response.</param>
        /// <param name="remote">The remote host.</param>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <param name="connectionName">Connection id to send a response through.</param>
        /// <param name="dbgConnectionId">The identifier of the connection, which is used for debugging purposes only.</param>
        /// <param name="useThisThread">True to invoke the target in the current thread.</param>
        /// <param name="iMessageRegistrator">The message registrator.</param>
        /// <param name="connectionLevelSecuritySession">Connection Level Security Session.</param>
        /// <param name="httpServerRequestResult">The HTTP request through which the message was received.</param>
        /// <returns>True if it's a one-way message.</returns>
        public bool HandleMessage(Stream stream, HostInformation remote, GenuineConnectionType genuineConnectionType, string connectionName, int dbgConnectionId, bool useThisThread, IMessageRegistrator iMessageRegistrator, SecuritySession connectionLevelSecuritySession, HttpServerRequestResult httpServerRequestResult)
        {
            // read the Security Session name
            BinaryReader binaryReader = new BinaryReader(stream);
            string sessionName = binaryReader.ReadString();
            Message message = null;
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            // and decode the packet
            SecuritySession securitySession = remote.GetSecuritySession(sessionName, this.ITransportContext.IKeyStore);
            if (securitySession == null)
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Security, "GenuineReceivingHandler.HandleMessage",
                        LogMessageType.SecuritySessionApplied, GenuineExceptions.Get_Security_ContextNotFound(sessionName),
                        message, remote,
                        null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        securitySession, sessionName, dbgConnectionId,
                        0, 0, 0, null, null, null, null,
                        "The requested Security Session can not be constructed or established. The name of Security Session: {0}.",
                        sessionName);
                }

                this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.SecuritySessionWasNotFound, GenuineExceptions.Get_Security_ContextNotFound(sessionName),
                    remote, null));

                return true;
            }

            // decode the stream and roll back if it was a Security Session's message
            stream = securitySession.Decrypt(stream);
            if (stream == null)
                return true;

            // read the message
            message = MessageCoder.Deserialize(stream, sessionName);
            message.ConnectionName = connectionName;
            message.SecuritySessionParameters._connectionName = connectionName;
            message.SecuritySessionParameters._genuineConnectionType = genuineConnectionType;
            message.Sender = remote;
            message.ITransportContext = this.ITransportContext;
            message.ConnectionLevelSecuritySession = connectionLevelSecuritySession;
            message.HttpServerRequestResult = httpServerRequestResult;

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0 )
            {
                binaryLogWriter.WriteEvent(LogCategory.Security, "GenuineReceivingHandler.HandleMessage",
                    LogMessageType.SecuritySessionApplied, null, message, remote,
                    null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    securitySession, sessionName, dbgConnectionId,
                    0, 0, 0, null, null, null, null,
                    "The Security Session has been used for decrypting the message.");
            }

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0 )
            {
                bool readContent = this.ITransportContext.BinaryLogWriter[LogCategory.MessageProcessing] > 1;
                if (readContent)
                {
                    GenuineChunkedStream streamClone = new GenuineChunkedStream();
                    GenuineUtility.CopyStreamToStream(message.Stream, streamClone);
                    message.Stream = streamClone;
                }

                binaryLogWriter.WriteMessageCreatedEvent("GenuineReceivingHandler.HandleMessage",
                    LogMessageType.MessageReceived, null, message, message.ReplyToId > 0, remote,
                    readContent ? message.Stream : null,
                    message.ITransportHeaders[Message.TransportHeadersInvocationTarget] as string, message.ITransportHeaders[Message.TransportHeadersMethodName] as string,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, connectionName, dbgConnectionId,
                    connectionLevelSecuritySession == null ? -1 : connectionLevelSecuritySession.SecuritySessionId,
                    connectionLevelSecuritySession == null ? null : connectionLevelSecuritySession.Name,
                    securitySession == null ? -1 : securitySession.SecuritySessionId,
                    securitySession.Name,
                    "The message has been received.");
            }

            if (message.ReplyToId == PING_MESSAGE_REPLYID)
                return true;

            if (iMessageRegistrator != null && iMessageRegistrator.WasRegistered(remote.Uri, message.MessageId, message.ReplyToId))
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0 )
                    binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineReceivingHandler.HandleMessage",
                        LogMessageType.MessageDispatched, GenuineExceptions.Get_Debugging_GeneralWarning("The message has been already processed."), message, remote,
                        null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, securitySession, securitySession.Name,
                        dbgConnectionId,
                        GenuineUtility.TickCount, 0, message.SeqNo, null, null, null, null,
                        "The message has been already processed. Therefore, this message is ignored.");

                return true;
            }

            // if it's a response, then direct the message to the response handler
            if (message.ReplyToId > 0)
            {
                message.IsOneWay = true;
                IResponseProcessor iResponseProcessor = GenuineReceivingHandler._responseHandlers[message.ReplyToId] as IResponseProcessor;

                // nothing waits for this request
                if (iResponseProcessor == null)
                    return true;

                // 2.5.1: set the answer flag
                if (iResponseProcessor.Message != null)
                    iResponseProcessor.Message.HasBeenAsnwered = true;

                if (iResponseProcessor.IsShortInProcessing)
                {
                    iResponseProcessor.ProcessRespose(message);

            #if TRIAL
            #else
                    if (iResponseProcessor.IsExpired(GenuineUtility.TickCount))
                        GenuineReceivingHandler._responseHandlers.Remove(message.ReplyToId);
            #endif

                    return true;
                }
            }

            // take care about the thread and call context
            if (useThisThread)
                InternalExecuteMessage(message);
            else
                GenuineThreadPool.QueueUserWorkItem(this._waitCallback_InternalExecuteMessagewaitCallback, message, false);

            return message.IsOneWay;
        }
 /// <summary>
 /// Closes all connections that fit to the specified characteristics.
 /// Automatically releases all resources acquired by connections being closed.
 /// </summary>
 /// <param name="hostInformation">The host or a null reference to embrace all remote hosts.</param>
 /// <param name="genuineConnectionType">Specifies what connection patterns will be affected by this operation.</param>
 /// <param name="reason">The reason of resource releasing that will be dispatched to all callers waiting something from the connections being closed.</param>
 public abstract void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason);
        /// <summary>
        /// Closes the specified connections to the remote host and releases acquired resources.
        /// </summary>
        /// <param name="hostInformation">The host information.</param>
        /// <param name="genuineConnectionType">A value indicating what kind of connections will be affected by this operation.</param>
        /// <param name="reason">The reason of resource releasing.</param>
        public override void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            reason = GenuineExceptions.Get_Channel_ConnectionShutDown(reason);

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "SharedMemoryConnectionManager.ReleaseConnections",
                    LogMessageType.ReleaseConnections, reason, null, hostInformation, null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    null, null, -1, 0, 0, 0, Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null, null, null,
                    "Connections \"{0}\" will be terminated.", Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null);
            }

            if (hostInformation == null)
            {
                this.InternalDispose(reason);
                return ;
            }

            SharedMemoryConnection sharedMemoryConnection = null;
            if (hostInformation.Url != null)
                sharedMemoryConnection = this._persistent[hostInformation.Url] as SharedMemoryConnection;
            if (sharedMemoryConnection != null)
                this.ConnectionFailed(reason, sharedMemoryConnection);

            sharedMemoryConnection = null;
            if (hostInformation.Uri != null)
                sharedMemoryConnection = this._persistent[hostInformation.Uri] as SharedMemoryConnection;
            if (sharedMemoryConnection != null)
                this.ConnectionFailed(reason, sharedMemoryConnection);
        }
 /// <summary>
 /// Closes all connections that fit to the specified characteristics.
 /// Automatically releases all resources acquired by connections being closed.
 /// </summary>
 /// <param name="hostInformation">The host or a null reference to embrace all remote hosts.</param>
 /// <param name="genuineConnectionType">Specifies what connection patterns will be affected by this operation.</param>
 /// <param name="reason">The reason of resource releasing that will be dispatched to all callers waiting something from the connections being closed.</param>
 public abstract void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason);
        /// <summary>
        /// Processes the sender's request.
        /// </summary>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <param name="input">The incoming data.</param>
        /// <param name="httpServerRequestResult">The request.</param>
        /// <param name="httpServerConnection">The connection.</param>
        /// <param name="sequenceNo">The sequence number.</param>
        /// <param name="remote">The information about remote host.</param>
        public void LowLevel_ProcessSenderRequest(GenuineConnectionType genuineConnectionType, Stream input, HttpServerRequestResult httpServerRequestResult, HttpServerConnection httpServerConnection, int sequenceNo, HostInformation remote)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            GenuineChunkedStream outputStream = null;

            // parse the incoming stream
            bool directExecution = genuineConnectionType != GenuineConnectionType.Persistent;
            BinaryReader binaryReader = new BinaryReader(input);

            using (BufferKeeper bufferKeeper = new BufferKeeper(0))
            {
                switch(genuineConnectionType)
                {
                    case GenuineConnectionType.Persistent:
                        Exception gotException = null;

                        try
                        {
                            if (httpServerConnection.Sender_SecuritySession != null)
                            {
                                input = httpServerConnection.Sender_SecuritySession.Decrypt(input);
                                binaryReader = new BinaryReader(input);
                            }

                            while (binaryReader.ReadByte() == 0)
                                using(LabelledStream labelledStream = new LabelledStream(this.ITransportContext, input, bufferKeeper.Buffer))
                                {
                                    GenuineChunkedStream receivedContent = new GenuineChunkedStream(true);
                                    GenuineUtility.CopyStreamToStream(labelledStream, receivedContent);
                                    this.ITransportContext.IIncomingStreamHandler.HandleMessage(receivedContent, httpServerConnection.Remote, genuineConnectionType, httpServerConnection.ConnectionName, httpServerConnection.DbgConnectionId, false, this._iMessageRegistrator, httpServerConnection.Sender_SecuritySession, httpServerRequestResult);
                                }
                        }
                        catch(Exception ex)
                        {
                            gotException = ex;

                            // LOG:
                            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                            {
                                binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.LowLevel_ProcessSenderRequest",
                                    LogMessageType.Error, ex, null, httpServerConnection.Remote, null,
                                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                                    httpServerConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                    "Error occurred while processing the sender request N: {0}.", httpServerConnection.Sender_SequenceNo);
                            }
                        }

                        if (gotException != null)
                        {
                            gotException = OperationException.WrapException(gotException);
                            outputStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.SenderError, sequenceNo, remote);
                            BinaryFormatter binaryFormatter = new BinaryFormatter(new RemotingSurrogateSelector(), new StreamingContext(StreamingContextStates.Other));
                            binaryFormatter.Serialize(outputStream, gotException);
                        }
                        else
                        {
                            // serialize and send the empty response
                            outputStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.SenderResponse, sequenceNo, remote);
                            MessageCoder.FillInLabelledStream(null, null, null, outputStream,
                                bufferKeeper.Buffer, (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]);
                        }
                        break;

                    case GenuineConnectionType.Invocation:
                        // register the http context as an invocation waiters
                        string connectionGuid = Guid.NewGuid().ToString("N");

                        try
                        {
                            if (binaryReader.ReadByte() != 0)
                            {
                                // LOG:
                                if ( binaryLogWriter != null )
                                {
                                    binaryLogWriter.WriteImplementationWarningEvent("HttpServerConnectionManager.LowLevel_ProcessSenderRequest", LogMessageType.Error,
                                        GenuineExceptions.Get_Debugging_GeneralWarning("The invocation request doesn't contain any messages."),
                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                        "The invocation request doesn't contain any messages.");
                                }
                            }

                            using(LabelledStream labelledStream = new LabelledStream(this.ITransportContext, input, bufferKeeper.Buffer))
                            {
                                // process the response
                                this._invocation[connectionGuid] = null;
                                this.ITransportContext.IIncomingStreamHandler.HandleMessage(labelledStream, remote, genuineConnectionType, connectionGuid, -1, true, null, null, httpServerRequestResult);
                            }

                            if (binaryReader.ReadByte() != 1)
                            {
                                // LOG:
                                if ( binaryLogWriter != null )
                                {
                                    binaryLogWriter.WriteImplementationWarningEvent("HttpServerConnectionManager.LowLevel_ProcessSenderRequest", LogMessageType.Error,
                                        GenuineExceptions.Get_Debugging_GeneralWarning("The invocation request must not contain more than one message."),
                                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                        "The invocation request must not contain more than one message.");
                                }
                            }

                            // if there is a response, serialize it
                            outputStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.Usual, sequenceNo, remote);
                            Message message = this._invocation[connectionGuid] as Message;
                            MessageCoder.FillInLabelledStream(message, null, null, outputStream,
                                bufferKeeper.Buffer, (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]);
                        }
                        finally
                        {
                            this._invocation.Remove(connectionGuid);
                        }
                        break;
                }
            }

            // report back to the client
            Stream finalStream = outputStream;
            this.LowLevel_SendStream(httpServerRequestResult.HttpContext, false, null, true, ref finalStream, httpServerConnection);
        }
示例#12
0
 /// <summary>
 /// Writes HTTP header to the specified binary writer.
 /// </summary>
 /// <param name="binaryWriter">The binary writer.</param>
 /// <param name="protocolVersion">The version of the protocol.</param>
 /// <param name="genuineConnectionType">The type of connection.</param>
 /// <param name="hostId">The id of the remote host.</param>
 /// <param name="httpPacketType">The type of the packet.</param>
 /// <param name="sequenceNo">The packet number.</param>
 /// <param name="connectionName">The name of the connection.</param>
 /// <param name="localHostUniqueIdentifier">The unique identifier of the local HostInformation.</param>
 public static void WriteRequestHeader(BinaryWriter binaryWriter, byte protocolVersion, GenuineConnectionType genuineConnectionType, byte[] hostId, HttpPacketType httpPacketType, int sequenceNo, string connectionName, int localHostUniqueIdentifier)
 {
     binaryWriter.Write((byte)MessageCoder.COMMAND_MAGIC_CODE);
     binaryWriter.Write((byte)protocolVersion);
     binaryWriter.Write((byte)genuineConnectionType);
     binaryWriter.Write(hostId);
     binaryWriter.Write((byte)httpPacketType);
     binaryWriter.Write((int)sequenceNo);
     binaryWriter.Write(connectionName);
     binaryWriter.Write((int)localHostUniqueIdentifier);
 }
        /// <summary>
        /// Sends HTTP content to the remote host.
        /// Does not process exceptions.
        /// Automatically initiates asynchronous receiving.
        /// Automatically manages stream seqNo for clients' connections.
        /// </summary>
        /// <param name="timeout">Operation timeout.</param>
        /// <param name="message">The message.</param>
        /// <param name="content">The content sent instead of the message.</param>
        /// <param name="exceptionToBeSent">The exception being sent in the response.</param>
        /// <param name="messageContainer">The message container.</param>
        /// <param name="xHttpPhysicalConnection">The physical connection.</param>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <param name="httpPacketType">The type of the HTTP packet.</param>
        /// <param name="repeatSending">Whether the content was already packed.</param>
        /// <param name="synchronous">Whether to send content synchronously.</param>
        /// <param name="startAutomaticReceiving">Indicates whether to start automatic receiving of the response/request if the type of the sending is synchronous.</param>
        /// <param name="applyClss">A boolean value indicating whether the CLSS should be applied.</param>
        private void LowLevel_SendHttpContent(int timeout, Message message, 
            GenuineChunkedStream content, Exception exceptionToBeSent,
            MessageContainer messageContainer, XHttpPhysicalConnection xHttpPhysicalConnection,
            GenuineConnectionType genuineConnectionType, HttpPacketType httpPacketType,
            bool repeatSending, bool synchronous, bool startAutomaticReceiving, bool applyClss
            )
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            // check whether the connection is valid and available
            xHttpPhysicalConnection.CheckConnectionStatus();

            // prevent the ping
            if (! xHttpPhysicalConnection.IsSender)
                xHttpPhysicalConnection.XHttpConnection.LastTimeContentWasSent = GenuineUtility.TickCount;

            // valid copies
            Socket socket;
            Stream sentContent;

            // to prevent from changing sequence information or disposing sent content during its encryption
            lock (xHttpPhysicalConnection.PhysicalConnectionStateLock)
            {
                if (! repeatSending)
                {
                    if (xHttpPhysicalConnection.XHttpConnection.IsClient)
                        xHttpPhysicalConnection.SequenceNo ++;

                    if (message != null || (message == null && content == null && exceptionToBeSent == null))
                    {
                        GenuineChunkedStream packedMessages = new GenuineChunkedStream(false);
                        MessageCoder.FillInLabelledStream(message, messageContainer,
                            xHttpPhysicalConnection.MessagesBeingSent, packedMessages,
                            xHttpPhysicalConnection.AsyncSendBuffer,
                            (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]);

                        // LOG:
                        if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0 )
                        {
                            for ( int i = 0; i < xHttpPhysicalConnection.MessagesBeingSent.Count; i++)
                            {
                                Message nextMessage = (Message) xHttpPhysicalConnection.MessagesBeingSent[i];

                                binaryLogWriter.WriteEvent(LogCategory.Transport, "XHttpConnectionManager.LowLevel_SendHttpContent",
                                    LogMessageType.MessageIsSentAsynchronously, null, nextMessage, xHttpPhysicalConnection.Remote, null,
                                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, xHttpPhysicalConnection.ConnectionLevelSecurity, null,
                                    xHttpPhysicalConnection.XHttpConnection.DbgConnectionId, xHttpPhysicalConnection.SequenceNo, 0, 0, null, null, null, null,
                                    "The message will be sent in the {0} stream N: {1}.",
                                    xHttpPhysicalConnection == xHttpPhysicalConnection.XHttpConnection.Sender ? "SENDER" : "LISTENER",
                                    xHttpPhysicalConnection.SequenceNo);
                            }
                        }

                        xHttpPhysicalConnection.SentContent = packedMessages;
                    }
                    else if (content != null)
                    {
                        xHttpPhysicalConnection.MessagesBeingSent.Clear();
                        xHttpPhysicalConnection.SentContent = content;
                    }
                    else //if (exceptionToBeSent != null)
                    {
            #if DEBUG
                        Debug.Assert(httpPacketType == HttpPacketType.SenderError);
            #endif

                        Exception exception = OperationException.WrapException(exceptionToBeSent);
                        GenuineChunkedStream output = new GenuineChunkedStream(false);
                        BinaryFormatter binaryFormatter = new BinaryFormatter(new RemotingSurrogateSelector(), new StreamingContext(StreamingContextStates.Other));
                        binaryFormatter.Serialize(output, exception);

                        xHttpPhysicalConnection.MessagesBeingSent.Clear();
                        xHttpPhysicalConnection.SentContent = output;
                    }

                    // client applies CLSSE only to the actual content
                    if (applyClss && xHttpPhysicalConnection.XHttpConnection.IsClient && xHttpPhysicalConnection.ConnectionLevelSecurity != null)
                    {
                        GenuineChunkedStream encryptedContent = new GenuineChunkedStream(false);
                        xHttpPhysicalConnection.ConnectionLevelSecurity.Encrypt(xHttpPhysicalConnection.SentContent, encryptedContent);
                        xHttpPhysicalConnection.SentContent = encryptedContent;
                    }

                    // write the binary header
                    GenuineChunkedStream resultStream = new GenuineChunkedStream(false);
                    BinaryWriter binaryWriter = new BinaryWriter(resultStream);

                    if (xHttpPhysicalConnection.XHttpConnection.IsClient)
                        HttpMessageCoder.WriteRequestHeader(binaryWriter, MessageCoder.PROTOCOL_VERSION, genuineConnectionType, xHttpPhysicalConnection.XHttpConnection.HostId, httpPacketType, xHttpPhysicalConnection.SequenceNo, xHttpPhysicalConnection.XHttpConnection.ConnectionName, xHttpPhysicalConnection.XHttpConnection.Remote.LocalHostUniqueIdentifier);
                    else
                        HttpMessageCoder.WriteResponseHeader(binaryWriter, xHttpPhysicalConnection.XHttpConnection.Remote.ProtocolVersion, this.ITransportContext.ConnectionManager.Local.Uri, xHttpPhysicalConnection.SequenceNo, httpPacketType, xHttpPhysicalConnection.XHttpConnection.Remote.LocalHostUniqueIdentifier);

                    resultStream.WriteStream(xHttpPhysicalConnection.SentContent);
                    xHttpPhysicalConnection.SentContent = resultStream;

                    // while server applies CLSSE to the entire response (except HTTP stuff, of course)
                    if (applyClss && ! xHttpPhysicalConnection.XHttpConnection.IsClient && xHttpPhysicalConnection.ConnectionLevelSecurity != null)
                    {
                        GenuineChunkedStream encryptedContent = new GenuineChunkedStream(false);
                        xHttpPhysicalConnection.ConnectionLevelSecurity.Encrypt(xHttpPhysicalConnection.SentContent, encryptedContent);
                        xHttpPhysicalConnection.SentContent = encryptedContent;
                    }

                    // generally it's impossible to have xHttpPhysicalConnection.SentContent without available length in the current implementation
                    // nevertheless, it's necessary to calculate the final length of the content if it's unknown
                    if (! xHttpPhysicalConnection.SentContent.CanSeek)
                    {
                        GenuineChunkedStream actualContent = new GenuineChunkedStream(false);
                        GenuineUtility.CopyStreamToStream(xHttpPhysicalConnection.SentContent, actualContent, xHttpPhysicalConnection.AsyncSendBuffer);
                        xHttpPhysicalConnection.SentContent = actualContent;
                    }

                    // write the header and compose final content
                    resultStream = new GenuineChunkedStream(false);
                    StreamWriter streamWriter = new StreamWriter(new NonClosableStream(resultStream), Encoding.ASCII, 3500);

                    if (xHttpPhysicalConnection.XHttpConnection.IsClient)
                        streamWriter.Write("POST /{0} HTTP/1.1\r\nAccept: */*\r\nContent-Type: application/octet-stream\r\nContent-Length: {1}\r\nUser-Agent: {2}\r\nHost: {3}\r\nConnection: Keep-Alive\r\nPragma: no-cache\r\n\r\n",
                            xHttpPhysicalConnection.EntryUri, xHttpPhysicalConnection.SentContent.Length, xHttpPhysicalConnection.XHttpConnection.UserAgent, xHttpPhysicalConnection.LocalEndPoint);
                    else
                    {
                        string now = DateTime.Now.ToString("r");
                        streamWriter.Write("HTTP/1.1 200 OK\r\nServer: GXHTTP\r\nDate: {0}\r\nX-Powered-By: Genuine Channels\r\nCache-Control: private\r\nContent-Type: application/octet-stream\r\nContent-Length: {1}\r\n\r\n",
                            now, xHttpPhysicalConnection.SentContent.Length);
                    }

                    streamWriter.Flush();
                    streamWriter.Close();
                    resultStream.WriteStream(xHttpPhysicalConnection.SentContent);

                    xHttpPhysicalConnection.SentContent = resultStream;
                }
                else
                {
                    xHttpPhysicalConnection.SentContent.Position = 0;
                }

                socket = xHttpPhysicalConnection.Socket;
                sentContent = xHttpPhysicalConnection.SentContent;
            }	// lock (xHttpPhysicalConnection.PhysicalConnectionStateLock)

            if (synchronous)
            {
                // send the content
                SyncSocketWritingStream syncSocketWritingStream = new SyncSocketWritingStream(this, socket, timeout, xHttpPhysicalConnection.XHttpConnection.DbgConnectionId, xHttpPhysicalConnection.Remote);
                GenuineUtility.CopyStreamToStreamPhysically(sentContent, syncSocketWritingStream, xHttpPhysicalConnection.AsyncSendBuffer);

                // automatically start receiving the response/request
                if (startAutomaticReceiving)
                {
                    if (xHttpPhysicalConnection.XHttpConnection.IsClient)
                        this.LowLevel_HalfSync_Client_StartReceiving(xHttpPhysicalConnection);
                    else
                        this.LowLevel_HalfSync_Server_StartReceiving(xHttpPhysicalConnection.Socket);
                }
            }
            else
            {
                xHttpPhysicalConnection.AsyncSendBufferCurrentPosition = 0;
                xHttpPhysicalConnection.AsyncSendBufferIsLastPacket = false;
                xHttpPhysicalConnection.AsyncSendBufferSizeOfValidContent = 0;
                xHttpPhysicalConnection.AsyncSendStream = sentContent;

                this.LowLevel_InitiateAsyncSending(xHttpPhysicalConnection);
            }
        }
        /// <summary>
        /// Closes the specified connections to the remote host and releases acquired resources.
        /// </summary>
        /// <param name="hostInformation">Host information.</param>
        /// <param name="genuineConnectionType">What kind of connections will be affected by this operation.</param>
        /// <param name="reason">Reason of resource releasing.</param>
        public override void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            ArrayList connectionsToClose = new ArrayList();

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.ReleaseConnections",
                    LogMessageType.ReleaseConnections, reason, null, hostInformation, null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    null, null, -1, 0, 0, 0, Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null, null, null,
                    "Connections \"{0}\" are terminated.", Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null);
            }

            using (new WriterAutoLocker(this._disposeLock))
            {
                // persistent
                if ( (genuineConnectionType & GenuineConnectionType.Persistent) != 0 )
                {
                    ReleaseConnections_Parameters releaseConnections_Parameters = new ReleaseConnections_Parameters();
                    releaseConnections_Parameters.FailedConnections = connectionsToClose;
                    releaseConnections_Parameters.HostInformation = hostInformation;

                    this._persistent.InspectAllConnections(this._releaseConnections_InspectPersistentConnections, releaseConnections_Parameters);
                }
            }

            // close connections
            foreach (XHttpConnection nextXHttpConnection in connectionsToClose)
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.ReleaseConnections",
                        LogMessageType.ConnectionShuttingDown, reason, null, hostInformation, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        null, null, nextXHttpConnection.DbgConnectionId, 0, 0, 0, Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null, null, null,
                        "Connection is terminated.");
                }

                this.ConnectionFailed(GenuineExceptions.Get_Channel_ConnectionShutDown(reason), nextXHttpConnection, null);

                if (nextXHttpConnection.GenuineConnectionType == GenuineConnectionType.Persistent)
                    nextXHttpConnection.SignalState(GenuineEventType.GeneralConnectionClosed, reason, null);
            }
        }
        /// <summary>
        /// Parses HTTP request or response.
        /// </summary>
        /// <param name="timeout">The reading timeout.</param>
        /// <param name="client">Specifies the parsing logic.</param>
        /// <param name="socket">The connection.</param>
        /// <param name="connectionLevelSecurity">Connection-level Security Session.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="uri">The URI of the remote host.</param>
        /// <param name="sequenceNo">The sequence no of the parsing packet.</param>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <param name="hostId">The identifier of the host.</param>
        /// <param name="httpPacketType">The type of the HTTP packet.</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>
        /// <returns>A stream based on the specified socket.</returns>
        private Stream LowLevel_ParseHttpContent(int timeout, bool client, Socket socket, SecuritySession connectionLevelSecurity, out byte protocolVersion, out string uri, out int sequenceNo, out GenuineConnectionType genuineConnectionType, out Guid hostId, out HttpPacketType httpPacketType, out string connectionName, out int remoteHostUniqueIdentifier)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            protocolVersion = MessageCoder.PROTOCOL_VERSION;
            uri = null;
            genuineConnectionType = GenuineConnectionType.None;
            hostId = Guid.Empty;
            httpPacketType = HttpPacketType.Unkown;
            connectionName = null;

            // read the entire header
            Stream inputStream = new BufferedStream(new SyncSocketStream(socket, this, timeout));

            int contentLength = -1;

            #if DEBUG
            GenuineChunkedStream httpHeadersContent = new GenuineChunkedStream(false);
            StreamWriter httpTraffic = new StreamWriter(httpHeadersContent);
            #endif

            GXHTTPHeaderParser gxhttpHeaderParser = new GXHTTPHeaderParser(client);
            int indexOfFirstDigit;
            int indexOfLastDigit;

            for ( ; ; )
            {
                string line = this.LowLevel_ReadToUpperLine(inputStream, out indexOfFirstDigit, out indexOfLastDigit);

            #if DEBUG
                httpTraffic.Write(line);
                httpTraffic.Write(Environment.NewLine);
            #endif

                if (line.Length <= 0)
                    break;

                if (gxhttpHeaderParser.ParseHeader(line, indexOfFirstDigit, indexOfLastDigit) == GXHTTPHeaderParser.HeaderFields.Expect100Continue && gxhttpHeaderParser.IsHttp11)
                    this.LowLevel_Send100Continue(socket);
            }

            contentLength = (int) gxhttpHeaderParser.ContentLength;

            #if DEBUG
            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0 )
            {
                binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "XHttpConnectionManager.LowLevel_ParseHttpContent",
                    LogMessageType.LowLevelTransport_SyncReceivingCompleted, null, null, null,
                    binaryLogWriter[LogCategory.LowLevelTransport] > 1 ? httpHeadersContent : null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    -1, contentLength, socket.RemoteEndPoint.ToString(),
                    null, null,
                    "XHTTP Headers parsed. Content Length: {0}.", contentLength);
            }

            httpHeadersContent.Dispose();
            #endif

            // ok, the header has been successfully skipped
            if (contentLength < 0)
                throw GenuineExceptions.Get_Receive_IncorrectData();

            // TODO: fix this! there is socket -> buffer -> delimiter chain, while it must be socket -> delimiter -> buffer
            // and we know the content length
            inputStream = new DelimiterStream(inputStream, contentLength);

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0 )
            {
                GenuineChunkedStream contentCopy = null;
                bool writeContent = binaryLogWriter[LogCategory.LowLevelTransport] > 1;
                if (writeContent)
                {
                    contentCopy = new GenuineChunkedStream(false);
                    GenuineUtility.CopyStreamToStream(inputStream, contentCopy, contentLength);
                }

                binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "XHttpConnectionManager.LowLevel_ParseHttpContent",
                    LogMessageType.LowLevelTransport_SyncReceivingCompleted, null, null, null,
                    writeContent ? contentCopy : null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    -1, contentLength, socket.RemoteEndPoint.ToString(),
                    null, null,
                    "XHTTP Message.", contentLength);

                if (writeContent)
                    inputStream = contentCopy;
            }

            // server always encrypts the entire content, including response headers
            if (client && connectionLevelSecurity != null && connectionLevelSecurity.IsEstablished)
                inputStream = connectionLevelSecurity.Decrypt(inputStream);

            BinaryReader binaryReader = new BinaryReader(inputStream);

            // read binary header
            if (client)
                HttpMessageCoder.ReadResponseHeader(binaryReader, out uri, out sequenceNo, out httpPacketType, out remoteHostUniqueIdentifier);
            else
                HttpMessageCoder.ReadRequestHeader(binaryReader, out protocolVersion, out genuineConnectionType, out hostId, out httpPacketType, out sequenceNo, out connectionName, out remoteHostUniqueIdentifier);

            return inputStream;
        }
示例#16
0
 /// <summary>
 /// Closes the specified connections to the remote host and releases acquired resources.
 /// </summary>
 /// <param name="hostInformation">Host information.</param>
 /// <param name="genuineConnectionType">What kind of connections will be affected by this operation.</param>
 /// <param name="reason">Reason of resource releasing.</param>
 public override void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason)
 {
 }
        /// <summary>
        /// Closes the specified connections to the remote host and releases acquired resources.
        /// </summary>
        /// <param name="hostInformation">Host information.</param>
        /// <param name="genuineConnectionType">What kind of connections will be affected by this operation.</param>
        /// <param name="reason">Reason of resource releasing.</param>
        public override void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            HttpClientConnection httpClientConnection = null;
            ArrayList connectionsToClose = new ArrayList();

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpClientConnectionManager.ReleaseConnections",
                    LogMessageType.ReleaseConnections, reason, null, hostInformation, null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    null, null, -1, 0, 0, 0, Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null, null, null,
                    "\"{0}\" connections will be terminated.", Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null);
            }

            // TODO: 2.5.3. fix (deadlock by design), will be completely fixed in 3.0
            //			using (new WriterAutoLocker(this._disposeLock))
            {
                // persistent
                if ( (genuineConnectionType & GenuineConnectionType.Persistent) != 0 )
                    lock (this._persistent.SyncRoot)
                    {
                        foreach (DictionaryEntry entry in this._persistent)
                        {
                            httpClientConnection = (HttpClientConnection) entry.Value;
                            if (hostInformation != null && httpClientConnection.Remote != hostInformation)
                                continue;

                            connectionsToClose.Add(httpClientConnection);
                        }
                    }

                // close connections
                foreach (HttpClientConnection nextHttpClientConnection in connectionsToClose)
                {
                    // LOG:
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                    {
                        binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpClientConnectionManager.ReleaseConnections",
                            LogMessageType.ConnectionShuttingDown, reason, null, nextHttpClientConnection.Remote, null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                            nextHttpClientConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                            "The connection is being shut down manually.");
                    }

                    this.ConnectionFailed(nextHttpClientConnection, true, GenuineExceptions.Get_Channel_ConnectionShutDown(reason), false);

                    if (nextHttpClientConnection.GenuineConnectionType == GenuineConnectionType.Persistent)
                    {
                        nextHttpClientConnection.SignalState(GenuineEventType.GeneralConnectionClosed, reason, null);
                    }
                }
            }
        }
        /// <summary>
        /// Closes the specified connections to the remote host and releases acquired resources.
        /// </summary>
        /// <param name="hostInformation">Host information or a null reference to close all connection according to specified types.</param>
        /// <param name="genuineConnectionType">What kind of connections will be affected by this operation.</param>
        /// <param name="reason">Reason of resource releasing.</param>
        public override void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason)
        {
            TcpSocketInfo tcpSocketInfo = null;
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.ReleaseConnections",
                    LogMessageType.ReleaseConnections, reason, null, hostInformation, null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    null, null, -1, 0, 0, 0, Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null, null, null,
                    "Connections \"{0}\" are terminated.", Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null);
            }

            // go through all connections and close such of them that fall under the specified category
            ArrayList failedConnections = new ArrayList();

            // persistent
            ReleaseConnections_Parameters releaseConnections_Parameters = new ReleaseConnections_Parameters();
            releaseConnections_Parameters.FailedConnections = failedConnections;
            releaseConnections_Parameters.HostInformation = hostInformation;
            releaseConnections_Parameters.GenuineConnectionType = genuineConnectionType;

            this._persistent.InspectAllConnections(this._releaseConnections_InspectPersistentConnections, releaseConnections_Parameters);

            // named
            if ( (genuineConnectionType & GenuineConnectionType.Persistent) != 0 || (genuineConnectionType & GenuineConnectionType.Named) != 0)
                lock (this._named)
                {
                    foreach (DictionaryEntry entry in this._named)
                    {
                        tcpSocketInfo = (TcpSocketInfo) entry.Value;
                        if (hostInformation != null && tcpSocketInfo.Remote != hostInformation)
                            continue;
                        if ( (genuineConnectionType & tcpSocketInfo.GenuineConnectionType) == 0)
                            continue;

                        failedConnections.Add(tcpSocketInfo);
                    }
                }

            // invocation
            if ( (genuineConnectionType & GenuineConnectionType.Invocation) != 0)
            {
                lock (this._invocation.SyncRoot)
                    foreach (DictionaryEntry entry in this._invocation)
                    {
                        ArrayList connections = (ArrayList) entry.Value;
                        lock (connections)
                        {
                            foreach (TcpSocketInfo nextTcpSocketInfo in connections)
                            {
                                if (hostInformation != null && nextTcpSocketInfo.Remote != hostInformation)
                                    continue;

                                failedConnections.Add(nextTcpSocketInfo);
                            }
                        }
                    }

                lock (this._knownInvocationConnections.SyncRoot)
                    foreach (DictionaryEntry entry in this._knownInvocationConnections)
                    {
                        tcpSocketInfo = (TcpSocketInfo) entry.Value;
                        if (hostInformation != null && tcpSocketInfo.Remote != hostInformation)
                            continue;

                        failedConnections.Add(tcpSocketInfo);
                    }
            }

            // close connections
            foreach (TcpSocketInfo failedTcpSocketInfo in failedConnections)
            {
                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "TcpConnectionManager.ReleaseConnections",
                        LogMessageType.ConnectionShuttingDown, reason, null, failedTcpSocketInfo.Remote, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        null, null, failedTcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null,
                        "The connection is terminated.");
                }

                this.SocketFailed(GenuineExceptions.Get_Channel_ConnectionShutDown(reason), failedTcpSocketInfo);

                if (failedTcpSocketInfo.GenuineConnectionType == GenuineConnectionType.Persistent)
                    failedTcpSocketInfo.SignalState(GenuineEventType.GeneralConnectionClosed, reason, null);
            }
        }
        /// <summary>
        /// Closes the specified connections to the remote host and releases acquired resources.
        /// </summary>
        /// <param name="hostInformation">Host information.</param>
        /// <param name="genuineConnectionType">What kind of connections will be affected by this operation.</param>
        /// <param name="reason">The reason of resource releasing.</param>
        public override void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;
            ArrayList connectionsToClose = new ArrayList();

            using (new WriterAutoLocker(this._disposeLock))
            {
                if (this._disposed)
                    return ;

                // LOG:
                if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                {
                    binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.ReleaseConnections",
                        LogMessageType.ReleaseConnections, reason, null, hostInformation, null,
                        GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                        null, null, -1, 0, 0, 0, Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null, null, null,
                        "Connections \"{0}\" will be terminated.", Enum.Format(typeof(GenuineConnectionType), genuineConnectionType, "g"), null);
                }

                // persistent
                if ( (genuineConnectionType & GenuineConnectionType.Persistent) != 0 )
                {
                    // persistent
                    ReleaseConnections_Parameters releaseConnections_Parameters = new ReleaseConnections_Parameters();
                    releaseConnections_Parameters.FailedConnections = connectionsToClose;
                    releaseConnections_Parameters.HostInformation = hostInformation;

                    this._persistent.InspectAllConnections(this._releaseConnections_InspectPersistentConnections, releaseConnections_Parameters);
                }

                // close connections
                foreach (HttpServerConnection nextHttpServerConnection in connectionsToClose)
                {
                    lock (nextHttpServerConnection.Listener_Lock)
                    {
                        // LOG:
                        if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                        {
                            binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpClientConnectionManager.ReleaseConnections",
                                LogMessageType.ConnectionShuttingDown, reason, null, nextHttpServerConnection.Remote, null,
                                GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                                nextHttpServerConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                "The connection is being shut down manually.");
                        }

                        nextHttpServerConnection.SignalState(GenuineEventType.GeneralConnectionClosed, reason, null);

                        this._persistent.Remove(nextHttpServerConnection.Remote.Uri, nextHttpServerConnection.ConnectionName);
                        if (nextHttpServerConnection.Listener != null)
                            this.Pool_SendThroughListener(nextHttpServerConnection, HttpPacketType.ClosedManually);
                    }
                }
            }
        }
        /// <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>
        /// Analyzes the version of the requested protocol and reads type of the connection.
        /// Throws OperationException on any errors.
        /// </summary>
        /// <param name="binaryReader">BinaryReader created on the stream with data.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="genuineConnectionType">Read type of the connection.</param>
        /// <param name="connectionId">The connection identifier.</param>
        public static void DeserializeConnectionHeader(BinaryReader binaryReader, out byte protocolVersion, out GenuineConnectionType genuineConnectionType, out string connectionId)
        {
            connectionId = "/__GC/Default";

            protocolVersion = binaryReader.ReadByte();

            genuineConnectionType = (GenuineConnectionType) binaryReader.ReadByte();
            if (! Enum.IsDefined(typeof(GenuineConnectionType), genuineConnectionType) || genuineConnectionType == GenuineConnectionType.None || genuineConnectionType == GenuineConnectionType.All)
                throw GenuineExceptions.Get_Connect_CanNotAcceptIncomingConnection("Incorrect type of the connection.");

            if (protocolVersion > 0)
            {
                connectionId = binaryReader.ReadString();
                if (connectionId == null || connectionId.Length <= 0)
                    throw GenuineExceptions.Get_Connect_CanNotAcceptIncomingConnection("Incorrect name of the connection.");
            }
        }
示例#22
0
        /// <summary>
        /// Parses the HTTP header.
        /// </summary>
        /// <param name="binaryReader">The source binary reader.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="genuineConnectionType">The type of connection.</param>
        /// <param name="hostId">The identifier of the remote host.</param>
        /// <param name="httpPacketType">The type of the packet.</param>
        /// <param name="sequenceNo">The packet number.</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>
        public static void ReadRequestHeader(BinaryReader binaryReader, out byte protocolVersion, out GenuineConnectionType genuineConnectionType, out Guid hostId, out HttpPacketType httpPacketType, out int sequenceNo, out string connectionName, out int remoteHostUniqueIdentifier)
        {
            if (binaryReader.ReadByte() != MessageCoder.COMMAND_MAGIC_CODE)
            {
                throw GenuineExceptions.Get_Receive_IncorrectData();
            }

            protocolVersion       = binaryReader.ReadByte();
            genuineConnectionType = (GenuineConnectionType)binaryReader.ReadByte();
            hostId         = new Guid(binaryReader.ReadBytes(16));
            httpPacketType = (HttpPacketType)binaryReader.ReadByte();
            sequenceNo     = binaryReader.ReadInt32();

            connectionName             = "$/__GC/" + hostId;
            remoteHostUniqueIdentifier = 0;

            if (protocolVersion >= 0x1)
            {
                connectionName             = binaryReader.ReadString();
                remoteHostUniqueIdentifier = binaryReader.ReadInt32();
            }
        }
 /// <summary>
 /// Writes HTTP header to the specified binary writer.
 /// </summary>
 /// <param name="binaryWriter">The binary writer.</param>
 /// <param name="protocolVersion">The version of the protocol.</param>
 /// <param name="genuineConnectionType">The type of connection.</param>
 /// <param name="hostId">The id of the remote host.</param>
 /// <param name="httpPacketType">The type of the packet.</param>
 /// <param name="sequenceNo">The packet number.</param>
 /// <param name="connectionName">The name of the connection.</param>
 /// <param name="localHostUniqueIdentifier">The unique identifier of the local HostInformation.</param>
 public static void WriteRequestHeader(BinaryWriter binaryWriter, byte protocolVersion, GenuineConnectionType genuineConnectionType, byte[] hostId, HttpPacketType httpPacketType, int sequenceNo, string connectionName, int localHostUniqueIdentifier)
 {
     binaryWriter.Write((byte) MessageCoder.COMMAND_MAGIC_CODE);
     binaryWriter.Write((byte) protocolVersion);
     binaryWriter.Write((byte) genuineConnectionType);
     binaryWriter.Write(hostId);
     binaryWriter.Write((byte) httpPacketType);
     binaryWriter.Write((int) sequenceNo);
     binaryWriter.Write(connectionName);
     binaryWriter.Write((int) localHostUniqueIdentifier);
 }
 /// <summary>
 /// Closes the specified connections to the remote host and releases acquired resources.
 /// </summary>
 /// <param name="hostInformation">Host information.</param>
 /// <param name="genuineConnectionType">What kind of connections will be affected by this operation.</param>
 /// <param name="reason">Reason of resource releasing.</param>
 public override void ReleaseConnections(HostInformation hostInformation, GenuineConnectionType genuineConnectionType, Exception reason)
 {
 }
示例#25
0
        /// <summary>
        /// Analyzes the version of the requested protocol and reads type of the connection.
        /// Throws OperationException on any errors.
        /// </summary>
        /// <param name="binaryReader">BinaryReader created on the stream with data.</param>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="genuineConnectionType">Read type of the connection.</param>
        /// <param name="connectionId">The connection identifier.</param>
        public static void DeserializeConnectionHeader(BinaryReader binaryReader, out byte protocolVersion, out GenuineConnectionType genuineConnectionType, out string connectionId)
        {
            connectionId = "/__GC/Default";

            protocolVersion = binaryReader.ReadByte();

            genuineConnectionType = (GenuineConnectionType)binaryReader.ReadByte();
            if (!Enum.IsDefined(typeof(GenuineConnectionType), genuineConnectionType) || genuineConnectionType == GenuineConnectionType.None || genuineConnectionType == GenuineConnectionType.All)
            {
                throw GenuineExceptions.Get_Connect_CanNotAcceptIncomingConnection("Incorrect type of the connection.");
            }

            if (protocolVersion > 0)
            {
                connectionId = binaryReader.ReadString();
                if (connectionId == null || connectionId.Length <= 0)
                {
                    throw GenuineExceptions.Get_Connect_CanNotAcceptIncomingConnection("Incorrect name of the connection.");
                }
            }
        }
        /// <summary>
        /// Creates and returns the Connection Level Security Session.
        /// </summary>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <returns>The created Security Session.</returns>
        internal SecuritySession CreateConnectionLevelSecuritySession(GenuineConnectionType genuineConnectionType)
        {
            // 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;
            }

            // create and return the Security Session
            if (connectionLevelSSName != null)
                return this.ITransportContext.IKeyStore.GetKey(connectionLevelSSName).CreateSecuritySession(connectionLevelSSName, null);

            return null;
        }
        /// <summary>
        /// Constructs an instance of the SecuritySessionParameters class.
        /// </summary>
        /// <param name="securitySessionName">The name of the Security Session.</param>
        /// <param name="securitySessionAttributes">Security Session parameters.</param>
        /// <param name="timeout">The invocation timeout or the TimeSpan.MinValue value to inherit the timeout from channel or Transport Context settings.</param>
        public SecuritySessionParameters(string securitySessionName, SecuritySessionAttributes securitySessionAttributes, TimeSpan timeout)
        {
            this.Name = securitySessionName;
            this.Attributes = securitySessionAttributes;
            this.Timeout = timeout;

            this._genuineConnectionType = GenuineConnectionType.Persistent;
        }
        /// <summary>
        /// Returns a stream containing version of the using protocol and type of the connection being established.
        /// </summary>
        /// <param name="protocolVersion">The version of the protocol.</param>
        /// <param name="genuineConnectionType">Type of the connection.</param>
        /// <param name="connectionId">The identifier of the connection.</param>
        /// <returns>BinaryWriter containing a stream with serialized data.</returns>
        public static BinaryWriter SerializeConnectionHeader(byte protocolVersion, GenuineConnectionType genuineConnectionType, string connectionId)
        {
            GenuineChunkedStream stream = new GenuineChunkedStream(false);
            BinaryWriter binaryWriter = new BinaryWriter(stream);
            binaryWriter.Write((byte) protocolVersion);
            binaryWriter.Write((byte) genuineConnectionType);
            binaryWriter.Write((string) connectionId);

            return binaryWriter;
        }
        /// <summary>
        /// Opens connection to the remote host.
        /// </summary>
        /// <param name="remote">The remote host.</param>
        /// <param name="genuineConnectionType">The type of the connection.</param>
        /// <param name="connectionName">The name of the connection.</param>
        /// <returns>The opened connection.</returns>
        private HttpClientConnection LowLevel_OpenConnection(HostInformation remote, GenuineConnectionType genuineConnectionType, string connectionName)
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

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

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

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpClientConnectionManager.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}\".", remote == null ? "?" : remote.Url == null ? "?" : remote.Url);
            }

            // first - send the check request and start CLSSE
            HttpClientConnection httpClientConnection = new HttpClientConnection(this.ITransportContext, connectionName);
            httpClientConnection.Remote = remote;
            httpClientConnection.GenuineConnectionType = genuineConnectionType;

            httpClientConnection.Sender_ConnectionLevelSecurity = this.CreateConnectionLevelSecuritySession(genuineConnectionType);
            httpClientConnection.Listener_ConnectionLevelSecurity = this.CreateConnectionLevelSecuritySession(genuineConnectionType);

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

            // gather the output stream
            Stream senderInputClsseStream = Stream.Null;
            Stream listenerInputClsseStream = Stream.Null;
            Stream clsseStream = null;
            GenuineChunkedStream outputStream = null;
            bool resend = false;
            bool firstFailure = false;

            // CLSS establishing
            for ( int i = 0; ; i++ )
            {
                bool noClsseToSend = true;

                if (! resend)
                {
                    // build the content
                    outputStream = new GenuineChunkedStream(false);
                    BinaryWriter binaryWriter = new BinaryWriter(outputStream);
                    HttpMessageCoder.WriteRequestHeader(binaryWriter, MessageCoder.PROTOCOL_VERSION, genuineConnectionType, httpClientConnection.HostId,
                        i == 0 ? HttpPacketType.Establishing_ResetConnection : HttpPacketType.Establishing, ++httpClientConnection.SendSequenceNo,
                        httpClientConnection.ConnectionName, remote.LocalHostUniqueIdentifier);

                    // CLSSE info
                    using (new GenuineChunkedStreamSizeLabel(outputStream))
                    {
                        if (httpClientConnection.Sender_ConnectionLevelSecurity != null && ! httpClientConnection.Sender_ConnectionLevelSecurity.IsEstablished)
                        {
                            clsseStream = httpClientConnection.Sender_ConnectionLevelSecurity.EstablishSession(senderInputClsseStream, true);
                            if (clsseStream != null)
                            {
                                noClsseToSend = false;
                                GenuineUtility.CopyStreamToStream(clsseStream, outputStream);
                            }
                        }

                    }

                    // CLSSE info
                    using (new GenuineChunkedStreamSizeLabel(outputStream))
                    {
                        if (httpClientConnection.Listener_ConnectionLevelSecurity != null && ! httpClientConnection.Listener_ConnectionLevelSecurity.IsEstablished)
                        {
                            clsseStream = httpClientConnection.Listener_ConnectionLevelSecurity.EstablishSession(listenerInputClsseStream, true);
                            if (clsseStream != null)
                            {
                                noClsseToSend = false;
                                GenuineUtility.CopyStreamToStream(clsseStream, outputStream);
                            }
                        }
                    }
                }
                else
                    outputStream.Position = 0;

                // parse the response
                HttpWebRequest httpWebRequest = httpClientConnection.InitializeRequest(true, httpClientConnection._keepalive);
                int millisecondsRemain = GenuineUtility.CompareTickCounts(timeout, GenuineUtility.TickCount);
                if ( millisecondsRemain <= 0)
                    throw GenuineExceptions.Get_Channel_ConnectionClosedAfterTimeout();

                httpWebRequest.Timeout = millisecondsRemain;
                httpWebRequest.ContentLength = outputStream.Length;
                Stream requestStream = null;

                try
                {
                    requestStream = httpWebRequest.GetRequestStream();
                    GenuineUtility.CopyStreamToStream(outputStream, requestStream, (int) outputStream.Length);
                    using (HttpWebResponse httpWebResponse = (HttpWebResponse) httpWebRequest.GetResponse())
                    {
                        // LOG:
                        if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                        {
                            StringBuilder stringBuilderHeaders = new StringBuilder(1024);
                            foreach (string headerName in httpWebResponse.Headers.Keys)
                                stringBuilderHeaders.AppendFormat("{0}=\"{1}\"; ", headerName, httpWebResponse.Headers.Get(headerName));

                            binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpClientConnectionManager.LowLevel_OpenConnection",
                                LogMessageType.ConnectionEstablishing, null, null, remote, null,
                                GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                                httpClientConnection.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                "The trial connection has been successfully completed. Content-Length: {0}; Content encoding: {1}; Content type: {2}; Protocol version: {3}; Respose uri: {4}; Status code: {5}; Status description: {6}; HTTP headers: {7}.",
                                httpWebResponse.ContentLength, httpWebResponse.ContentEncoding, httpWebResponse.ContentType,
                                httpWebResponse.ProtocolVersion, httpWebResponse.ResponseUri,
                                httpWebResponse.StatusCode, httpWebResponse.StatusDescription,
                                stringBuilderHeaders.ToString());
                        }

                        using (Stream responseStream = httpWebResponse.GetResponseStream())
                        {
                            BinaryReader binaryReader = new BinaryReader(responseStream);
                            string serverUri;
                            int sequenceNo;
                            HttpPacketType httpPacketType;
                            int remoteHostUniqueIdentifier;

                            HttpMessageCoder.ReadResponseHeader(binaryReader, out serverUri, out sequenceNo, out httpPacketType, out remoteHostUniqueIdentifier);

                            if ( httpPacketType != HttpPacketType.Establishing && httpPacketType != HttpPacketType.Establishing_ResetConnection )
                                throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(remote.ToString(), "Wrong response received from the remote host.");

                            // check the restartion if either CLSS or the persistent connection is used
                            if (genuineConnectionType == GenuineConnectionType.Persistent || httpClientConnection.Sender_ConnectionLevelSecurity != null)
                                remote.UpdateUri(serverUri, remoteHostUniqueIdentifier);

                            // the first SS
                            int writtenSize = binaryReader.ReadInt32();
                            senderInputClsseStream = new GenuineChunkedStream(true);
                            GenuineUtility.CopyStreamToStream(responseStream, senderInputClsseStream, writtenSize);

                            writtenSize = binaryReader.ReadInt32();
                            listenerInputClsseStream = new GenuineChunkedStream(true);
                            GenuineUtility.CopyStreamToStream(responseStream, listenerInputClsseStream, writtenSize);
                        }
                    }

                    outputStream.Close();
                }
                catch(Exception ex)
                {
                    if (firstFailure)
                        throw;

                    // LOG:
                    if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
                    {
                        binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpClientConnectionManager.LowLevel_OpenConnection",
                            LogMessageType.ConnectionEstablishing, ex, null, remote, null,
                            GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                            -1, 0, 0, 0, null, null, null, null,
                            "Exception occurred while establishing the connection to \"{0}\". The connection establishing will be continued.", remote == null ? "?" : remote.Url == null ? "?" : remote.Url);
                    }

                    // try to recover
                    resend = true;
                    continue;
                }
                finally
                {
                    if (requestStream != null)
                        requestStream.Close();
                }

                firstFailure = false;
                resend = false;

                if (httpClientConnection.Sender_ConnectionLevelSecurity != null && ! httpClientConnection.Sender_ConnectionLevelSecurity.IsEstablished)
                    continue;
                if (httpClientConnection.Listener_ConnectionLevelSecurity != null && ! httpClientConnection.Listener_ConnectionLevelSecurity.IsEstablished)
                    continue;
                if (! noClsseToSend)
                    continue;

                break;
            }

            // start listener if it's a persistent connection
            remote.PhysicalAddress = remote.Url;

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

            // LOG:
            if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 )
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpClientConnectionManager.LowLevel_OpenConnection",
                    LogMessageType.ConnectionEstablished, null, null, remote, null,
                    GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                    httpClientConnection.Sender_ConnectionLevelSecurity,
                    httpClientConnection.Sender_ConnectionLevelSecurity == null ? null : httpClientConnection.Sender_ConnectionLevelSecurity.Name,
                    httpClientConnection.DbgConnectionId, (int) genuineConnectionType, 0, 0, this.GetType().Name, remote.Url, remote.Url, null,
                    "The connection to the remote host is established.");
            }

            if (genuineConnectionType == GenuineConnectionType.Persistent)
                this.LowLevel_InitiateListening(httpClientConnection, true);
            return httpClientConnection;
        }
示例#30
0
        /// <summary>
        /// Constructs an instance of the SecuritySessionParameters class.
        /// </summary>
        /// <param name="securitySessionName">The name of the Security Session.</param>
        /// <param name="securitySessionAttributes">Security Session parameters.</param>
        /// <param name="timeout">The invocation timeout or the TimeSpan.MinValue value to inherit the timeout from channel or Transport Context settings.</param>
        /// <param name="genuineConnectionType">Type of the connection being used. The connection type must be support by the corresponding connection manager.</param>
        /// <param name="connecitonName">The name of the connection if named connection type is specified.</param>
        /// <param name="closeAfterInactivity">The time of inactivity to close a connection or TimeSpan.MinValue to inherit this value from channel or Transport Context parameters.</param>
        /// <param name="remoteTransportUser">For load balancing or dispatching the invocation to the specific known appdomain.</param>
        public SecuritySessionParameters(string securitySessionName, SecuritySessionAttributes securitySessionAttributes, TimeSpan timeout, GenuineConnectionType genuineConnectionType, string connecitonName, TimeSpan closeAfterInactivity, string remoteTransportUser)
        {
            this.Name       = securitySessionName;
            this.Attributes = securitySessionAttributes;
            this.Timeout    = timeout;

            this._genuineConnectionType = genuineConnectionType;
            this._connectionName        = connecitonName;
            this.CloseAfterInactivity   = closeAfterInactivity;
            this.RemoteTransportUser    = remoteTransportUser;
        }
        /// <summary>
        /// Constructs an instance of the SecuritySessionParameters class.
        /// </summary>
        /// <param name="securitySessionName">The name of the Security Session.</param>
        public SecuritySessionParameters(string securitySessionName)
        {
            this.Name = securitySessionName;

            this._genuineConnectionType = GenuineConnectionType.Persistent;
        }