System.Net.Connection.ReadStartNextRequest C# (CSharp) Method

ReadStartNextRequest() private method

private ReadStartNextRequest ( WebRequest currentRequest, ConnectionReturnResult &returnResult ) : void
currentRequest WebRequest
returnResult ConnectionReturnResult
return void
        internal void ReadStartNextRequest(WebRequest currentRequest, ref ConnectionReturnResult returnResult)
        {
            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::ReadStartNextRequest" + " WriteDone:" + m_WriteDone + " ReadDone:" + m_ReadDone + " WaitList:" + m_WaitList.Count + " WriteList:" + m_WriteList.Count);
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "Connection#" + ValidationHelper.HashString(this) + "::ReadStartNextRequest");

            HttpWebRequest nextRequest = null;
            TriState startRequestResult = TriState.Unspecified;
            bool calledCloseConnection = false;
            bool mustExit = false;

            try {
                lock(this) {
                    if (m_WriteList.Count > 0 && (object)currentRequest == m_WriteList[0])
                    {
                        // advance back to state 0
                        m_ReadState = ReadState.Start;
                        m_WriteList.RemoveAt(0);

                        // Must reset ConnectStream here to prevent a leak through the stream of the last request on each connection.
                        m_ResponseData.m_ConnectStream = null;

                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ReadStartNextRequest() Removed request#" + ValidationHelper.HashString(currentRequest) + " from m_WriteList. New m_WriteList.Count:" + m_WriteList.Count.ToString());
                    }
                    else
                    {
                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ReadStartNextRequest() The request#" + ValidationHelper.HashString(currentRequest) + " was disassociated so do nothing.  m_WriteList.Count:" + m_WriteList.Count.ToString());
                        mustExit = true;;
                    }

                    //
                    // Since this is called after we're done reading the current
                    // request, if we're not doing keepalive and we're done
                    // writing we can close the connection now.
                    //
                    if(!mustExit)
                    {
                        //
                        // m_ReadDone==true is implied because we just finished a request but really the value must still be false here
                        //
                        if (m_ReadDone)
                            throw new InternalException();  // other requests may already started reading on this connection, need a QFE

                        if (!m_KeepAlive || m_Error != WebExceptionStatus.Success || !CanBePooled)
                        {
                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ReadStartNextRequest() KeepAlive:" + m_KeepAlive + " WriteDone:" + m_WriteDone);
                            // Finished one request and connection is closing.
                            // We will not read from this connection so set readDone = true
                            m_ReadDone = true;
                            if (m_WriteDone)
                            {

                                // We could be closing because of an unexpected keep-alive
                                // failure, ie we pipelined a few requests and in the middle
                                // the remote server stopped doing keep alive. In this
                                // case m_Error could be success, which would be misleading.
                                // So in that case we'll set it to KeepAliveFailure.

                                if (m_Error == WebExceptionStatus.Success) {
                                    // Only reason we could have gotten here is because
                                    // we're not keeping the connection alive.
                                    m_Error = WebExceptionStatus.KeepAliveFailure;
                                }

                                // PrepareCloseConnectionSocket has to be called with the critical section held.
                                PrepareCloseConnectionSocket(ref returnResult);
                                calledCloseConnection = true;
                                Close();
                            }
                        }
                        else
                        {
                            // We try to sort out KeepAliveFailure thing (search by context)
                            m_AtLeastOneResponseReceived = true;

                            if (m_WriteList.Count != 0)
                            {
                                // If a *pipelined* request that is being submitted has finished with the headers, post a receive
                                nextRequest = m_WriteList[0] as HttpWebRequest;
                                // If the active request has not finished its headers we can set m_ReadDone = true
                                // and that will be changed when said request will call CheckStartReceive
                                if (!nextRequest.HeadersCompleted)
                                {
                                    nextRequest = null;
                                    m_ReadDone = true;
                                }
                            }
                            // If there are no requests left to write (means pipeline),
                            // we can get the next request from wait list going now.
                            else
                            {
                                m_ReadDone = true;

                                // Sometime we get a response before completing the body in which case
                                // we defer next request to WriteStartNextRequest
                                if (m_WriteDone)
                                {
                                    nextRequest = CheckNextRequest();

                                    if (nextRequest != null )
                                    {
                                        // We cannot have HeadersCompleted on the request that was not placed yet on the write list
                                        if(nextRequest.HeadersCompleted)
                                            throw new InternalException();

                                        startRequestResult = StartRequest(nextRequest);
                                    }
                                    else
                                    {
                                        //There are no other requests to process, so make connection avaliable for all
                                        m_Free = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            finally
            {
                CheckIdle();
                //set result here to prevent nesting of readstartnextrequest.
                if(returnResult != null){
                    ConnectionReturnResult.SetResponses(returnResult);
                }
            }

            if(!mustExit && !calledCloseConnection)
            {
                if (startRequestResult != TriState.Unspecified)
                {
                    CompleteStartRequest(false, nextRequest, startRequestResult);
                }
                else if (nextRequest != null)
                {
                    // Handling receive, note that is for pipelinning case only !
                    if (!nextRequest.Async)
                    {
                        nextRequest.ConnectionReaderAsyncResult.InvokeCallback();
                    }
                    else
                    {
                        if (m_BytesScanned < m_BytesRead)
                        {
                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ReadStartNextRequest() Calling ReadComplete, bytes unparsed = " + (m_BytesRead - m_BytesScanned));
                            ReadComplete(0, WebExceptionStatus.Success);
                        }
                        else if (Thread.CurrentThread.IsThreadPoolThread)
                        {
                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ReadStartNextRequest() Calling PostReceive().");
                            PostReceive();
                        }
                        else
                        {
                            // Offload to the threadpool to protect against the case where one request's thread posts IO that another request
                            // depends on, but the first thread dies in the mean time.
                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ReadStartNextRequest() ThreadPool.UnsafeQueueUserWorkItem(m_PostReceiveDelegate, this)");
                            ThreadPool.UnsafeQueueUserWorkItem(m_PostReceiveDelegate, this);
                        }
                    }
                }
            }
            GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::ReadStartNextRequest");
        }