/// <summary> /// Initiates an asynchronous call to the HTTP handler. /// </summary> /// <param name="context">An HttpContext object that provides references to intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> /// <param name="cb">The AsyncCallback to call when the asynchronous method call is complete. If cb is a null reference (Nothing in Visual Basic), the delegate is not called.</param> /// <param name="extraData">Any extra data needed to process the request.</param> /// <returns>An IAsyncResult that contains information about the status of the process.</returns> public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { try { HttpServerRequestResult httpServerRequestResult = new HttpServerRequestResult(context, cb, extraData); httpServerRequestResult.IPrincipal = Thread.CurrentPrincipal; lock (this._httpServerConnectionManagerLock) if (this._httpServerConnectionManager == null) { GenuineHttpServerChannel serverChannel = ChannelServices.GetChannel("ghttp") as GenuineHttpServerChannel; if (serverChannel == null) { throw GenuineExceptions.Get_Receive_NoServerChannel(); } this._httpServerConnectionManager = serverChannel.ITransportContext.ConnectionManager as HttpServerConnectionManager; } // GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this._httpServerConnectionManager.HandleIncomingRequest), httpServerRequestResult, true); this._httpServerConnectionManager.HandleIncomingRequest(httpServerRequestResult); return(httpServerRequestResult); } catch (Exception ex) { // LOG: BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; if (binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0) { binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "HttpServerHandler.BeginProcessRequest", LogMessageType.ConnectionAccepting, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Can't process an incoming connection."); } throw; } }
/// <summary> /// Initiates an asynchronous call to the HTTP handler. /// </summary> /// <param name="context">An HttpContext object that provides references to intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> /// <param name="cb">The AsyncCallback to call when the asynchronous method call is complete. If cb is a null reference (Nothing in Visual Basic), the delegate is not called.</param> /// <param name="extraData">Any extra data needed to process the request.</param> /// <returns>An IAsyncResult that contains information about the status of the process.</returns> public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { try { HttpServerRequestResult httpServerRequestResult = new HttpServerRequestResult(context, cb, extraData); httpServerRequestResult.IPrincipal = Thread.CurrentPrincipal; lock (this._httpServerConnectionManagerLock) if (this._httpServerConnectionManager == null) { GenuineHttpServerChannel serverChannel = ChannelServices.GetChannel("ghttp") as GenuineHttpServerChannel; if (serverChannel == null) throw GenuineExceptions.Get_Receive_NoServerChannel(); this._httpServerConnectionManager = serverChannel.ITransportContext.ConnectionManager as HttpServerConnectionManager; } // GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this._httpServerConnectionManager.HandleIncomingRequest), httpServerRequestResult, true); this._httpServerConnectionManager.HandleIncomingRequest(httpServerRequestResult); return httpServerRequestResult; } catch(Exception ex) { // LOG: BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; if ( binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "HttpServerHandler.BeginProcessRequest", LogMessageType.ConnectionAccepting, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Can't process an incoming connection."); } throw; } }
/// <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> /// 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); }
/// <summary> /// Handles the listener request. /// </summary> /// <param name="httpServerRequestResult">The request.</param> /// <param name="httpServerConnection">The connection.</param> /// <param name="requestedSequenceNo">The sequence number.</param> /// <returns>True if the response should be delayed.</returns> public bool LowLevel_ProcessListenerRequest(HttpServerRequestResult httpServerRequestResult, HttpServerConnection httpServerConnection, int requestedSequenceNo) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; GenuineChunkedStream responseStream = null; lock (httpServerConnection.Listener_Lock) { // if there is an already registered listener request, release it if (httpServerConnection.Listener != null) { try { this.LowLevel_ReportServerError(httpServerConnection.Listener.HttpContext); } finally { httpServerConnection.Listener.Complete(false); httpServerConnection.Listener = null; } } try { Debug.Assert(httpServerConnection.Listener == null); // if the previous content requested - send it if (requestedSequenceNo == httpServerConnection.Listener_SequenceNo && httpServerConnection.Listener_SentStream != null) { httpServerConnection.Listener_SentStream.Position = 0; this.LowLevel_SendStream(httpServerRequestResult.HttpContext, true, httpServerConnection, false, ref httpServerConnection.Listener_SentStream, httpServerConnection); return false; } // if too old content version requested - send an error if (requestedSequenceNo < httpServerConnection.Listener_SequenceNo || requestedSequenceNo > httpServerConnection.Listener_SequenceNo + 1) { // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { string errorMessage = string.Format("Desynchronization error. Current sequence number: {0}. Requested sequence number: {1}.", httpServerConnection.Listener_SequenceNo, requestedSequenceNo); binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.LowLevel_ProcessListenerRequest", LogMessageType.Error, GenuineExceptions.Get_Debugging_GeneralWarning(errorMessage), null, httpServerConnection.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, httpServerConnection.DbgConnectionId, 0, 0, 0, null, null, null, null, errorMessage); } // send the error Stream errorResponseStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.Desynchronization, requestedSequenceNo, httpServerConnection.Remote); MessageCoder.FillInLabelledStream(null, null, null, (GenuineChunkedStream) errorResponseStream, httpServerConnection.Listener_IntermediateBuffer, (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]); this.LowLevel_SendStream(httpServerRequestResult.HttpContext, true, httpServerConnection, true, ref errorResponseStream, httpServerConnection); return false; } // the next sequence is requested if (httpServerConnection.Listener_SentStream != null) { // release the content httpServerConnection.Listener_MessagesBeingSent.Clear(); httpServerConnection.Listener_SentStream.Close(); httpServerConnection.Listener_SentStream = null; } Message message = httpServerConnection.Listener_MessageContainer.GetMessage(); if (message == null) { // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.LowLevel_ProcessListenerRequest", LogMessageType.ReceivingFinished, null, null, httpServerConnection.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, httpServerConnection.DbgConnectionId, 0, 0, 0, null, null, null, null, "Listener request is postponed."); } // no data is available, postpone the request httpServerConnection.Listener_Opened = GenuineUtility.TickCount; httpServerConnection.Listener = httpServerRequestResult; httpServerConnection.Listener_SequenceNo = requestedSequenceNo; return true; } // some data is available, gather the stream and send it responseStream = this.LowLevel_CreateStreamWithHeader(HttpPacketType.Usual, requestedSequenceNo, httpServerConnection.Remote); MessageCoder.FillInLabelledStream(message, httpServerConnection.Listener_MessageContainer, httpServerConnection.Listener_MessagesBeingSent, responseStream, httpServerConnection.Listener_IntermediateBuffer, (int) this.ITransportContext.IParameterProvider[GenuineParameter.HttpRecommendedPacketSize]); // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0 ) { for ( int i = 0; i < httpServerConnection.Listener_MessagesBeingSent.Count; i++) { Message nextMessage = (Message) httpServerConnection.Listener_MessagesBeingSent[i]; binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "HttpServerConnectionManager.LowLevel_ProcessListenerRequest", LogMessageType.MessageIsSentAsynchronously, null, nextMessage, httpServerConnection.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, httpServerConnection.Listener_SecuritySession, null, httpServerConnection.DbgConnectionId, httpServerConnection.Listener_SequenceNo, 0, 0, null, null, null, null, "The message is sent in the LISTENER stream N: {0}.", httpServerConnection.Listener_SequenceNo); } } httpServerConnection.Listener_SentStream = responseStream; httpServerConnection.Listener_SequenceNo = requestedSequenceNo; this.LowLevel_SendStream(httpServerRequestResult.HttpContext, true, httpServerConnection, true, ref httpServerConnection.Listener_SentStream, httpServerConnection); } catch(Exception ex) { // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "HttpServerConnectionManager.LowLevel_ProcessListenerRequest", 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 listener request N: {0}.", httpServerConnection.Listener_SequenceNo); } } } return false; }