internal bool SubmitRequest(HttpWebRequest request, bool forcedsubmit)
        {
            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "request#" + ValidationHelper.HashString(request));
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest");
            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() Free:" + m_Free.ToString() + " m_WaitList.Count:" + m_WaitList.Count.ToString());

            TriState startRequestResult = TriState.Unspecified;
            ConnectionReturnResult returnResult = null;
            bool expiredIdleConnection = false;

            // See if the connection is free, and if the underlying socket or
            // stream is set up. If it is, we can assign this connection to the
            // request right now. Otherwise we'll have to put this request on
            // on the wait list until it its turn.

            lock(this)
            {
                request.AbortDelegate = m_AbortDelegate;

                if (request.Aborted)
                {
                    // Note that request is not on the connection list yet and Abort() will push the response on the request
                    GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - (Request was aborted before being submitted)", true);
                    UnlockIfNeeded(request);
                    return true;
                }
                //
                // There is a race condition between FindConnection and PrepareCloseConnectionSocket
                // Some request may already try to submit themselves while the connection is dying.
                //
                // Retry if that's the case
                //
                if (!CanBePooled)
                {
                    GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false - can't be pooled");
                    UnlockIfNeeded(request);
                    return false;
                }

                //
                // There is a race condition between SubmitRequest and FindConnection. A non keep-alive request may
                // get submitted on this connection just after we check for it. So make sure that if we are queueing
                // behind non keep-alive request then its a forced submit.
                // Retry if that's not the case.
                //
                if (!forcedsubmit && NonKeepAliveRequestPipelined)
                {
                    GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false - behind non keep-alive request");
                    UnlockIfNeeded(request);
                    return false;
                }

                // See if our timer still matches the SerivcePoint.  If not, get rid of it.
                if (m_RecycleTimer.Duration != ServicePoint.ConnectionLeaseTimerQueue.Duration) {
                    m_RecycleTimer.Cancel();
                    m_RecycleTimer = ServicePoint.ConnectionLeaseTimerQueue.CreateTimer();
                }

                if (m_RecycleTimer.HasExpired) {
                    request.KeepAlive = false;
                }

                //
                // If the connection has already been locked by another request, then
                // we fail the submission on this Connection.
                //

                if (LockedRequest != null && LockedRequest != request) {
                    GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false");
                    return false;
                }


                //free means no one in the wait list.  We should only add a request
                //if the request can pipeline, or pipelining isn't available

                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest WriteDone:" + m_WriteDone.ToString() + ", ReadDone:" + m_ReadDone.ToString() + ", m_WriteList.Count:" + m_WriteList.Count.ToString());

                //
                // If this request is marked as non keep-alive, we should stop pipelining more requests on this
                // connection. The keep-alive context is transfered to the connection from request only after we start
                // receiving response for the request.
                //
                if (!forcedsubmit && !m_NonKeepAliveRequestPipelined) {
                    m_NonKeepAliveRequestPipelined = (!request.KeepAlive && !request.NtlmKeepAlive);
                }

                if (m_Free && m_WriteDone && !forcedsubmit && (m_WriteList.Count == 0 || (request.Pipelined && !request.HasEntityBody && m_CanPipeline && m_Pipelining && !m_IsPipelinePaused))) {

                    // Connection is free. Mark it as busy and see if underlying
                    // socket is up.
                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - Free ");
                    m_Free = false;

                    // This codepath handles the case where the server has closed the Connection by
                    // returning false below: the request will be resubmitted on a different Connection.
                    startRequestResult = StartRequest(request, true);
                    if (startRequestResult == TriState.Unspecified)
                    {
                        expiredIdleConnection = true;
                        PrepareCloseConnectionSocket(ref returnResult);
                        // Hard Close the socket.
                        Close(0);
                    }
                }
                else {
                    m_WaitList.Add(new WaitListItem(request, NetworkingPerfCounters.GetTimestamp()));
                    NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.HttpWebRequestQueued);
                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - Request added to WaitList#"+ValidationHelper.HashString(request));
#if TRAVE
                    if (q_Tunnelling) {
                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() MyLocalPort:" + MyLocalPort + " ERROR: adding HttpWebRequest#" + ValidationHelper.HashString(request) +" to tunnelling WaitList");
                    }
                    else {
                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() MyLocalPort:" + MyLocalPort + " adding HttpWebRequest#" + ValidationHelper.HashString(request) +" to non-tunnelling WaitList m_WaitList.Count:" + m_WaitList.Count);
                    }
#endif
                    CheckNonIdle();
                }
            }

            if (expiredIdleConnection)
            {
                GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest(), expired idle connection", false);
                ConnectionReturnResult.SetResponses(returnResult);
                return false;
            }

            GlobalLog.DebugAddRequest(request, this, 0);
            if(Logging.On)Logging.Associate(Logging.Web, this, request);

            if (startRequestResult != TriState.Unspecified) {
                CompleteStartRequest(true, request, startRequestResult);
            }
            // On [....], we wait for the Connection to be come availble here,
            if (!request.Async)
            {
                object responseObject = request.ConnectionAsyncResult.InternalWaitForCompletion();
                ConnectStream writeStream = responseObject as ConnectStream;
                AsyncTriState triStateAsync = null;
                if (writeStream == null)
                    triStateAsync = responseObject as AsyncTriState;

                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() Pipelining:"+m_Pipelining);

                if (startRequestResult == TriState.Unspecified && triStateAsync != null) {
                    // May need to recreate Connection here (i.e. call Socket.Connect)
                    CompleteStartRequest(true, request, triStateAsync.Value);
                }
                else if (writeStream != null)
                {
                    // return the Stream to the Request
                    request.SetRequestSubmitDone(writeStream);
                }
#if DEBUG
                else if (responseObject is Exception)
                {
                    Exception exception = responseObject as Exception;
                    WebException webException = responseObject as WebException;
                    GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest (SYNC) - Error waiting for a connection: " + exception.Message,
                                    "Status:" + (webException == null? exception.GetType().FullName: (webException.Status.ToString() +  " Internal Status: " + webException.InternalStatus.ToString())));
                    return true;
                }
#endif
            }

            GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", true);
            return true;
        }
        private void CompleteStartRequest(bool onSubmitThread, HttpWebRequest request, TriState needReConnect) {
            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::CompleteStartRequest", ValidationHelper.HashString(request));
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "Connection#" + ValidationHelper.HashString(this) + "::CompleteStartRequest");

            if (needReConnect == TriState.True) {
                // Socket is not alive.

                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::CompleteStartRequest() Queue StartConnection Delegate ");
                try {
                    if (request.Async) {
                        CompleteStartConnection(true, request);
                    }
                    else if (onSubmitThread) {
                        CompleteStartConnection(false, request);
                    }
                    // else - fall through and wake up other thread
                }
                catch (Exception exception) {
                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::CompleteStartRequest(): exception: " + exception.ToString());
                    if (NclUtilities.IsFatal(exception)) throw;
                    //
                    // Should not be here because CompleteStartConnection and below tries to catch everything
                    //
                    GlobalLog.Assert(exception.ToString());
                }

                // If neeeded wake up other thread where SubmitRequest was called
                if (!request.Async) {
                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::CompleteStartRequest() Invoking Async Result");
                    request.ConnectionAsyncResult.InvokeCallback(new AsyncTriState(needReConnect));
                }


                GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::CompleteStartRequest", "needReConnect");
                return;
            }


            //
            // From now on the request.SetRequestSubmitDone must be called or it may hang
            // For a [....] request the write side reponse windowwas opened in HttpWebRequest.SubmitRequest
            if (request.Async)
                request.OpenWriteSideResponseWindow();


            ConnectStream writeStream = new ConnectStream(this, request);

            // Call the request to let them know that we have a write-stream, this might invoke Send() call
            if (request.Async || onSubmitThread) {
                request.SetRequestSubmitDone(writeStream);
            }
            else {
                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::CompleteStartRequest() Invoking Async Result");
                request.ConnectionAsyncResult.InvokeCallback(writeStream);
            }
            GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::CompleteStartRequest");
        }
Example #3
0
        /*

            SubmitRequest       - Submit a request for sending.

            The core submit handler. This is called when a request needs to be
            submitted to the network. This routine is asynchronous; the caller
            passes in an HttpSubmitDelegate that we invoke when the caller
            can use the underlying network. The delegate is invoked with the
            stream that it can right to.

            On the Sync path, we work by attempting to gain control of the Connection
            for writing and reading.  If some other thread is using the Connection,
            We wait inside of a LazyAsyncResult until it is availble.

            Input:
                    request                 - request that's being submitted.
                    SubmitDelegate          - Delegate to be invoked.

            Returns:
                    true when the request was correctly submitted

        --*/
        // userReqeustThread says whether we can post IO from this thread or not.
        internal bool SubmitRequest(HttpWebRequest request)
        {
            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "request#" + ValidationHelper.HashString(request));
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest");
            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() Free:" + m_Free.ToString() + " m_WaitList.Count:" + m_WaitList.Count.ToString());

            TriState startRequestResult = TriState.Unspecified;
            ConnectionReturnResult returnResult = null;
            bool expiredIdleConnection = false;

            // See if the connection is free, and if the underlying socket or
            // stream is set up. If it is, we can assign this connection to the
            // request right now. Otherwise we'll have to put this request on
            // on the wait list until it its turn.

            lock(this)
            {
                request.AbortDelegate = m_AbortDelegate;

                if (request.Aborted)
                {
                    // Note that request is not on the connection list yet and Abort() will push the response on the request
                    GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - (Request was aborted before being submitted)", true);
                    return true;
                }
                //
                // There is a race condition between FindConnection and PrepareCloseConnectionSocket
                // Some request may already try to submit themselves while the connection is dying.
                //
                // Retry if that's the case
                //
                if (!CanBePooled)
                {
                    GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false - can't be pooled");
                    return false;
                }

                // See if our timer still matches the SerivcePoint.  If not, get rid of it.
                if (m_RecycleTimer.Duration != ServicePoint.ConnectionLeaseTimerQueue.Duration) {
                    m_RecycleTimer.Cancel();
                    m_RecycleTimer = ServicePoint.ConnectionLeaseTimerQueue.CreateTimer();
                }

                if (m_RecycleTimer.HasExpired) {
                    request.KeepAlive = false;
                }

                //
                // If the connection has already been locked by another request, then
                // we fail the submission on this Connection.
                //

                if (LockedRequest != null && LockedRequest != request) {
                    GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false");
                    return false;
                }

                //free means no one in the wait list.  We should only add a request
                //if the request can pipeline, or pipelining isn't available

                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest WriteDone:" + m_WriteDone.ToString() + ", ReadDone:" + m_ReadDone.ToString() + ", m_WriteList.Count:" + m_WriteList.Count.ToString());

                if (m_Free && m_WriteDone && (m_WriteList.Count == 0 || (request.Pipelined && !request.RequireBody && m_CanPipeline && m_Pipelining && !m_IsPipelinePaused))) {

                    // Connection is free. Mark it as busy and see if underlying
                    // socket is up.
                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - Free ");
                    m_Free = false;

                    startRequestResult = StartRequest(request);
                    if (startRequestResult == TriState.Unspecified)
                    {
                        expiredIdleConnection = true;
                        PrepareCloseConnectionSocket(ref returnResult);
                        // Hard Close the socket.
                        Close(0);
                    }
                }
                else {
                    m_WaitList.Add(request);
                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - Request added to WaitList#"+ValidationHelper.HashString(request));

                    CheckNonIdle();
                }
            }

            if (expiredIdleConnection)
            {
                GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest(), expired idle connection", false);
                ConnectionReturnResult.SetResponses(returnResult);
                return false;
            }

            GlobalLog.DebugAddRequest(request, this, 0);
            if(Logging.On)Logging.Associate(Logging.Web, this, request);

            if (startRequestResult != TriState.Unspecified) {
                CompleteStartRequest(true, request, startRequestResult);
            }
            // On Sync, we wait for the Connection to be come availble here,
            if (!request.Async)
            {
                object responseObject = request.ConnectionAsyncResult.InternalWaitForCompletion();
                ConnectStream writeStream = responseObject as ConnectStream;
                AsyncTriState triStateAsync = null;
                if (writeStream == null)
                    triStateAsync = responseObject as AsyncTriState;

                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() Pipelining:"+m_Pipelining);

                if (startRequestResult == TriState.Unspecified && triStateAsync != null) {
                    // May need to recreate Connection here (i.e. call Socket.Connect)
                    CompleteStartRequest(true, request, triStateAsync.Value);
                }
                else if (writeStream != null)
                {
                    // return the Stream to the Request
                    request.SetRequestSubmitDone(writeStream);
                }
            #if DEBUG
                else if (responseObject is Exception)
                {
                    Exception exception = responseObject as Exception;
                    WebException webException = responseObject as WebException;
                    GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest (SYNC) - Error waiting for a connection: " + exception.Message,
                                    "Status:" + (webException == null? exception.GetType().FullName: (webException.Status.ToString() +  " Internal Status: " + webException.InternalStatus.ToString())));
                    return true;
                }
            #endif
            }

            GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", true);
            return true;
        }
        private void CompleteConnection(bool async, HttpWebRequest request)
        {
            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::CompleteConnection", "async:" + async.ToString() + " request:" + ValidationHelper.HashString(request));
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "Connection#" + ValidationHelper.HashString(this) + "::CompleteConnection");

            WebExceptionStatus ws = WebExceptionStatus.ConnectFailure;
            //
            // From now on the request.SetRequestSubmitDone must be called or it may hang
            // For a [....] request the write side reponse windowwas opened in HttpWebRequest.SubmitRequest
            if (request.Async)
                request.OpenWriteSideResponseWindow();

            try
            {
                try {
#if !FEATURE_PAL
                    if (request.Address.Scheme == Uri.UriSchemeHttps) {
                        TlsStream tlsStream = new TlsStream(request.GetRemoteResourceUri().IdnHost,
                            NetworkStream, request.ClientCertificates, ServicePoint, request,
                            request.Async ? request.GetConnectingContext().ContextCopy : null);
                        NetworkStream = tlsStream;
                    }
#endif
                    ws = WebExceptionStatus.Success;
                }
                catch {
                    // The TLS stream could not be created.  Close the current non-TLS stream immediately
                    // to prevent any future use of it.  Due to race conditions, the error handling will sometimes
                    // try to write (flush) out some of the HTTP headers to the stream as it is closing down the failed 
                    // HttpWebRequest. This would cause plain text to go on the wire even though the stream should
                    // have been TLS encrypted.
                    NetworkStream.Close();
                    throw;
                }
                finally {
                    //
                    // There is a ---- with Abort so TlsStream ctor may throw.
                    // SetRequestSubmitDone will deal with this kind of errors.
                    // 

                    m_ReadState = ReadState.Start;
                    ClearReaderState();

                    request.SetRequestSubmitDone(new ConnectStream(this, request));
                }
            }
            catch (Exception exception)
            {
                if (m_InnerException == null)
                    m_InnerException = exception;
                WebException webException = exception as WebException;
                if (webException != null)
                {
                    ws = webException.Status;
                }
            }

            if (ws != WebExceptionStatus.Success)
            {
                ConnectionReturnResult returnResult = null;
                HandleError(false, false, ws, ref returnResult);
                ConnectionReturnResult.SetResponses(returnResult);

                if (Logging.On) Logging.PrintError(Logging.Web, this, "CompleteConnection", "on error");
                GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::CompleteConnection", "on error");
            }
            else
            {
                GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::CompleteConnection");
            }
        }
Example #5
0
        private void CompleteConnection(bool async, HttpWebRequest request)
        {
            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::CompleteConnection", "async:" + async.ToString() + " request:" + ValidationHelper.HashString(request));
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "Connection#" + ValidationHelper.HashString(this) + "::CompleteConnection");

            WebExceptionStatus ws = WebExceptionStatus.ConnectFailure;
            //
            // From now on the request.SetRequestSubmitDone must be called or it may hang
            // For a sync request the write side reponse windowwas opened in HttpWebRequest.SubmitRequest
            if (request.Async)
                request.OpenWriteSideResponseWindow();

            try
            {
                try {
                }
                finally {
                    m_ReadState = ReadState.Start;
                    ClearReaderState();

                    request.SetRequestSubmitDone(new ConnectStream(this, request));
                    ws = WebExceptionStatus.Success;
                }

            }
            catch (Exception exception)
            {
                if (m_InnerException == null)
                    m_InnerException = exception;
                WebException webException = exception as WebException;
                if (webException != null)
                {
                    ws = webException.Status;
                }
            }

            if (ws != WebExceptionStatus.Success)
            {
                ConnectionReturnResult returnResult = null;
                HandleError(false, false, ws, ref returnResult);
                ConnectionReturnResult.SetResponses(returnResult);

                GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::CompleteConnection", "on error");
            }
            else
            {
                GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::CompleteConnection");
            }
        }
 private void CompleteStartRequest(bool onSubmitThread, HttpWebRequest request, TriState needReConnect)
 {
     if (needReConnect == TriState.True)
     {
         try
         {
             if (request.Async)
             {
                 this.CompleteStartConnection(true, request);
             }
             else if (onSubmitThread)
             {
                 this.CompleteStartConnection(false, request);
             }
         }
         catch (Exception exception)
         {
             if (NclUtilities.IsFatal(exception))
             {
                 throw;
             }
         }
         if (!request.Async)
         {
             request.ConnectionAsyncResult.InvokeCallback(new AsyncTriState(needReConnect));
         }
     }
     else
     {
         if (request.Async)
         {
             request.OpenWriteSideResponseWindow();
         }
         ConnectStream submitStream = new ConnectStream(this, request);
         if (request.Async || onSubmitThread)
         {
             request.SetRequestSubmitDone(submitStream);
         }
         else
         {
             request.ConnectionAsyncResult.InvokeCallback(submitStream);
         }
     }
 }
 private void CompleteConnection(bool async, HttpWebRequest request)
 {
     WebExceptionStatus connectFailure = WebExceptionStatus.ConnectFailure;
     if (request.Async)
     {
         request.OpenWriteSideResponseWindow();
     }
     try
     {
         try
         {
             if (request.Address.Scheme == Uri.UriSchemeHttps)
             {
                 TlsStream stream = new TlsStream(request.GetRemoteResourceUri().Host, base.NetworkStream, request.ClientCertificates, this.ServicePoint, request, request.Async ? request.GetConnectingContext().ContextCopy : null);
                 base.NetworkStream = stream;
             }
         }
         finally
         {
             this.m_ReadState = ReadState.Start;
             this.ClearReaderState();
             request.SetRequestSubmitDone(new ConnectStream(this, request));
             connectFailure = WebExceptionStatus.Success;
         }
     }
     catch (Exception exception)
     {
         if (this.m_InnerException == null)
         {
             this.m_InnerException = exception;
         }
         WebException exception2 = exception as WebException;
         if (exception2 != null)
         {
             connectFailure = exception2.Status;
         }
     }
     if (connectFailure != WebExceptionStatus.Success)
     {
         ConnectionReturnResult returnResult = null;
         this.HandleError(false, false, connectFailure, ref returnResult);
         ConnectionReturnResult.SetResponses(returnResult);
     }
 }
 internal bool SubmitRequest(HttpWebRequest request, bool forcedsubmit)
 {
     TriState unspecified = TriState.Unspecified;
     ConnectionReturnResult returnResult = null;
     bool flag = false;
     lock (this)
     {
         request.AbortDelegate = this.m_AbortDelegate;
         if (request.Aborted)
         {
             return true;
         }
         if (!base.CanBePooled)
         {
             return false;
         }
         if (!forcedsubmit && this.NonKeepAliveRequestPipelined)
         {
             return false;
         }
         if (this.m_RecycleTimer.Duration != this.ServicePoint.ConnectionLeaseTimerQueue.Duration)
         {
             this.m_RecycleTimer.Cancel();
             this.m_RecycleTimer = this.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer();
         }
         if (this.m_RecycleTimer.HasExpired)
         {
             request.KeepAlive = false;
         }
         if ((this.LockedRequest != null) && (this.LockedRequest != request))
         {
             return false;
         }
         if (!forcedsubmit && !this.m_NonKeepAliveRequestPipelined)
         {
             this.m_NonKeepAliveRequestPipelined = !request.KeepAlive && !request.NtlmKeepAlive;
         }
         if (((this.m_Free && this.m_WriteDone) && !forcedsubmit) && ((this.m_WriteList.Count == 0) || (((request.Pipelined && !request.HasEntityBody) && (this.m_CanPipeline && this.m_Pipelining)) && !this.m_IsPipelinePaused)))
         {
             this.m_Free = false;
             unspecified = this.StartRequest(request, true);
             if (unspecified == TriState.Unspecified)
             {
                 flag = true;
                 this.PrepareCloseConnectionSocket(ref returnResult);
                 base.Close(0);
             }
         }
         else
         {
             this.m_WaitList.Add(new WaitListItem(request, NetworkingPerfCounters.GetTimestamp()));
             NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.HttpWebRequestQueued);
             this.CheckNonIdle();
         }
     }
     if (flag)
     {
         ConnectionReturnResult.SetResponses(returnResult);
         return false;
     }
     if (Logging.On)
     {
         Logging.Associate(Logging.Web, this, request);
     }
     if (unspecified != TriState.Unspecified)
     {
         this.CompleteStartRequest(true, request, unspecified);
     }
     if (!request.Async)
     {
         object obj2 = request.ConnectionAsyncResult.InternalWaitForCompletion();
         ConnectStream submitStream = obj2 as ConnectStream;
         AsyncTriState state2 = null;
         if (submitStream == null)
         {
             state2 = obj2 as AsyncTriState;
         }
         if ((unspecified == TriState.Unspecified) && (state2 != null))
         {
             this.CompleteStartRequest(true, request, state2.Value);
         }
         else if (submitStream != null)
         {
             request.SetRequestSubmitDone(submitStream);
         }
     }
     return true;
 }
Example #9
0
        private void StartRequest(HttpWebRequest Request, bool PostReceive) {
            GlobalLog.Enter("StartRequest", "Request=#"+ValidationHelper.HashString(Request) + ", PostReceive=" + PostReceive);

            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::StartRequest", ValidationHelper.HashString(Request) + ", " + PostReceive);
            bool needReConnect = false;

            // Initialze state, and add the request to the write queue.

            // disable pipeling in certain cases such as when the Request disables it,
            // OR if the request is made using a Verb that cannot be pipelined,
            // BUT!! What about special verbs with data?? Should we not disable then too?

            m_Pipelining = m_CanPipeline && Request.InternalPipelined && (!Request.RequireBody);
            m_KeepAlive = Request.KeepAlive;

            // start of write process, disable done-ness flag
            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::StartRequest() setting m_WriteDone:" + m_WriteDone.ToString() + " to false");
            m_WriteDone = false;

            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::StartRequest() _WriteList Add " + ValidationHelper.HashString(Request) + " - cnt#" + ValidationHelper.HashString(this) );
            m_WriteList.Add(Request);
            GlobalLog.Print(m_WriteList.Count+" requests queued");
            CheckNonIdle();

            // with no transport around, we will have to create one, therefore, we can't have
            //  the possiblity to even have a DoneReading().

            if (Transport == null) {
                m_ReadDone = false;
                needReConnect = true;
            }

            if (Request is HttpProxyTunnelRequest) {
                Tunnelling = true;
            }
            Monitor.Exit(this);

            //
            // When we're uploading data, to a 1.0 server, we need to buffer
            //  in order to determine content length
            //
            if (Request.CheckBuffering) {
                Request.SetRequestContinue();
            }

            // If we need to post a receive, do so now.

            if (PostReceive) {
                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::StartRequest() ThreadPool.QueueUserWorkItem(m_PostReceiveDelegate, this)");
                ThreadPool.QueueUserWorkItem(m_PostReceiveDelegate, this);
            }

            if (needReConnect) {
                // Socket is not alive. Queue a request to the thread pool
                // to get it going.

                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::StartRequest() Queue StartConnection Delegate ");
#if DEBUG
                m_StartDelegateQueued = true;
                try {
#endif
                    ThreadPool.RegisterWaitForSingleObject(
                                m_ReadCallbackEvent,
                                m_StartConnectionDelegate,
                                Request,
                                -1,
                                true);
#if DEBUG
                }
                catch (Exception exception) {
                    GlobalLog.Assert(false, exception.ToString(), "");
                }
#endif

                GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::StartRequest", "needReConnect");
                return;
            }


            // Call the Request to let them know that we have a write-stream

            Request.SetRequestSubmitDone(
                new ConnectStream(
                    this,
                    Request.SendChunked ? -1 : (Request.ContentLength>0 ? Request.ContentLength : 0),
                    Request )
                    );

            GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::StartRequest");
        }