Наследование: System.IO.Stream, ICloseEx, IRequestLifetimeTracker
Пример #1
0
        /*
            RequestSubmitDone - Handle submit done callback.

            This is our submit done handler, called by the underlying connection
            code when a stream is available for our use. We save the stream for
            later use and signal the wait event.

            We also handle the continuation/termination of a BeginGetRequestStream,
            by saving out the result and calling its callback if needed.

            Input:  SubmitStream        - The stream we may write on.
                    Status              - The status of the submission.

            Returns: Nothing.

        */
        internal void SetRequestSubmitDone(ConnectStream submitStream) {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone", ValidationHelper.HashString(submitStream));
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone");

            if (!Async) {
                ConnectionAsyncResult.InvokeCallback();
            }

            if (AllowWriteStreamBuffering) {
                submitStream.EnableWriteBuffering();
            }

            if (submitStream.CanTimeout) {
                submitStream.ReadTimeout = ReadWriteTimeout;
                submitStream.WriteTimeout = ReadWriteTimeout;
            }
            if(Logging.On)Logging.Associate(Logging.Web, this, submitStream);

            // The CBT won't actually be valid until we write to the stream for the first time, but we can create
            // the TransportContext now.  We don't query it until later, when we know it's available.
            TransportContext transportContext = new ConnectStreamContext(submitStream);
            ServerAuthenticationState.TransportContext = transportContext;
            ProxyAuthenticationState.TransportContext = transportContext;

            _SubmitWriteStream = submitStream;

            // Async RTC requests only.  Skip if ApplySetting has not been called so we can test
            // without IOControl support/workarounds.
            if (RtcState != null && RtcState.inputData != null && !RtcState.IsAborted)
            {
                RtcState.outputData = new byte[sizeof(RtcState.ControlChannelTriggerStatus)];
                RtcState.result = _SubmitWriteStream.SetRtcOption(RtcState.inputData, RtcState.outputData);
                if (!RtcState.IsEnabled())
                {
                    // Abort request if we weren't able to enable RTC.
                    Abort(null, AbortState.Public);
                }
                RtcState.connectComplete.Set();
            }

            //
            // This line is needed ONLY if we got a connect failure (Abort can still happen at random time)
            // CallDone will check for the write side response processing and this is what we want.
            // Note that [....] case already has a separate path to check for the response
            //
            if (Async && _CoreResponse != null && (object)_CoreResponse != (object)DBNull.Value)
            {
                GlobalLog.Assert(_CoreResponse is Exception, "SetRequestSubmitDone()|Found offensive response right after getting connection ({0}).", _CoreResponse);
                submitStream.CallDone();
                GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone() - already have a core response", _CoreResponse.GetType().FullName);
                return;
            }

            EndSubmitRequest();
            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone");
        }
Пример #2
0
        internal HttpWebResponse(
            Uri responseUri,
            string verb,
            CoreResponseData coreData,
            string mediaType,
            bool usesProxySemantics) {

            m_Uri                       = responseUri;
            m_Verb                      = verb;
            m_MediaType                 = mediaType;
            m_UsesProxySemantics        = usesProxySemantics;

            m_ConnectStream             = coreData.m_ConnectStream;
            m_HttpResponseHeaders       = coreData.m_ResponseHeaders;
            m_ContentLength             = coreData.m_ContentLength;
            m_StatusCode                = coreData.m_StatusCode;
            m_StatusDescription         = coreData.m_StatusDescription;
            m_Version                   = coreData.m_Version;

            // handle Content-Location header, by combining it with the orginal request.
            string contentLocation = m_HttpResponseHeaders[HttpKnownHeaderNames.ContentLocation];

            if (contentLocation != null) {
                try {
                    m_Uri = new Uri(m_Uri, contentLocation);
                } catch (Exception e) {
                    GlobalLog.Assert(false, "Exception on Uri parsing", e.ToString());
                }
            }
        }
Пример #3
0
        internal void WriteCallDone(ConnectStream stream, ConnectionReturnResult returnResult)
        {
            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteCallDone()");

            // Make sure this is the user stream.
            if (!object.ReferenceEquals(stream, _OldSubmitWriteStream != null ? _OldSubmitWriteStream : _SubmitWriteStream))
            {
                GlobalLog.Assert(object.ReferenceEquals(stream, _SubmitWriteStream), "HttpWebRequest#{0}::CallDone|Called from invalid stream.", ValidationHelper.HashString(this));
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteCallDone() - called for resubmit stream");
                stream.ProcessWriteCallDone(returnResult);
                return;
            }

            // If we're still writing headers in GetRequestStream, don't delay, or GetRequestStream will hang.
            if (!UserRetrievedWriteStream)
            {
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteCallDone() - called during headers");
                stream.ProcessWriteCallDone(returnResult);
                return;
            }

            // In some cases such as redirects, we do not expect a response from the server after we finish writing.
            if (stream.FinishedAfterWrite)
            {
                stream.ProcessWriteCallDone(returnResult);
                return;
            }

            object pendResult = returnResult == null ? (object) Missing.Value : returnResult;
            object oldResult = Interlocked.CompareExchange(ref m_PendingReturnResult, pendResult, null);
            if (oldResult == DBNull.Value)
            {
                stream.ProcessWriteCallDone(returnResult);
            }
#if TRAVE
            else if (oldResult == null)
            {
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteCallDone() - deferring processing");
            }
            else
            {
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteCallDone() - ignoring duplicate call.  typeof(oldResult):" + oldResult.GetType().ToString());
            }
#endif
        }
 internal ConnectStreamContext(ConnectStream connectStream)
 {
     GlobalLog.Assert(connectStream != null, "ConnectStreamContext..ctor(): Not expecting a null connectStream!");
     this.connectStream = connectStream;
 }
Пример #5
0
 internal WriteHeadersCallbackState(HttpWebRequest request, ConnectStream stream){
     this.request = request;
     this.stream = stream;
 }
Пример #6
0
        private void SubmitRequest(ServicePoint servicePoint)
        {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest");
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest");
            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest() HaveResponse:" + HaveResponse + " Saw100Continue:" + Saw100Continue);

            if (!Async)
            {
                _ConnectionAResult = new LazyAsyncResult(this, null, null);
                _ConnectionReaderAResult = new LazyAsyncResult(this, null, null);
                OpenWriteSideResponseWindow();
            }

            if (_Timer == null && !Async){
                _Timer = TimerQueue.CreateTimer(s_TimeoutCallback, this);
            }

            try {

                if (_SubmitWriteStream != null && _SubmitWriteStream.IsPostStream)
                {
                    // _OldSubmitWriteStream is the stream that holds real user data
                    // In no case it can be overwritten.
                    // For multiple resubmits the ContentLength was set already, so no need call it again.
                    // on first resubmission the real user data hasn't been saved, so _OldSubmitWriteStream is null
                    GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest() (resubmit) firstResubmission:" + (_OldSubmitWriteStream == null) + " NtlmKeepAlive:" + NtlmKeepAlive);
                    if (_OldSubmitWriteStream == null && !_SubmitWriteStream.ErrorInStream && AllowWriteStreamBuffering)
                    {
                        // save the real user data.
                        GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest() (resubmit) save the real user data _OldSubmitWriteStream#" + ValidationHelper.HashString(_OldSubmitWriteStream));
                        _OldSubmitWriteStream = _SubmitWriteStream;
                    }
                    // make sure we reformat the headers before resubmitting
                    _WriteBuffer = null;
                }

                m_Retry = false;

                // If pre-authentication is requested call the AuthenticationManager
                // and add authorization header if there is response
                if (PreAuthenticate) {
                    if (UsesProxySemantics && _Proxy != null && _Proxy.Credentials != null)
                        ProxyAuthenticationState.PreAuthIfNeeded(this, _Proxy.Credentials);
                    if (Credentials != null)
                        ServerAuthenticationState.PreAuthIfNeeded(this, Credentials);
                }

                if (WriteBuffer == null) {
                    UpdateHeaders();
                }

                if (CheckCacheRetrieveBeforeSubmit()) {
                    // We are done and internal Response processing is kicked in
                    GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest CACHED RESPONSE");
                    return;
                }

                // At this point we are going to send a live request
                // _AbortDelegate is set on submission process.
                servicePoint.SubmitRequest(this, GetConnectionGroupLine());
            }
            finally {
                if (!Async)
                    CheckWriteSideResponseProcessing();
            }
            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest");
        }
 internal ConnectStreamContext(ConnectStream connectStream)
 {
     this.connectStream = connectStream;
 }
Пример #8
0
        /*++

        Routine Description:

            CheckResubmit - Determines if a HTTP request needs to be
              resubmitted to a server point, this is called in Response
              Parsing to handle cases such as server Redirects,
              und Authentication

        Arguments:

            None.

        Return Value:

            true  - if we should reattempt submitting the request
            false - if the request is complete

        --*/
        private bool CheckResubmit() {
            GlobalLog.Enter("CheckResubmit");

            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::CheckResubmit()");

            if (ResponseStatusCode==HttpStatusCode.Unauthorized                 || // 401
                ResponseStatusCode==HttpStatusCode.ProxyAuthenticationRequired) {  // 407
                //
                // Check for Authentication
                //
                if (!CheckResubmitForAuth()) {
                    GlobalLog.Leave("CheckResubmit");
                    return false;
                }
            }
            else {
                //
                // Check for Redirection
                //
                // Table View:
                // Method            301             302             303             307
                //    *                *               *             GET               *
                // POST              GET             GET             GET            POST
                //
                // Put another way:
                //  301 & 302  - All methods are redirected to the same method but POST. POST is redirected to a GET.
                //  303 - All methods are redirected to GET
                //  307 - All methods are redirected to the same method.
                //

                if (_AllowAutoRedirect && (
                    ResponseStatusCode==HttpStatusCode.Ambiguous          || // 300
                    ResponseStatusCode==HttpStatusCode.Moved              || // 301
                    ResponseStatusCode==HttpStatusCode.Redirect           || // 302
                    ResponseStatusCode==HttpStatusCode.RedirectMethod     || // 303
                    ResponseStatusCode==HttpStatusCode.RedirectKeepVerb)) {  // 307

                    _AutoRedirects += 1;
                    if (_AutoRedirects > _MaximumAllowedRedirections) {
                        GlobalLog.Leave("CheckResubmit");
                        return false;
                    }

                    string Location = _HttpResponse.Headers["Location"];
                    string newMethod = _Verb;
                    bool DisableUpload = false;

                    switch (ResponseStatusCode) {
                        case HttpStatusCode.Moved:
                        case HttpStatusCode.Redirect:
                            if (string.Compare(newMethod, "POST", true, CultureInfo.InvariantCulture) == 0) {
                                newMethod = "GET";
                                DisableUpload = true;
                            }
                            break;

                        case HttpStatusCode.RedirectKeepVerb:
                            break;

                        case HttpStatusCode.RedirectMethod:
                        default:
                            DisableUpload = true;
                            newMethod = "GET";
                            break;
                    }

                    GlobalLog.Print("Location = " + Location);

                    if (Location != null) {
                        // set possible new Method
                        GlobalLog.Print("HttpWebRequest#"+ValidationHelper.HashString(this)+": changing Verb from "+_Verb+" to "+newMethod);
                        _Verb = newMethod;
                        if (DisableUpload) {
                            GlobalLog.Print("HttpWebRequest#"+ValidationHelper.HashString(this)+": disabling upload");
                            _ContentLength = -1;
                            _HttpWriteMode = HttpWriteMode.None;
                            _SubmitWriteStream = null;
                        }

                        Uri previousUri = _Uri;

                        try {
                            _Uri = new Uri(_Uri, Location, true);
                        }
                        catch (Exception exception) {
                            _ResponseException = new WebException(SR.GetString(SR.net_resubmitprotofailed),
                                                               exception,
                                                               WebExceptionStatus.ProtocolError,
                                                               _HttpResponse
                                                              );
                            GlobalLog.Leave("CheckResubmit");
                            return false;
                        }

                        if (_Uri.Scheme != Uri.UriSchemeHttp &&
                            _Uri.Scheme != Uri.UriSchemeHttps) {
                            _ResponseException = new WebException(SR.GetString(SR.net_resubmitprotofailed),
                                                               null,
                                                               WebExceptionStatus.ProtocolError,
                                                               _HttpResponse
                                                              );

                            GlobalLog.Leave("CheckResubmit");
                            return false;  // can't handle these redirects
                        }

                        try {
                            //Check for permissions against redirect Uri
                            (new WebPermission(NetworkAccess.Connect, _Uri.AbsoluteUri)).Demand();
                        }
                        catch {
                            // We are on other thread.
                            // Don't let the thread die but pass the error on to the user thread.
                            _ResponseException = new SecurityException(SR.GetString(SR.net_redirect_perm),
                                                                    new WebException(SR.GetString(SR.net_resubmitcanceled),
                                                                    null,
                                                                    WebExceptionStatus.ProtocolError,
                                                                    _HttpResponse)
                                                                    );
                            GlobalLog.Leave("CheckResubmit");
                            return false;
                        }

                        //
                        // make sure we're not sending over credential information to an evil redirection
                        // URI. this will set our credentials to null unless the user is using DefaultCredentials
                        // or a CredentialCache, in which case he is responsible for binding the credentials to
                        // the proper Uri and AuthenticationScheme.
                        //

                        ICredentials authTemp = _AuthInfo as CredentialCache;

                        if (authTemp==null) {
                            //
                            // if it's not a CredentialCache it could still be DefaultCredentials
                            // check for this case as well
                            //
                            _AuthInfo = _AuthInfo as SystemNetworkCredential;
                        }
                        else {
                            _AuthInfo = authTemp;
                        }

                        //
                        // do the necessary cleanup on the Headers involved in the
                        // Authentication handshake.
                        //
                        _ProxyAuthenticationState.ClearAuthReq(this);
                        _ServerAuthenticationState.ClearAuthReq(this);

                        GlobalLog.Print("HttpWebRequest#"+ValidationHelper.HashString(this)+": _Verb="+_Verb);
                        // resubmit
                    }
                    else {
                        GlobalLog.Leave("CheckResubmit");
                        return false;
                    }
                }
                else { // if (_AllowAutoRedirect)
                    GlobalLog.Leave("CheckResubmit");
                    return false;
                }
            } // else

            if ((_HttpWriteMode != HttpWriteMode.None) && !AllowWriteStreamBuffering && _ContentLength != 0) {
                _ResponseException = new WebException(SR.GetString(SR.net_need_writebuffering),
                                                        null,
                                                        WebExceptionStatus.ProtocolError,
                                                        _HttpResponse);


                GlobalLog.Leave("CheckResubmit");
                return false;
            }

            if (System.Net.Connection.IsThreadPoolLow()) {
                _ResponseException = new InvalidOperationException(SR.GetString(SR.net_needmorethreads));
                return false;
            }

            GlobalLog.Leave("CheckResubmit");
            return true;
        }
Пример #9
0
        /*++

            CheckFinalStatus - Check the final status of an HTTP response.

            This is a utility routine called from several places. We look
            at the final status of the HTTP response. If it's not 'success',
            we'll generate a WebException and throw that. Otherwise we'll
            do nothing.

            This should get merged into other code eventually. When all of
            the async work gets completed and we only generate a response in
            one place, this function should be called (or inlined) there.

            Input:

                Nothing.

            Returns:
                Nothing. May throw an exception.

        --*/

        private void CheckFinalStatus() {
            // Make sure we have seen a response. We might not have seen one
            // yet in some cases.

            Exception errorException = null;
            GlobalLog.Print("CheckFinalStatus");

            if (!_HaveResponse && !_Abort) {
                GlobalLog.Print("CheckFinalStatus - returning");
                return;
            }


            // Now see if we have a valid response. If not, throw the response
            // exception.

            errorException = _ResponseException;

            if (_HttpResponse != null) {
                errorException = _ResponseException;

                GlobalLog.Print("CheckFinalStatus - status" + (int)ResponseStatusCode);

                // We have a response. See if it's not valid. It's not valid if the
                // response code is greater than 399 (299 if we're not auto following
                // redirects.

                if (errorException == null && (int)ResponseStatusCode > (int)HttpStatusRange.MaxOkStatus) {
                    // Not a success status. Could be a redirect, which if OK if we're
                    // not auto following redirects.

                    if ((int)ResponseStatusCode > (int)HttpStatusRange.MaxRedirectionStatus ||
                        _AllowAutoRedirect) {


                        // Some sort of error. Generate, save and throw a new
                        // WebException.

                        if (_AutoRedirects > _MaximumAllowedRedirections) {
                            errorException = new WebException(
                                SR.GetString(SR.net_tooManyRedirections),
                                _ResponseException,
                                WebExceptionStatus.ProtocolError,
                                _HttpResponse );
                        }
                        else {
                            errorException = new WebException(
                                SR.GetString(SR.net_servererror,
                                    NetRes.GetWebStatusCodeString(ResponseStatusCode, _HttpResponse.StatusDescription)),
                                _ResponseException,
                                WebExceptionStatus.ProtocolError,
                                _HttpResponse );
                        }
                    }
                }

                // error, need to throw exception
                if (errorException != null) {
                    //
                    // Close the Stream to prevent it from breaking the
                    //  connection

                    if (_HttpResponse.ResponseStream != null) {

                        //
                        // copy off stream, don't just close it, if this
                        //  exception isn't handled, we've closed it,
                        //  if it is, then it gets read through a buffer.
                        //

                        ConnectStream connStream =  _HttpResponse.ResponseStream;
                        ConnectStream connNewStream = connStream.MakeMemoryStream();

                        _HttpResponse.ResponseStream = connNewStream;
                        connStream.CloseInternal(true);
                    }

                    _ResponseException = errorException;
                    _HttpResponse = null;
                }
            }

            if ( errorException != null) {
                if (_SubmitWriteStream != null) {
                    try {
                        _SubmitWriteStream.CloseInternal(true);
                    }
                    catch {
                    }

                    _SubmitWriteStream = null;
                }

                throw errorException;
            }
        }
Пример #10
0
        /*
            RequestSubmitDone - Handle submit done callback.

            This is our submit done handler, called by the underlying connection
            code when a stream is available for our use. We save the stream for
            later use and signal the wait event.

            We also handle the continuation/termination of a BeginGetRequestStream,
            by saving out the result and calling its callback if needed.

            Input:  SubmitStream        - The stream we may write on.
                    Status              - The status of the submission.

            Returns: Nothing.

        */
        internal void SetRequestSubmitDone(ConnectStream submitStream) {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone", ValidationHelper.HashString(submitStream));

            if (_Abort) {
                try {
                    submitStream.SetAbortState();
                    submitStream.CloseInternal(true);
                }
                catch {
                }

                GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone", "ABORT");
                return;
            }

             //This state should be set before invoking the callback
             //otherwise extra request will be issued without any
             //particular reason.

            _RequestSubmitted = true;
            _SubmitWriteStream = submitStream;

            // Finish the submission of the request. If the asyncResult now
            // isn't null, mark it as completed.

            WebExceptionStatus Error = EndSubmitRequest();

            if (Error != WebExceptionStatus.Pending) {

                // check for failure
                if (Error != WebExceptionStatus.Success) {
                    // OK, something happened on the request, close down stream
                    submitStream.SetAbortState();
                    submitStream.CloseInternal(true);
                }

                // wake up any pending waits to write, since this is an error
                if ( _WriteEvent != null ) {
                    GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone() calling _WriteEvent.Set()");
                    _WriteEvent.Set();
                }
            } // != Pending

            if (_Abort) {
                try {
                    submitStream.SetAbortState();
                    submitStream.CloseInternal(true);
                }
                catch {
                }
            }

            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone");
        }
Пример #11
0
        /*++

            BeginSubmitRequest: Begins Submit off a request to the network.

            This is called when we need to transmit an Async Request, but
            this function only servers to activate the submit, and does not
            actually block

            Called when we want to submit a request to the network. We do several
            things here - look for a proxy, find the service point, etc. In the
            end we call the service point to get access (via a stream) to the
            underlying connection, then serialize our headers onto that connection.
            The actual submission request to the service point is async, so we
            submit the request and then return, to allow the async to run its course.

            Input:
                forceFind - insures that always get a new ServicePoint,
                    needed on redirects, or where the ServicePoint may have changed

            Returns: Nothing

        --*/

        internal void BeginSubmitRequest(bool forceFind) {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::BeginSubmitRequest", forceFind.ToString());
            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + " " + Method + " " + Address);


            if (_SubmitWriteStream!=null) {
                long writeBytes = _SubmitWriteStream.BytesLeftToWrite;

                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::BeginSubmitRequest() _OldSubmitWriteStream:" + ValidationHelper.HashString(_OldSubmitWriteStream) + " _SubmitWriteStream:" + ValidationHelper.HashString(_SubmitWriteStream) + " writeBytes:" + writeBytes.ToString());

                if (writeBytes == 0) {
                    //
                    // we're resubmitting a request with an entity body
                    //
                    _OldSubmitWriteStream = _SubmitWriteStream;
                    if (_SubmitWriteStream.BufferedData!=null && _SubmitWriteStream.BufferedData.Length>0) {
                        //
                        // if we're resubmitting and buffering:
                        //
                        SetContentLength(_SubmitWriteStream.BufferedData.Length);
                        WriteBuffer = null;
                    }
                }
                else {
                    GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::BeginSubmitRequest() got a _SubmitWriteStream.WriteBytes:" + writeBytes.ToString());
                }
            }

            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::BeginSubmitRequest() _HaveResponse:" + _HaveResponse.ToString());
            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::BeginSubmitRequest() _RequestSubmitted:" + _RequestSubmitted.ToString());
            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::BeginSubmitRequest() Saw100Continue:" + Saw100Continue.ToString());

            // if we're submitting then we don't have a response
            _HaveResponse = false;
            _RequestSubmitted = true;

            ServicePoint servicePoint = FindServicePoint(forceFind);

            if ((_HttpWriteMode != HttpWriteMode.None) && (_WriteEvent == null)) {
                // don't create a WriteEvent until we are doing a Write
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::BeginSubmitRequest() lazy allocation of _WriteEvent");
                _WriteEvent = new AutoResetEvent(false);
            }

            _AbortDelegate = servicePoint.SubmitRequest(this, GetConnectionGroupLine());

            // prevent someone from sending chunked to a HTTP/1.0 server
            if (ChunkedUploadOnHttp10) {
                Abort();
                throw new ProtocolViolationException(SR.GetString(SR.net_nochunkuploadonhttp10));
            }

            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::BeginSubmitRequest");
        }
Пример #12
0
        /*
            Abort - Attempts to abort pending request,

            This calls into the delegate, and then closes any pending streams.

            Input: none

            Returns: none

        */
        /// <include file='doc\HttpWebRequest.uex' path='docs/doc[@for="HttpWebRequest.Abort"]/*' />
        public override void Abort()
        {
            _OnceFailed = true;
            _Abort = true;

            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::Abort()");

            _ResponseException = new WebException(
                    NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled),
                    WebExceptionStatus.RequestCanceled) ;

            _HaveResponse = true;

            try {
                if ( _AbortDelegate != null ) {
                    _AbortDelegate();
                    _AbortDelegate = null;
                }
            }
            catch {
            }

            try {
                if (_SubmitWriteStream != null) {
                    _SubmitWriteStream.CloseInternal(true);
                    _SubmitWriteStream = null;
                }
            }
            catch {
            }

            try {
                if (_HttpResponse != null) {
                    _HttpResponse.Close();
                }
            }
            catch {
            }
        }
 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);
         }
     }
 }
Пример #14
0
        /*++
            Uses an old Stream to resubmit buffered data using the current
             stream, this is used in cases of POST, or authentication,
             where we need to buffer upload data so that it can be resubmitted

            Input:

                OldStream - Old Stream that was previously used

            Returns:

                Nothing.

        --*/

        internal void ResubmitWrite(ConnectStream oldStream) {
            GlobalLog.Enter("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite", "ConnectStream");
            //
            // we're going to resubmit
            //
            ScatterGatherBuffers bufferedData = oldStream.BufferedData;

            Interlocked.Increment( ref m_CallNesting );
            GlobalLog.Print("Inc: " + m_CallNesting.ToString());

            try {
                //
                // no need to buffer here:
                // we're already resubmitting buffered data give it to the connection to put it on the wire again
                // we set BytesLeftToWrite to 0 'cause even on failure there can be no recovery,
                // so just leave it to IOError() to clean up and don't call ResubmitWrite()
                //
                m_Connection.Write(bufferedData);
                GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite() sent:" + bufferedData.Length.ToString() );
                BytesLeftToWrite = 0;
            }
            catch {
                IOError();
            }

            Interlocked.Decrement( ref m_CallNesting );
            GlobalLog.Print("Dec: " + m_CallNesting.ToString());

            SetWriteDone();

            CallDone();

            GlobalLog.Leave("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite", BytesLeftToWrite.ToString());
        }
Пример #15
0
        internal void WriteHeadersCallback(WebExceptionStatus errorStatus, ConnectStream stream, bool async)
        {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteHeadersCallback", ValidationHelper.HashString(stream));
            if(errorStatus == WebExceptionStatus.Success)
            {
                bool completed = EndWriteHeaders(async);
                if (!completed) {
                    errorStatus = WebExceptionStatus.Pending;
                }
                else {
                    GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(stream) + "::WriteHeaders completed:true BytesLeftToWrite:" + stream.BytesLeftToWrite.ToString());
                    if (stream.BytesLeftToWrite == 0) {
                        //
                        // didn't go pending, no data to write. we're done.
                        //
                        stream.CallDone();
                    }
                }
            }

            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteHeadersCallback", errorStatus.ToString());
        }
Пример #16
0
        internal void EndWriteHeaders_Part2()
        {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2");
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2");

            try {
                ConnectStream submitWriteStream = _SubmitWriteStream;
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2() ConnectStream#" + ValidationHelper.HashString(submitWriteStream) + " HttpWriteMode:" + HttpWriteMode + " HaveResponse:" + HaveResponse);
                if (HttpWriteMode != HttpWriteMode.None)
                {
                    m_BodyStarted = true;

                    GlobalLog.Assert(submitWriteStream != null, "HttpWebRequest#{0}::EndWriteHeaders_Part2()|submitWriteStream == null", ValidationHelper.HashString(this));
                    //
                    // We always need to buffer because some servers send
                    // 100 Continue even when they mean to redirect,
                    // so we waste the cycles with buffering
                    //
                    GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2() AllowWriteStreamBuffering:" + AllowWriteStreamBuffering);
                    if (AllowWriteStreamBuffering) {
                        GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2() BufferOnly:" + submitWriteStream.BufferOnly + " _OldSubmitWriteStream#" + ValidationHelper.HashString(_OldSubmitWriteStream) + " submitWriteStream#" + ValidationHelper.HashString(submitWriteStream));
                        if (submitWriteStream.BufferOnly) {
                            //
                            // if the ConnectStream was buffering the headers then
                            // there will not be an OldSubmitWriteStream. set it
                            // now to the newly created one.
                            //
                            _OldSubmitWriteStream = submitWriteStream;
                        }
                        if (_OldSubmitWriteStream != null)
                        {
                            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2() _OldSubmitWriteStream#" + ValidationHelper.HashString(_OldSubmitWriteStream) + " NtlmKeepAlive:" + NtlmKeepAlive);
            #if DEBUG
                            using (GlobalLog.SetThreadKind(ThreadKinds.Sync)) {
            #endif
                            submitWriteStream.ResubmitWrite(_OldSubmitWriteStream, (NtlmKeepAlive && ContentLength == 0));
            #if DEBUG
                            }
            #endif
                            submitWriteStream.CloseInternal(true);
                        }
                    }
                }
                else { // if (HttpWriteMode == HttpWriteMode.None) {
                    if (submitWriteStream != null) {
                        // close stream so the headers get sent
                        submitWriteStream.CloseInternal(true);
                        // disable write stream
                        submitWriteStream = null;
                    }
                    _OldSubmitWriteStream = null;
                }

                // callback processing - notify our caller that we're done
                InvokeGetRequestStreamCallback();
            }
            catch {
                // We depend on this to unblock possible response processing in case of unexpected failure
                ConnectStream chkStream = _SubmitWriteStream;
                if (chkStream != null)
                    chkStream.CallDone();

                //
                // Here we don't expect any exceptions and if got some from the user code then propagate it up.
                //
                throw;
            }

            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2");
        }
Пример #17
0
        //
        // Process an exception and optionally set request for retrying
        //
        private void SetResponse(Exception E) {
#if DEBUG
            bool callbackInvoked = false;
            try
            {
#endif
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse", E.ToString() + "/*** SETRESPONSE IN ERROR ***");
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse");

            HttpProcessingResult httpResult = HttpProcessingResult.Continue;

            //
            // Preserve the very first web exception occured if it was fatal
            //
            WebException webException = HaveResponse ? _ReadAResult.Result as WebException : null;
            WebException newWebException = E as WebException;
            if (webException != null && (webException.InternalStatus == WebExceptionInternalStatus.RequestFatal ||
                webException.InternalStatus == WebExceptionInternalStatus.ServicePointFatal) &&
                (newWebException == null || newWebException.InternalStatus != WebExceptionInternalStatus.RequestFatal))
            {
                E = webException;
            }
            else
            {
                webException = newWebException;
            }

            if (E != null)
            {
                if (Logging.On) Logging.Exception(Logging.Web, this, "", webException);
            }

            try {
                if ( webException != null &&
                     (webException.InternalStatus == WebExceptionInternalStatus.Isolated ||
                     webException.InternalStatus == WebExceptionInternalStatus.ServicePointFatal ||
                     (webException.InternalStatus == WebExceptionInternalStatus.Recoverable && !m_OnceFailed)))
                {

                    if (webException.InternalStatus == WebExceptionInternalStatus.Recoverable)
                        m_OnceFailed = true;

                    Pipelined = false;

                    if (_SubmitWriteStream != null && _OldSubmitWriteStream == null && _SubmitWriteStream.BufferOnly) {
                        _OldSubmitWriteStream = _SubmitWriteStream;
                    }

                    httpResult = DoSubmitRequestProcessing(ref E);
                }
            }
            catch (Exception unexpectedException)
            {
                if (NclUtilities.IsFatal(unexpectedException)) throw;

                // This is highly unexpected but if happens would result into Aborted exception with caught one as an inner exception
                httpResult = HttpProcessingResult.Continue;
                E = new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled), unexpectedException, WebExceptionStatus.RequestCanceled, _HttpResponse);
            }
            finally
            {
                if (httpResult == HttpProcessingResult.Continue)
                {
                    CancelTimer();

                    if (!(E is WebException) && !(E is SecurityException))
                    {
                        if (_HttpResponse==null) {
                            E = new WebException(E.Message, E);
                        }
                        else {
                            E = new WebException(
                                SR.GetString(
                                    SR.net_servererror,
                                    NetRes.GetWebStatusCodeString(
                                        ResponseStatusCode,
                                        _HttpResponse.StatusDescription)),
                                E,
                                WebExceptionStatus.ProtocolError,
                                _HttpResponse );
                        }
                    }

                    LazyAsyncResult writeAResult;
                    LazyAsyncResult readAResult = null;

                    // Async Abort may happen at any time including when the request is being cleared
                    // and resubmitted hence using checked response.
                    HttpWebResponse chkResponse = _HttpResponse;

                    lock (this)
                    {
                        writeAResult = _WriteAResult;

                        if (_ReadAResult == null)
                        {
                            _ReadAResult = new LazyAsyncResult(null, null, null, E); //never throws
                        }
                        else
                        {
                            readAResult = _ReadAResult;
                        }
                    }

                    try
                    {
                        FinishRequest(chkResponse, E); //never throws

                        try
                        {
                            if (writeAResult != null) {
                                writeAResult.InvokeCallback(E);
                            }
                        }
                        finally
                        {
                            if (readAResult != null) {
#if DEBUG
                                callbackInvoked = true;
#endif
                                readAResult.InvokeCallback(E);
                            }
                        }
                    }
                    finally
                    {
                        chkResponse = _ReadAResult.Result as HttpWebResponse;

                        // If the response was already set that exception closes it.
                        if (chkResponse != null)
                        {
                            chkResponse.Abort();    //never throws
                        }

                        if (CacheProtocol != null)
                        {
                            CacheProtocol.Abort();  //never throws
                        }
                    }
                }
#if DEBUG
                else
                {
                    callbackInvoked = true;
                }
#endif
            }
            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse", httpResult.ToString());
#if DEBUG
            }
            catch (Exception exception)
            {
                t_LastStressException = exception;

                if (!NclUtilities.IsFatal(exception)){
                    GlobalLog.Assert(callbackInvoked, "HttpWebRequest#{0}::SetResponse|{1}", ValidationHelper.HashString(this), exception.Message);
                }
                throw;
            }
#endif
        }
Пример #18
0
        /*
            RequestSubmitDone - Handle submit done callback.

            This is our submit done handler, called by the underlying connection
            code when a stream is available for our use. We save the stream for
            later use and signal the wait event.

            We also handle the continuation/termination of a BeginGetRequestStream,
            by saving out the result and calling its callback if needed.

            Input:  SubmitStream        - The stream we may write on.
                    Status              - The status of the submission.

            Returns: Nothing.

        */
        internal void SetRequestSubmitDone(ConnectStream submitStream)
        {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone", ValidationHelper.HashString(submitStream));
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone");

            if (!Async) {
                ConnectionAsyncResult.InvokeCallback();
            }

            if (AllowWriteStreamBuffering) {
                submitStream.EnableWriteBuffering();
            }

            if (submitStream.CanTimeout) {
                submitStream.ReadTimeout = ReadWriteTimeout;
                submitStream.WriteTimeout = ReadWriteTimeout;
            }
            if(Logging.On)Logging.Associate(Logging.Web, this, submitStream);
            _SubmitWriteStream = submitStream;

            //
            // This line is needed ONLY if we got a connect failure (Abort can still happen at random time)
            // CallDone will check for the write side response processing and this is what we want.
            // Note that Sync case already has a separate path to check for the response
            //
            if (Async && _CoreResponse != null && (object)_CoreResponse != (object)DBNull.Value)
            {
                GlobalLog.Assert(_CoreResponse is Exception, "SetRequestSubmitDone()|Found offensive response right after getting connection ({0}).", _CoreResponse);
                submitStream.CallDone();
                GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone() - already have a core response", _CoreResponse.GetType().FullName);
                return;
            }

            EndSubmitRequest();
            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitDone");
        }
Пример #19
0
        internal void EndWriteHeaders_Part2()
        {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2");
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2");

            try {
                ConnectStream submitWriteStream = _SubmitWriteStream;
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2() ConnectStream#" + ValidationHelper.HashString(submitWriteStream) + " HttpWriteMode:" + HttpWriteMode + " HaveResponse:" + HaveResponse);
                if (HttpWriteMode != HttpWriteMode.None)
                {
                    m_BodyStarted = true;

                    GlobalLog.Assert(submitWriteStream != null, "HttpWebRequest#{0}::EndWriteHeaders_Part2()|submitWriteStream == null", ValidationHelper.HashString(this));
                    //
                    // We always need to buffer because some servers send
                    // 100 Continue even when they mean to redirect,
                    // so we waste the cycles with buffering
                    //
                    GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2() AllowWriteStreamBuffering:" + AllowWriteStreamBuffering);
                    if (AllowWriteStreamBuffering || (_resendRequestContent != null)) {
                        GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2() BufferOnly:" + submitWriteStream.BufferOnly + " _OldSubmitWriteStream#" + ValidationHelper.HashString(_OldSubmitWriteStream) + " submitWriteStream#" + ValidationHelper.HashString(submitWriteStream));
                        if (submitWriteStream.BufferOnly) {
                            //
                            // if the ConnectStream was buffering the headers then
                            // there will not be an OldSubmitWriteStream. set it
                            // now to the newly created one.
                            //
                            _OldSubmitWriteStream = submitWriteStream;
                        }
                        if (_OldSubmitWriteStream != null || (UserRetrievedWriteStream && _resendRequestContent != null))
                        {
                            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2() _OldSubmitWriteStream#" + ValidationHelper.HashString(_OldSubmitWriteStream) + " NtlmKeepAlive:" + NtlmKeepAlive);
                            // workaround for NTLM: we're submitting this as ContentLength 0
                            // We need a second check for a buffering-only POST case.
                            // 
    #if DEBUG
                            using (GlobalLog.SetThreadKind(ThreadKinds.Sync)) {
    #endif
                            if (_resendRequestContent == null) {
                                submitWriteStream.ResubmitWrite(_OldSubmitWriteStream, (NtlmKeepAlive && ContentLength == 0));
                            }
                            else {
                                if (NtlmKeepAlive && ((ContentLength == 0) || (HttpWriteMode == HttpWriteMode.Chunked))) {
                                    // We just sent the 1st NTLM auth leg with a Content-Length value of 0. Don't
                                    // upload content. Just close the request stream (see CloseInternal() call below).
                                    if (ContentLength == 0) {
                                        submitWriteStream.BytesLeftToWrite = 0;
                                    }
                                }
                                else {
                                    // We don't have NTLM authentication or we sent headers for the 2nd NTLM auth leg.
                                    // Either way, we want to upload the request content now. If we know the length
                                    // of the content, update the request stream with this information.
                                    if (HttpWriteMode != HttpWriteMode.Chunked)
                                    {
                                        submitWriteStream.BytesLeftToWrite = _originalContentLength;
                                    }
                                    try
                                    {
                                        _resendRequestContent(submitWriteStream);
                                    }
                                    catch (Exception e)
                                    {
                                        // If the delegate throws, then catch the exception and abort the request. The
                                        // WebException thrown by Abort() contains the original exception as inner
                                        // exception (useful for debugging).
                                        Abort(e, AbortState.Public);
                                    }
                                }
                            }
    #if DEBUG
                            }
    #endif
                            submitWriteStream.CloseInternal(true);
                        }
                    }
                }
                else { // if (HttpWriteMode == HttpWriteMode.None) {
                    if (submitWriteStream != null) {
                        // close stream so the headers get sent
                        submitWriteStream.CloseInternal(true);
                        // disable write stream
                        submitWriteStream = null;
                    }
                    _OldSubmitWriteStream = null;
                }

                // callback processing - notify our caller that we're done
                InvokeGetRequestStreamCallback();
            }
            catch {
                // We depend on this to unblock possible response processing in case of unexpected failure
                ConnectStream chkStream = _SubmitWriteStream;
                if (chkStream != null)
                    chkStream.CallDone();

                //
                // Here we don't expect any exceptions and if got some from the user code then propagate it up.
                //
                throw;
            }

            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders_Part2");
        }
Пример #20
0
        internal void WriteCallDone(ConnectStream stream, ConnectionReturnResult returnResult)
        {
            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteCallDone()");

            // Make sure this is the user stream.
            if (!object.ReferenceEquals(stream, _OldSubmitWriteStream != null ? _OldSubmitWriteStream : _SubmitWriteStream))
            {
                GlobalLog.Assert(object.ReferenceEquals(stream, _SubmitWriteStream), "HttpWebRequest#{0}::CallDone|Called from invalid stream.", ValidationHelper.HashString(this));
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteCallDone() - called for resubmit stream");
                stream.ProcessWriteCallDone(returnResult);
                return;
            }

            // If we're still writing headers in GetRequestStream, don't delay, or GetRequestStream will hang.
            if (!UserRetrievedWriteStream)
            {
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::WriteCallDone() - called during headers");
                stream.ProcessWriteCallDone(returnResult);
                return;
            }

            object pendResult = returnResult == null ? (object) Missing.Value : returnResult;
            object oldResult = Interlocked.CompareExchange(ref m_PendingReturnResult, pendResult, null);
            if (oldResult == DBNull.Value)
            {
                stream.ProcessWriteCallDone(returnResult);
            }
        }
Пример #21
0
        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");
        }
Пример #22
0
        /// <devdoc>
        /// <para>Gets a <see cref='System.IO.Stream'/> that the application can use to write request data.
        ///    This property returns a stream that the calling application can write on.
        ///    This property is not settable.  Getting this property may cause the
        ///    request to be sent, if it wasn't already. Getting this property after
        ///    a request has been sent that doesn't have an entity body causes an
        ///    exception to be thrown.
        ///</para>
        /// </devdoc>
        public Stream GetRequestStream(out TransportContext context) {
#if DEBUG
            using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) {
#endif
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::GetRequestStream");
            if(Logging.On)Logging.Enter(Logging.Web, this, "GetRequestStream", "");

            context = null;

            CheckProtocol(true);

            // See if we're already submitted a request and have a result cached.
            if (_WriteAResult == null || !_WriteAResult.InternalPeekCompleted)
            {
                lock(this)
                {
                    if (_WriteAResult != null)
                    {
                        throw new InvalidOperationException(SR.GetString(SR.net_repcall));
                    }

                    // See if we're already submitted a request (e.g. via GetResponse).
                    if (SetRequestSubmitted())
                    {
                        // Not completed write stream, this is an application error.
                        throw new InvalidOperationException(SR.GetString(SR.net_reqsubmitted));
                    }

                    // If there's already been a _ReadAResult completed, it better have been with an exception, like an abort.
                    // We need to check within this lock.  Before the lock, _WriteAResult didn't exist so won't have been notified.
                    // BeginSubmitRequest() will fail silently if we go ahead and call it after an abort.  Since we know this is the
                    // first call to any of the [Begin]GetRe... methods by the above checks, we know ProcessResponse can't have been
                    // called or any other valid _ReadAResult created yet.
                    if (_ReadAResult != null)
                    {
                        GlobalLog.Assert(_ReadAResult.InternalPeekCompleted, "HttpWebRequest#{0}::GetRequestStream()|Incomplete _ReadAResult present on request.", ValidationHelper.HashString(this));
                        GlobalLog.Assert(_ReadAResult.Result is Exception, "HttpWebRequest#{0}::GetRequestStream()|_ReadAResult with successful completion already present on request.", ValidationHelper.HashString(this));
                        throw (Exception) _ReadAResult.Result;
                    }

                    // use the AsyncResult to return our Stream
                    _WriteAResult = new LazyAsyncResult(this, null, null);

                    Async = false;
                }

                // OK, we haven't submitted the request yet, so do so now
                // save off verb from origin Verb
                GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "GetRequestStream() resetting CurrentMethod to " + _OriginVerb);
                CurrentMethod = _OriginVerb;

                // Submit the Request, causes us to queue ourselves to a Connection and may block
                // It has happened that [....] path uses this loop the Retry memeber for handling resubmissions.
                while (m_Retry && !_WriteAResult.InternalPeekCompleted) {
                    _OldSubmitWriteStream = null;
                    _SubmitWriteStream = null;
                    BeginSubmitRequest();
                }

                while(Aborted && !_WriteAResult.InternalPeekCompleted)
                {
                    // spin untill the _CoreResponse is set
                    if (!(_CoreResponse is Exception))
                        Thread.SpinWait(1);
                    else
                        CheckWriteSideResponseProcessing();
                }
            }

            ConnectStream connectStream = _WriteAResult.InternalWaitForCompletion() as ConnectStream;
            _WriteAResult.EndCalled = true;
            if (connectStream == null)
            {
                if (Logging.On) Logging.Exception(Logging.Web, this, "EndGetRequestStream", _WriteAResult.Result as Exception);
                throw (Exception) _WriteAResult.Result;
            }

            context = new ConnectStreamContext(connectStream);

            if(Logging.On)Logging.Exit(Logging.Web, this, "GetRequestStream", connectStream);
            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::GetRequestStream", ValidationHelper.HashString(connectStream));
            return connectStream;
#if DEBUG
            }
#endif
        }
Пример #23
0
 public StreamChunkBytes(ConnectStream connectStream) {
     ChunkStream = connectStream;
     return;
 }
Пример #24
0
        private void CheckDeferredCallDone(ConnectStream stream)
        {
            object returnResult = Interlocked.Exchange(ref m_PendingReturnResult, DBNull.Value);
            if (returnResult == NclConstants.Sentinel)
            {
#if DEBUG
                if (!Async)
                {
                    using (GlobalLog.SetThreadKind(ThreadKinds.Sync)) {
                        EndSubmitRequest();
                    }
                }
                else
#endif
                EndSubmitRequest();
            }
            else if (returnResult != null && returnResult != DBNull.Value)
            {
                // It could still be Missing.Value, which indicates ProcessWriteCallDone() should be called with null.
                stream.ProcessWriteCallDone(returnResult as ConnectionReturnResult);
            }
        }
Пример #25
0
        /*++
            Uses an old Stream to resubmit buffered data using the current
             stream, this is used in cases of POST, or authentication,
             where we need to buffer upload data so that it can be resubmitted

            Input:

                OldStream - Old Stream that was previously used

            Returns:

                Nothing.

        --*/

        // 
        internal void ResubmitWrite(ConnectStream oldStream, bool suppressWrite) {
            GlobalLog.Enter("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite", ValidationHelper.HashString(oldStream));
            GlobalLog.ThreadContract(ThreadKinds.Sync, "ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite");

            //
            // 




            //
            // we're going to resubmit
            //
            try {
                Interlocked.CompareExchange(ref m_CallNesting, Nesting.InternalIO, Nesting.Idle);
                GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite() Inc: " + m_CallNesting.ToString());

                GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite(), callNesting : " + m_CallNesting.ToString() + " IsClosed = " + IsClosed);
                //
                // no need to buffer here:
                // we're already resubmitting buffered data give it to the connection to put it on the wire again
                // we set BytesLeftToWrite to 0 'cause even on failure there can be no recovery,
                // so just leave it to IOError() to clean up and don't call ResubmitWrite()
                //
                ScatterGatherBuffers bufferedData = oldStream.BufferedData;
                SafeSetSocketTimeout(SocketShutdown.Send);
                if (!WriteChunked) {
                    if (!suppressWrite)
                        m_Connection.Write(bufferedData);
                }
                else {
                    // we have the data buffered, but we still want to chunk.

                    // first set this to disable Close() from sending a chunk terminator.
                    GlobalLog.Assert(m_HttpWriteMode != HttpWriteMode.None, "ConnectStream#{0}::ResubmitWrite()|m_HttpWriteMode == HttpWriteMode.None", ValidationHelper.HashString(this));
                    m_HttpWriteMode = HttpWriteMode.ContentLength;

                    if (bufferedData.Length==0) {
                        m_Connection.Write(NclConstants.ChunkTerminator, 0, NclConstants.ChunkTerminator.Length);
                    }
                    else {
                        int chunkHeaderOffset = 0;
                        byte[] chunkHeaderBuffer = GetChunkHeader(bufferedData.Length, out chunkHeaderOffset);
                        BufferOffsetSize[] dataBuffers = bufferedData.GetBuffers();
                        BufferOffsetSize[] buffers = new BufferOffsetSize[dataBuffers.Length + 3];
                        buffers[0] = new BufferOffsetSize(chunkHeaderBuffer, chunkHeaderOffset, chunkHeaderBuffer.Length - chunkHeaderOffset, false);
                        int index = 0;
                        foreach (BufferOffsetSize buffer in dataBuffers) {
                            buffers[++index] = buffer;
                        }
                        buffers[++index] = new BufferOffsetSize(NclConstants.CRLF, 0, NclConstants.CRLF.Length, false);
                        buffers[++index] = new BufferOffsetSize(NclConstants.ChunkTerminator, 0, NclConstants.ChunkTerminator.Length, false);

                        SplitWritesState splitState = new SplitWritesState(buffers);

                        BufferOffsetSize[] sendBuffers = splitState.GetNextBuffers();
                        while(sendBuffers != null){
                            m_Connection.MultipleWrite(sendBuffers);
                            sendBuffers = splitState.GetNextBuffers();
                        }
                    }
                }
                if(Logging.On && bufferedData.GetBuffers() != null) {
                    foreach (BufferOffsetSize bufferOffsetSize in bufferedData.GetBuffers()) {
                        if (bufferOffsetSize == null) {
                            Logging.Dump(Logging.Web, this, "ResubmitWrite", null, 0, 0);
                        }
                        else {
                            Logging.Dump(Logging.Web, this, "ResubmitWrite", bufferOffsetSize.Buffer, bufferOffsetSize.Offset, bufferOffsetSize.Size);
                        }
                    }
                }
                GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite() sent:" + bufferedData.Length.ToString() );
            }
            catch (Exception exception)
            {
                if (NclUtilities.IsFatal(exception)) throw;

                // A Fatal error
                WebException we = new WebException(NetRes.GetWebStatusString("net_connclosed", WebExceptionStatus.SendFailure),
                                               WebExceptionStatus.SendFailure,
                                               WebExceptionInternalStatus.RequestFatal,
                                               exception);
                IOError(we, false);
            }
            finally {
                Interlocked.CompareExchange(ref m_CallNesting, Nesting.Idle, Nesting.InternalIO);
                GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite(), callNesting : " + m_CallNesting.ToString() + " IsClosed = " + IsClosed);
            }
            m_BytesLeftToWrite = 0;
            CallDone();
            GlobalLog.Leave("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite", BytesLeftToWrite.ToString());
        }
Пример #26
0
        /*++

            Close - Closes the Response after the use.

            This causes the read stream to be closed.

        --*/

        /// <include file='doc\HttpWebResponse.uex' path='docs/doc[@for="HttpWebResponse.Close"]/*' />
        public override void Close() {
            ConnectStream chkConnectStream = m_ConnectStream;
            m_ConnectStream = null;                
            if (chkConnectStream!=null) {
                chkConnectStream.Close();
            }
        }