internal void SyncRead(HttpWebRequest request, bool userRetrievedStream, bool probeRead)
 {
     if (t_SyncReadNesting <= 0)
     {
         bool flag = !probeRead;
         try
         {
             bool flag2;
             t_SyncReadNesting++;
             int num = probeRead ? request.RequestContinueCount : 0;
             int bytesRead = -1;
             WebExceptionStatus receiveFailure = WebExceptionStatus.ReceiveFailure;
             if (this.m_BytesScanned < this.m_BytesRead)
             {
                 flag = true;
                 bytesRead = 0;
                 receiveFailure = WebExceptionStatus.Success;
             }
             do
             {
                 flag2 = true;
                 try
                 {
                     if (bytesRead != 0)
                     {
                         receiveFailure = WebExceptionStatus.ReceiveFailure;
                         if (!flag)
                         {
                             flag = base.Poll(0x55730, SelectMode.SelectRead);
                         }
                         if (flag)
                         {
                             this.ReadTimeout = request.Timeout;
                             bytesRead = this.Read(this.m_ReadBuffer, this.m_BytesRead, this.m_ReadBuffer.Length - this.m_BytesRead);
                             receiveFailure = WebExceptionStatus.Success;
                             if (bytesRead == 0)
                             {
                                 bytesRead = -1;
                             }
                         }
                     }
                 }
                 catch (Exception exception)
                 {
                     if (NclUtilities.IsFatal(exception))
                     {
                         throw;
                     }
                     if (this.m_InnerException == null)
                     {
                         this.m_InnerException = exception;
                     }
                     if (exception.GetType() == typeof(ObjectDisposedException))
                     {
                         receiveFailure = WebExceptionStatus.RequestCanceled;
                     }
                     else if (base.NetworkStream is TlsStream)
                     {
                         receiveFailure = ((TlsStream) base.NetworkStream).ExceptionStatus;
                     }
                     else
                     {
                         SocketException innerException = exception.InnerException as SocketException;
                         if (innerException != null)
                         {
                             if (innerException.ErrorCode == 0x274c)
                             {
                                 receiveFailure = WebExceptionStatus.Timeout;
                             }
                             else
                             {
                                 receiveFailure = WebExceptionStatus.ReceiveFailure;
                             }
                         }
                     }
                 }
                 if (flag)
                 {
                     flag2 = this.ReadComplete(bytesRead, receiveFailure);
                 }
                 bytesRead = -1;
             }
             while (!flag2 && (userRetrievedStream || (num == request.RequestContinueCount)));
         }
         finally
         {
             t_SyncReadNesting--;
         }
         if (probeRead)
         {
             if (flag)
             {
                 if (!request.Saw100Continue && !userRetrievedStream)
                 {
                     request.SawInitialResponse = true;
                 }
             }
             else
             {
                 request.SetRequestContinue();
             }
         }
     }
 }
        //
        //    Peforms a [....] Read and calls the ReadComplete to process the result
        //    The reads are done iteratively, until the Request has received enough
        //    data to contruct a response, or a 100-Continue is read, allowing the HttpWebRequest
        //    to return a write stream
        //
        //    probeRead = true only for POST request and when the caller needs to wait for 100-continue
        //
        internal void SyncRead(HttpWebRequest request, bool userRetrievedStream, bool probeRead)
        {
            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::SyncRead(byte[]) request#" + ValidationHelper.HashString(request) + (probeRead? ", Probe read = TRUE":string.Empty));
            GlobalLog.ThreadContract(ThreadKinds.Sync, "Connection#" + ValidationHelper.HashString(this) + "::SyncRead");

            // prevent recursive calls to this function
            if (t_SyncReadNesting > 0) {
                GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SyncRead() - nesting");
                return;
            }

            bool pollSuccess = probeRead? false: true;

            try {
                t_SyncReadNesting++;

                // grab a counter to tell us whenever the SetRequestContinue is called
                int requestContinueCount = probeRead ? request.RequestContinueCount : 0;

                bool requestDone;
                int bytesRead = -1;
                WebExceptionStatus errorStatus = WebExceptionStatus.ReceiveFailure;


                if (m_BytesScanned < m_BytesRead)
                {
                    // left over from previous read
                    pollSuccess = true;
                    bytesRead = 0; //tell it we want to use buffered data on the first iteration
                    errorStatus = WebExceptionStatus.Success;
                }

                do {
                    requestDone = true;

                    try {
                        if (bytesRead != 0)
                        {
                            errorStatus = WebExceptionStatus.ReceiveFailure;

                            if (!pollSuccess)
                            {
                                pollSuccess = Poll(request.ContinueTimeout * 1000, SelectMode.SelectRead);  // Timeout is in microseconds
                                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SyncRead() PollSuccess : " + pollSuccess);
                            }

                            if (pollSuccess)
                            {
                                //Ensures that we'll timeout eventually on an appdomain unload.
                                //Will be a no-op if the timeout doesn't change from request to request.
                                ReadTimeout = request.Timeout;

                                bytesRead = Read(m_ReadBuffer, m_BytesRead, m_ReadBuffer.Length - m_BytesRead);
                                errorStatus = WebExceptionStatus.Success;
                                if (bytesRead == 0)
                                    bytesRead = -1; // 0 is reserved for re-entry on already buffered data
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        if (NclUtilities.IsFatal(exception)) throw;

                        if (m_InnerException == null)
                            m_InnerException = exception;

                        if (exception.GetType() == typeof(ObjectDisposedException))
                            errorStatus = WebExceptionStatus.RequestCanceled;

                        // need to handle SSL errors too
#if !FEATURE_PAL
                        else if (NetworkStream is TlsStream)  {
                            errorStatus = ((TlsStream)NetworkStream).ExceptionStatus;
                        }
#endif // !FEATURE_PAL
                        else
                        {
                            SocketException socketException = exception.InnerException as SocketException;
                            if (socketException != null)
                            {
                                 if (socketException.ErrorCode == (int) SocketError.TimedOut)
                                    errorStatus = WebExceptionStatus.Timeout;
                                else
                                    errorStatus = WebExceptionStatus.ReceiveFailure;
                            }
                        }

                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SyncRead() Read() threw errorStatus:" + errorStatus.ToString() + " bytesRead:" + bytesRead.ToString());
                    }

                    if (pollSuccess)
                        requestDone = ReadComplete(bytesRead, errorStatus);

                    bytesRead = -1;
                } while (!requestDone && (userRetrievedStream || requestContinueCount == request.RequestContinueCount));
            }
            finally {
                t_SyncReadNesting--;
            }

            if (probeRead)
            {
                // [....] 100-Continue wait only
                request.FinishContinueWait();
                if (pollSuccess)
                {
                    if (!request.Saw100Continue && !userRetrievedStream)
                    {
                        //During polling, we got a response that wasn't a 100 continue.
                        request.NeedsToReadForResponse = false;
                    }
                }
                else
                {
                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SyncRead() Poll has timed out, calling SetRequestContinue().");
                    request.SetRequestContinue();
                }
            }
            GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SyncRead()");
        }
Example #3
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");
        }