// Process the given tcpStream until either // - ProcessStatus.Error OR // - ProcessStatus.NeedMoreData OR // - ProcessStatus.Completed // // ProcessStatus.Continue is hidden as this method will simply // loop internally, asking the current HttpMessage to continue processing // // see HttpMessage.Process() for return values from this method as they // are the same private HttpMessage.ProcessStatus HandleTcpStreamGenerator(TcpStreamGenerator tcpStreamGenerator) { var tcpStream = tcpStreamGenerator.tcpStream; var monitorType = tcpStreamGeneratorToMonitorType[tcpStreamGenerator]; if (IsDebugEnabled) { log.DebugFormat("monitorType: {0}", monitorType); } HttpMessage theMessage = null; // retrieve the pending message or create and assign a new one if there // is no pending message if (monitorType == MonitorTypes.Client) { if (pendingRequest == null) { if (IsDebugEnabled) { log.Debug("No pendingRequest, creating a new one"); } pendingRequest = new HttpRequest(); } theMessage = pendingRequest; } else if (monitorType == MonitorTypes.Server) { if (pendingStatus == null) { if (IsDebugEnabled) { log.Debug("no pendingStatus, creating a new one"); } pendingStatus = new HttpStatus(); } theMessage = pendingStatus; } BinaryReader br = new BinaryReader(tcpStream); // default to NeedMoreData since that would be our state if // we didn't get into the while() loop due to running out of data HttpMessage.ProcessStatus status = HttpMessage.ProcessStatus.NeedMoreData; // outer loop runs while we have bytes to process // // NOTE: We can process until we run out of data because we re-use // the same message for the given TcpStream while (br.BaseStream.Position < br.BaseStream.Length) { // if we haven't identified the monitor type yet, attempt to do so now if (monitorType == HttpSessionWatcher.MonitorTypes.Unknown) { // attempt to process as a request // NOTE: Must assign pendingRequest BEFORE calling ProcessBinaryReader() // which may pass the object if processing completes pendingRequest = new HttpRequest(); status = ProcessBinaryReader(pendingRequest, MonitorTypes.Client, br); if (status == HttpMessage.ProcessStatus.Error) { pendingRequest = null; // attempt to process as a status // NOTE: Must assign pendingStatus BEFORE calling ProcessBinaryReader() // which may pass the object if processing completes pendingStatus = new HttpStatus(); status = ProcessBinaryReader(pendingStatus, MonitorTypes.Server, br); if (status == HttpMessage.ProcessStatus.Error) { pendingStatus = null; return(status); } else // success { theMessage = pendingStatus; monitorType = HttpSessionWatcher.MonitorTypes.Server; // assign the monitor type SetTypeForTcpStreamGenerator(tcpStreamGenerator, monitorType); } } else // success { theMessage = pendingRequest; monitorType = HttpSessionWatcher.MonitorTypes.Client; // assign the monitor type SetTypeForTcpStreamGenerator(tcpStreamGenerator, monitorType); } } else // otherwise just process the data like normal { status = ProcessBinaryReader(theMessage, monitorType, br); } // stop processing if we need more data // or if we are complete since we are done with this message and // only by re-entering this function do we create a new one if ((status == HttpMessage.ProcessStatus.NeedMoreData) || (status == HttpMessage.ProcessStatus.Complete)) { break; } } return(status); }
private HttpMessage.ProcessStatus ProcessBinaryReader(HttpMessage theMessage, MonitorTypes monitorType, BinaryReader br) { HttpMessage.ProcessStatus status; status = theMessage.Process(br); if (IsDebugEnabled) { log.DebugFormat("status == {0}", status); } if (status == HttpMessage.ProcessStatus.Error) { log.Debug("ProcessStatus.Error"); } else if (status == HttpMessage.ProcessStatus.Complete) { // send a completed notification to the appropriate handler if (monitorType == MonitorTypes.Client) { if (OnHttpRequestFound != null) { if (IsDebugEnabled) { log.Debug("Calling OnHttpRequestFound() delegates"); } try { OnHttpRequestFound(new HttpSessionWatcherRequestEventArgs(this, pendingRequest)); } catch (System.Exception) { // drop all exceptions thrown from handlers, its not our issue } } // put this request into requests waiting for status queue requestsWaitingForStatus.Enqueue(pendingRequest); // clear out the pendingRequest since we finished with it pendingRequest = null; } else if (monitorType == MonitorTypes.Server) { // do we have any pending requests? if so we should // dequeue one of them and assign it to the pendingStatus // so the user can match the status with the request if (requestsWaitingForStatus.Count != 0) { pendingStatus.Request = requestsWaitingForStatus.Dequeue(); } if (OnHttpStatusFound != null) { if (IsDebugEnabled) { log.Debug("Calling OnHttpStatusFound() delegates"); } try { OnHttpStatusFound(new HttpSessionWatcherStatusEventArgs(this, pendingStatus)); } catch (System.Exception) { // drop all exceptions thrown from handlers, its not our issue } } // clear out the pendingStatus since we finished with it pendingStatus = null; } // return completion status = HttpMessage.ProcessStatus.Complete; } else if (status == HttpMessage.ProcessStatus.NeedMoreData) { // need more data, return with our current position } return(status); }
/// <summary> /// Constructor /// </summary> /// <param name="sessionWatcher"> /// A <see cref="HttpSessionWatcher"/> /// </param> /// <param name="status"> /// A <see cref="HttpStatus"/> /// </param> public HttpSessionWatcherStatusEventArgs(HttpSessionWatcher sessionWatcher, HttpStatus status) { this.sessionWatcher = sessionWatcher; this.status = status; }