예제 #1
0
        /// <summary>
        // NOTE: We only support starting a session monitor
        ///       if we catch a client request or server status
        ///       response at the head of the TcpStream.
        ///       We *could* pick things up in the middle but it would
        ///       require a bit more effort for what shouldn't be
        ///       a typical case.
        /// </summary>
        /// <param name="c">
        /// A <see cref="TcpConnection"/>
        /// </param>
        /// <param name="OnHttpRequestFound">
        /// A <see cref="OnHttpRequestFoundDelegate"/>
        /// </param>
        /// <param name="OnHttpStatusFound">
        /// A <see cref="OnHttpStatusFoundDelegate"/>
        /// </param>
        /// <param name="OnHttpWatcherError">
        /// A <see cref="OnHttpWatcherErrorDelegate"/>
        /// </param>
        public HttpSessionWatcher(TcpConnection c,
                                  OnHttpRequestFoundDelegate OnHttpRequestFound,
                                  OnHttpStatusFoundDelegate OnHttpStatusFound,
                                  OnHttpWatcherErrorDelegate OnHttpWatcherError)
        {
            if (IsDebugEnabled)
            {
                log.Debug("");
            }

            // attach stream generators to both flows of the given connection
            streamGenerator0             = new TcpStreamGenerator(c.Flows[0], new TimeSpan(0, 0, 60), null);
            streamGenerator0.OnCallback += HandleStreamGeneratorOnCallback;
            tcpStreamGeneratorToMonitorType[streamGenerator0] = MonitorTypes.Unknown;

            streamGenerator1             = new TcpStreamGenerator(c.Flows[1], new TimeSpan(0, 0, 60), null);
            streamGenerator1.OnCallback += HandleStreamGeneratorOnCallback;
            tcpStreamGeneratorToMonitorType[streamGenerator1] = MonitorTypes.Unknown;

            requestsWaitingForStatus = new Queue <HttpRequest>();

            // setup the delegates
            this.OnHttpRequestFound = OnHttpRequestFound;
            this.OnHttpStatusFound  = OnHttpStatusFound;
            this.OnHttpWatcherError = OnHttpWatcherError;
        }
예제 #2
0
 private void SetTypeForTcpStreamGenerator(TcpStreamGenerator sg,
                                           MonitorTypes monitorType)
 {
     if (sg == streamGenerator0)
     {
         MonitorTypeFlow0 = monitorType;
     }
     else
     {
         MonitorTypeFlow1 = monitorType;
     }
 }
예제 #3
0
        TcpStreamGenerator.CallbackReturnValue HandleTcpStreamGeneratorOnCallback(TcpStreamGenerator tcpStreamGenerator, TcpStreamGenerator.CallbackCondition condition)
        {
            Console.WriteLine("{0} bytes in stream",
                              tcpStreamGenerator.tcpStream.Length);

            int expectedSize = 0;

            for (int i = 0; i < callbackCount; i++)
            {
                expectedSize += payloadSizes[i];
            }

            Assert.Equal(expectedSize, tcpStreamGenerator.tcpStream.Length);

            callbackCount++;
            return(TcpStreamGenerator.CallbackReturnValue.ContinueMonitoring);
        }
예제 #4
0
        void HandleConnectionManagerOnConnectionFound(TcpConnection c)
        {
            Console.WriteLine("HandleConnectionManagerOnConnectionFound c {0}", c.ToString());

            var timeout = new TimeSpan(0, 5, 0);
            TcpStreamGenerator incomingGenerator = new TcpStreamGenerator(c.Flows[0],
                                                                          timeout,
                                                                          100000);

            incomingGenerator.OnCallback += HandleTcpStreamGeneratorOnCallback;
            incomingGenerators.Add(incomingGenerator);

            // We only test the first of the two flows in this unit test
            // so no need to attach to the other flow
#if false
            TcpStreamGenerator outgoingGenerator = new TcpStreamGenerator(c.Flows[1],
                                                                          timeout,
                                                                          100000);
            outgoingGenerator.OnCallback += HandleTcpStreamGeneratorOnCallback;
            outgoingGenerators.Add(outgoingGenerator);
#endif
        }
예제 #5
0
        // 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);
        }
예제 #6
0
        TcpStreamGenerator.CallbackReturnValue HandleStreamGeneratorOnCallback(TcpStreamGenerator tcpStreamGenerator,
                                                                               TcpStreamGenerator.CallbackCondition condition)
        {
            switch (condition)
            {
            // stop monitoring if we have an error condition
            case TcpStreamGenerator.CallbackCondition.SizeLimitReached:
            case TcpStreamGenerator.CallbackCondition.OutOfRange:
            case TcpStreamGenerator.CallbackCondition.ConnectionTimeout:
            case TcpStreamGenerator.CallbackCondition.StreamError:
                string errorString = string.Format("condition == {0}, shutting down monitors",
                                                   condition);
                log.Warn(errorString);
                ShutDownMonitor(errorString);
                return(TcpStreamGenerator.CallbackReturnValue.StopMonitoring);

            // early out if we don't have the next packet in sequence
            case TcpStreamGenerator.CallbackCondition.OutOfSequence:
                if (IsDebugEnabled)
                {
                    log.DebugFormat("condition {0} != TcpStreamMonitor.CallbackCondition.NextInSequence, returning ContinueMonitoring",
                                    condition);
                }
                return(TcpStreamGenerator.CallbackReturnValue.ContinueMonitoring);

            case TcpStreamGenerator.CallbackCondition.DuplicateDropped:
                // nothing to do here, we dropped a duplicate entry
                return(TcpStreamGenerator.CallbackReturnValue.ContinueMonitoring);

            // normal case, nothing to do here but fall through
            case TcpStreamGenerator.CallbackCondition.NextInSequence:
                break;

            default:
                string error = "Unknown condition of '" + condition + "'";
                throw new System.InvalidOperationException(error);
            }

            // process the data in the TcpStream until we encounter
            // an error/exception case
            HttpMessage.ProcessStatus processStatus;
            while (true)
            {
                processStatus = HandleTcpStreamGenerator(tcpStreamGenerator);

                if (IsDebugEnabled)
                {
                    log.DebugFormat("processStatus is {0}", processStatus);
                }

                // if an error was detected we should stop monitoring the monitor
                // with the error and delete the other monitor
                if (processStatus == HttpMessage.ProcessStatus.Error)
                {
                    var    monitorType = tcpStreamGeneratorToMonitorType[tcpStreamGenerator];
                    string errorString = string.Format("Processing monitorType {0} got {1}, stopping monitor and deleting other monitor",
                                                       monitorType, processStatus);
                    ShutDownMonitor(errorString);
                    return(TcpStreamGenerator.CallbackReturnValue.StopMonitoring);
                }
                else if (processStatus == HttpMessage.ProcessStatus.NeedMoreData)
                {
                    // not enough data remaining in the TcpStream so stop looping
                    // and ask the TcpStreamMonitor to continue monitoring
                    return(TcpStreamGenerator.CallbackReturnValue.ContinueMonitoring);
                }
                else if (processStatus == HttpMessage.ProcessStatus.Continue)
                {
                    // just continue looping
                }
                else if (processStatus == HttpMessage.ProcessStatus.Continue)
                {
                    // just continue looping
                }
            }
        }