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());
                }
            }
        }
 internal Connection(System.Net.ConnectionGroup connectionGroup) : base(null)
 {
     this.m_IISVersion = -1;
     this.m_Free = true;
     this.m_Idle = true;
     this.m_KeepAlive = true;
     this.m_MaximumUnauthorizedUploadLength = SettingsSectionInternal.Section.MaximumUnauthorizedUploadLength;
     if (this.m_MaximumUnauthorizedUploadLength > 0L)
     {
         this.m_MaximumUnauthorizedUploadLength *= 0x400L;
     }
     this.m_ResponseData = new CoreResponseData();
     this.m_ConnectionGroup = connectionGroup;
     this.m_ReadBuffer = new byte[0x1000];
     this.m_ReadState = ReadState.Start;
     this.m_WaitList = new List<WaitListItem>();
     this.m_WriteList = new ArrayList();
     this.m_AbortDelegate = new HttpAbortDelegate(this.AbortOrDisassociate);
     this.m_ConnectionUnlock = new UnlockConnectionDelegate(this.UnlockRequest);
     this.m_StatusLineValues = new StatusLineValues();
     this.m_RecycleTimer = this.ConnectionGroup.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer();
     this.ConnectionGroup.Associate(this);
     this.m_ReadDone = true;
     this.m_WriteDone = true;
     this.m_Error = WebExceptionStatus.Success;
 }
Exemple #3
0
        internal HttpWebResponse(Uri responseUri, KnownHttpVerb verb, CoreResponseData coreData, string mediaType, bool usesProxySemantics, DecompressionMethods decompressionMethod) {
            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_IsVersionHttp11           = coreData.m_IsVersionHttp11;


            //if the returned contentlength is zero, preemptively invoke calldone on the stream.
            //this will wake up any pending reads.
            if (m_ContentLength == 0 && m_ConnectStream is ConnectStream) {
                ((ConnectStream)m_ConnectStream).CallDone();
            }

            // 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 (UriFormatException e) {
                    GlobalLog.Assert("Exception on response Uri parsing.", e.ToString());
                }
            }
            // decompress responses by hooking up a final response Stream - only if user required it
            if(decompressionMethod != DecompressionMethods.None) {
                string contentEncoding = m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding];
                if (contentEncoding != null){ 
                    if(((decompressionMethod & DecompressionMethods.GZip) != 0) && contentEncoding.IndexOf(HttpWebRequest.GZipHeader) != -1) {
                        m_ConnectStream = new GZipWrapperStream(m_ConnectStream, CompressionMode.Decompress);
                        m_ContentLength = -1; // unknown on compressed streams
    
                        // Setting a response header after parsing will ruin the Common Header optimization.
                        // This seems like a corner case.  ContentEncoding could be added as a common header, with a special
                        // property allowing it to be nulled.
                        m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding] = null;
                    }
                    else if (((decompressionMethod & DecompressionMethods.Deflate) != 0) && contentEncoding.IndexOf(HttpWebRequest.DeflateHeader) != -1) {
                        m_ConnectStream = new DeflateWrapperStream(m_ConnectStream, CompressionMode.Decompress);
                        m_ContentLength = -1; // unknown on compressed streams
    
                        // Setting a response header after parsing will ruin the Common Header optimization.
                        // This seems like a corner case.  ContentEncoding could be added as a common header, with a special
                        // property allowing it to be nulled.
                        m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding] = null;
                    }
                }
            }
        }
        internal HttpWebResponse(Uri responseUri, KnownHttpVerb verb, CoreResponseData coreData, string mediaType, bool usesProxySemantics, DecompressionMethods decompressionMethod)
        {
            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_IsVersionHttp11           = coreData.m_IsVersionHttp11;

            //if the returned contentlength is zero, preemptively invoke calldone on the stream.
            //this will wake up any pending reads.
            if (m_ContentLength == 0 && m_ConnectStream is ConnectStream) {
                ((ConnectStream)m_ConnectStream).CallDone();
            }

            // 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 (UriFormatException e) {
                    GlobalLog.Assert("Exception on response Uri parsing.", e.ToString());
                }
            }
            // decompress responses by hooking up a final response Stream - only if user required it
            if(decompressionMethod != DecompressionMethods.None) {
                string contentEncoding = m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding];
                if (contentEncoding != null){
                    if(((decompressionMethod & DecompressionMethods.GZip) != 0) && contentEncoding.IndexOf(HttpWebRequest.GZipHeader) != -1) {
                        m_ConnectStream = new GZipWrapperStream(m_ConnectStream, CompressionMode.Decompress);
                        m_ContentLength = -1; // unknown on compressed streams

                        // Setting a response header after parsing will ruin the Common Header optimization.
                        // This seems like a corner case.  ContentEncoding could be added as a common header, with a special
                        // property allowing it to be nulled.
                        m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding] = null;
                    }
                    else if (((decompressionMethod & DecompressionMethods.Deflate) != 0) && contentEncoding.IndexOf(HttpWebRequest.DeflateHeader) != -1) {
                        m_ConnectStream = new DeflateWrapperStream(m_ConnectStream, CompressionMode.Decompress);
                        m_ContentLength = -1; // unknown on compressed streams

                        // Setting a response header after parsing will ruin the Common Header optimization.
                        // This seems like a corner case.  ContentEncoding could be added as a common header, with a special
                        // property allowing it to be nulled.
                        m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding] = null;
                    }
                }
            }
        }
Exemple #5
0
        internal CoreResponseData Clone()
        {
            CoreResponseData cloneResponseData = new CoreResponseData();

            cloneResponseData.m_StatusCode        = m_StatusCode;
            cloneResponseData.m_StatusDescription = m_StatusDescription;
            cloneResponseData.m_IsVersionHttp11   = m_IsVersionHttp11;
            cloneResponseData.m_ContentLength     = m_ContentLength;
            cloneResponseData.m_ResponseHeaders   = m_ResponseHeaders;
            cloneResponseData.m_ConnectStream     = m_ConnectStream;
            return(cloneResponseData);
        }
 internal static void Add(ref ConnectionReturnResult returnResult, HttpWebRequest request, CoreResponseData coreResponseData)
 {
     if (coreResponseData == null)
     {
         throw new InternalException();
     }
     if (returnResult == null)
     {
         returnResult = new ConnectionReturnResult();
     }
     returnResult.m_Context.Add(new RequestContext(request, coreResponseData));
 }
        /// <summary>
        /// Creates WEB response based on information known just after parsing the status line.
        /// </summary>
        /// <param name="method">Http Verb</param>
        /// <param name="responseUrl">TBD</param>
        /// <param name="data">Response data</param>
        /// <param name="httpWebReq">TBD</param>
        internal HttpWebResponse(string method, Uri responseUrl,
                                 CoreResponseData data, HttpWebRequest httpWebReq)
        {
            m_httpWebRequest    = httpWebReq;
            m_method            = method;
            m_url               = responseUrl;
            m_version           = data.m_version;
            m_statusCode        = data.m_statusCode;
            m_statusDescription = data.m_statusDescription;

            m_httpResponseHeaders = data.m_headers;

            m_contentLength = data.m_contentLength;
        }
Exemple #8
0
        internal HttpWebResponse(Uri responseUri, KnownHttpVerb verb, CoreResponseData coreData, string mediaType, bool usesProxySemantics, DecompressionMethods decompressionMethod)
        {
            this.m_Uri                 = responseUri;
            this.m_Verb                = verb;
            this.m_MediaType           = mediaType;
            this.m_UsesProxySemantics  = usesProxySemantics;
            this.m_ConnectStream       = coreData.m_ConnectStream;
            this.m_HttpResponseHeaders = coreData.m_ResponseHeaders;
            this.m_ContentLength       = coreData.m_ContentLength;
            this.m_StatusCode          = coreData.m_StatusCode;
            this.m_StatusDescription   = coreData.m_StatusDescription;
            this.m_IsVersionHttp11     = coreData.m_IsVersionHttp11;
            if ((this.m_ContentLength == 0L) && (this.m_ConnectStream is ConnectStream))
            {
                ((ConnectStream)this.m_ConnectStream).CallDone();
            }
            string relativeUri = this.m_HttpResponseHeaders["Content-Location"];

            if (relativeUri != null)
            {
                try
                {
                    this.m_Uri = new Uri(this.m_Uri, relativeUri);
                }
                catch (UriFormatException)
                {
                }
            }
            if (decompressionMethod != DecompressionMethods.None)
            {
                string str2 = this.m_HttpResponseHeaders["Content-Encoding"];
                if (str2 != null)
                {
                    if (((decompressionMethod & DecompressionMethods.GZip) != DecompressionMethods.None) && (str2.IndexOf("gzip") != -1))
                    {
                        this.m_ConnectStream = new GZipWrapperStream(this.m_ConnectStream, CompressionMode.Decompress);
                        this.m_ContentLength = -1L;
                        this.m_HttpResponseHeaders["Content-Encoding"] = null;
                    }
                    else if (((decompressionMethod & DecompressionMethods.Deflate) != DecompressionMethods.None) && (str2.IndexOf("deflate") != -1))
                    {
                        this.m_ConnectStream = new DeflateWrapperStream(this.m_ConnectStream, CompressionMode.Decompress);
                        this.m_ContentLength = -1L;
                        this.m_HttpResponseHeaders["Content-Encoding"] = null;
                    }
                }
            }
        }
 internal HttpWebResponse(Uri responseUri, KnownHttpVerb verb, CoreResponseData coreData, string mediaType, bool usesProxySemantics, DecompressionMethods decompressionMethod)
 {
     this.m_Uri = responseUri;
     this.m_Verb = verb;
     this.m_MediaType = mediaType;
     this.m_UsesProxySemantics = usesProxySemantics;
     this.m_ConnectStream = coreData.m_ConnectStream;
     this.m_HttpResponseHeaders = coreData.m_ResponseHeaders;
     this.m_ContentLength = coreData.m_ContentLength;
     this.m_StatusCode = coreData.m_StatusCode;
     this.m_StatusDescription = coreData.m_StatusDescription;
     this.m_IsVersionHttp11 = coreData.m_IsVersionHttp11;
     if ((this.m_ContentLength == 0L) && (this.m_ConnectStream is ConnectStream))
     {
         ((ConnectStream) this.m_ConnectStream).CallDone();
     }
     string relativeUri = this.m_HttpResponseHeaders["Content-Location"];
     if (relativeUri != null)
     {
         try
         {
             this.m_Uri = new Uri(this.m_Uri, relativeUri);
         }
         catch (UriFormatException)
         {
         }
     }
     if (decompressionMethod != DecompressionMethods.None)
     {
         string str2 = this.m_HttpResponseHeaders["Content-Encoding"];
         if (str2 != null)
         {
             if (((decompressionMethod & DecompressionMethods.GZip) != DecompressionMethods.None) && (str2.IndexOf("gzip") != -1))
             {
                 this.m_ConnectStream = new GZipWrapperStream(this.m_ConnectStream, CompressionMode.Decompress);
                 this.m_ContentLength = -1L;
                 this.m_HttpResponseHeaders["Content-Encoding"] = null;
             }
             else if (((decompressionMethod & DecompressionMethods.Deflate) != DecompressionMethods.None) && (str2.IndexOf("deflate") != -1))
             {
                 this.m_ConnectStream = new DeflateWrapperStream(this.m_ConnectStream, CompressionMode.Decompress);
                 this.m_ContentLength = -1L;
                 this.m_HttpResponseHeaders["Content-Encoding"] = null;
             }
         }
     }
 }
        /// <summary>
        /// Reads and parses HTTP response from server.
        /// After return of function HTTP response is read.
        /// </summary>
        /// <param name="inStream">Network stream connected to server.</param>
        /// <param name="defaultKeepAlive">TBD</param>
        /// <returns>CoreResponseData that describes server response.</returns>
        private CoreResponseData ParseHTTPResponse(InputNetworkStreamWrapper inStream, bool defaultKeepAlive)
        {
            // CoreResponseData keeps all the information of the response.
            CoreResponseData ret = new CoreResponseData();
            // maximumHeadersLength is maximum total length of http header. Basically this is amount
            // of memory used for headers.
            int headersLength = m_maxResponseHeadersLen == -1 ? 0x7FFFFFFF : m_maxResponseHeadersLen * 1024;

            ret.m_shouldClose = !defaultKeepAlive;
            // Parse the request line.
            string line = inStream.Read_HTTP_Line(maxHTTPLineLength).Trim();

            // Cutoff white spaces
            int currentOffset = 0;
            for (; currentOffset < line.Length && ' ' != line[currentOffset]; ++currentOffset) ;

            // find HTTP version, read http/1.x
            string httpVersionString = line.Substring(0, currentOffset).ToLower();
            if (httpVersionString.Equals("http/1.1"))
            {
                ret.m_version = HttpVersion.Version11;
            }
            else if (httpVersionString.Equals("http/1.0"))
            {
                ret.m_version = HttpVersion.Version10;
            }
            else
            {
                ret.m_status = WebExceptionStatus.ServerProtocolViolation;
                ret.m_exceptionMessage = "Unknown http version: " + httpVersionString;
                return ret;
            }

            //advance to the status code
            for (; currentOffset < line.Length && ' ' == line[currentOffset]; ++currentOffset) ;

            // Read the status code
            int codeStart = currentOffset;
            for (; currentOffset < line.Length && ' ' != line[currentOffset]; ++currentOffset) ;
            int statusCode = -1;
            try
            {
                string statusCodeStr =
                    line.Substring(codeStart,
                                    currentOffset - codeStart);
                statusCode = Convert.ToInt32(statusCodeStr);
            }
            catch (Exception e)
            {
                ret.m_status = WebExceptionStatus.ServerProtocolViolation;
                ret.m_exceptionMessage = "Missing status code in HTTP reply";
                ret.m_innerException = e;
                return ret;
            }

            // If we get here - status code should be read.
            ret.m_statusCode = statusCode;

            // Advance to the status message.  The message is optional
            for (; currentOffset < line.Length && ' ' != line[currentOffset]; ++currentOffset) ;
            ret.m_statusDescription = line.Substring(currentOffset);

            ret.m_headers = new WebHeaderCollection(true);
            ret.m_chunked = false;
            ret.m_contentLength = -1;

            while ((line = inStream.Read_HTTP_Header(maxHTTPLineLength)).Length > 0)
            {
                // line.Length is used for the header. Substruct it.
                headersLength -= line.Length;
                // If total length used for header is exceeded, we break
                if (headersLength < 0)
                {
                    ret.m_status = WebExceptionStatus.ServerProtocolViolation;
                    ret.m_exceptionMessage = "Headers size exceed limit";
                    return ret;
                }

                // Now parse the header.
                int sepIdx = line.IndexOf(':');
                if (sepIdx == -1)
                {
                    ret.m_status = WebExceptionStatus.ServerProtocolViolation;
                    ret.m_exceptionMessage = "Illegal header format: " + line;
                    return ret;
                }

                string headerName = line.Substring(0, sepIdx);
                string headerValue = line.Substring(sepIdx + 1).TrimStart(null);
                string matchableHeaderName = headerName.ToLower();

                ret.m_headers.AddInternal(headerName, headerValue);
                if (matchableHeaderName.Equals("content-length"))
                {
                    try
                    {
                        ret.m_contentLength = Convert.ToInt32(headerValue);

                        // set the response stream length for the input stream, so that an EOF will be read
                        // if the caller tries to read base the response content length
                        inStream.m_BytesLeftInResponse = ret.m_contentLength;
                    }
                    catch (Exception e)
                    {
                        ret.m_status =
                            WebExceptionStatus.ServerProtocolViolation;
                        ret.m_exceptionMessage = "Content length NAN: " + headerValue;
                        ret.m_innerException = e;
                        return ret;
                    }
                }
                else if (matchableHeaderName.Equals("transfer-encoding"))
                {
                    if (headerValue.ToLower().IndexOf("chunked") != -1)
                    {
                        ret.m_chunked = true;
                    }
                }
                else if (matchableHeaderName.Equals("connection"))
                {
                    if (headerValue.ToLower().IndexOf(HttpKnownHeaderValues.close) != -1)
                    {
                        ret.m_shouldClose = true;
                    }
                }
            }

            return ret;
        }
Exemple #11
0
 internal static void Add(ref ConnectionReturnResult returnResult, HttpWebRequest request, CoreResponseData coreResponseData)
 {
     if (coreResponseData == null)
     {
         throw new InternalException();
     }
     if (returnResult == null)
     {
         returnResult = new ConnectionReturnResult();
     }
     returnResult.m_Context.Add(new RequestContext(request, coreResponseData));
 }
Exemple #12
0
 internal static void Add(ref ConnectionReturnResult returnResult, HttpWebRequest request, CoreResponseData coreResponseData) {
     if (returnResult == null) {
         returnResult = new ConnectionReturnResult();
     }
     request.CoreResponse = coreResponseData;
     returnResult.m_RequestList.Add(request);
 }
Exemple #13
0
        //
        // This method has to be invoked as part of the wire response processing.
        // The wire response can be replaced on return
        //
        // ATTN: If the method returns false, the response is invalid and should be retried
        //
        private bool CheckCacheRetrieveOnResponse() {
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::CheckCacheRetrieveOnResponse");

            if (CacheProtocol == null) {
                return true;
            }

            if (CacheProtocol.ProtocolStatus == CacheValidationStatus.Fail) {
                throw CacheProtocol.ProtocolException;
            }

            Stream oldResponseStream = _HttpResponse.ResponseStream;

            CacheProtocol.GetRevalidateStatus(_HttpResponse, _HttpResponse.ResponseStream);

            if (CacheProtocol.ProtocolStatus == CacheValidationStatus.RetryResponseFromServer)
            {
                // Try to resubmit or fail
                return false;
            }

            if (CacheProtocol.ProtocolStatus != CacheValidationStatus.ReturnCachedResponse &&
                CacheProtocol.ProtocolStatus != CacheValidationStatus.CombineCachedAndServerResponse)
            {
                // Take current response
                return true;
            }

            if (HttpWriteMode!=HttpWriteMode.None) {
                // This should never happen in real life
                throw new NotSupportedException(SR.GetString(SR.net_cache_not_supported_body));
            }

            CoreResponseData responseData = new CoreResponseData();
            HttpRequestCacheValidator ctx = (HttpRequestCacheValidator) CacheProtocol.Validator;
            // If we take it from cache, we have to replace the live response if any
            responseData.m_IsVersionHttp11  = ctx.CacheHttpVersion.Equals(HttpVersion.Version11);
            responseData.m_StatusCode       = ctx.CacheStatusCode;
            responseData.m_StatusDescription= ctx.CacheStatusDescription;

            responseData.m_ResponseHeaders  = CacheProtocol.ProtocolStatus == CacheValidationStatus.CombineCachedAndServerResponse
                                                ? new WebHeaderCollection(ctx.CacheHeaders)
                                                : ctx.CacheHeaders;

            responseData.m_ContentLength    = CacheProtocol.ResponseStreamLength;
            responseData.m_ConnectStream    = CacheProtocol.ResponseStream;

            _HttpResponse = new HttpWebResponse(GetRemoteResourceUri(), CurrentMethod, responseData,
                _MediaType, UsesProxySemantics, AutomaticDecompression, IsWebSocketRequest, ConnectionGroupName);

            if (CacheProtocol.ProtocolStatus == CacheValidationStatus.ReturnCachedResponse)
            {
                _HttpResponse.InternalSetFromCache = true;
                _HttpResponse.InternalSetIsCacheFresh = CacheProtocol.IsCacheFresh;

                // can only dispose the response stream when not combining the streams
                // Note the response itself may still be needed for cache update call.
                if (oldResponseStream != null)
                {
                    try {
                        oldResponseStream.Close();
                    }
                    catch {
                    }
                }
            }
            return true;
        }
Exemple #14
0
        //
        // This method may be invoked as part of the request submission but
        // before the response is received
        // Return:
        // - True       = response is ready
        // - False      = Proceed with the request submission
        private bool CheckCacheRetrieveBeforeSubmit() {
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::CheckCacheRetrieveBeforeSubmit");

            if (CacheProtocol == null) {
                return false;
            }

            try
            {
                Uri cacheUri = GetRemoteResourceUri();
                if (cacheUri.Fragment.Length != 0)
                    cacheUri = new Uri(cacheUri.GetParts(UriComponents.AbsoluteUri & ~UriComponents.Fragment, UriFormat.SafeUnescaped));

                CacheProtocol.GetRetrieveStatus(cacheUri, this);

                if (CacheProtocol.ProtocolStatus == CacheValidationStatus.Fail) {
                    throw CacheProtocol.ProtocolException;
                }

                if (CacheProtocol.ProtocolStatus != CacheValidationStatus.ReturnCachedResponse) {
                    return false;
                }

                if (HttpWriteMode!=HttpWriteMode.None) {
                    throw new NotSupportedException(SR.GetString(SR.net_cache_not_supported_body));
                }

                // If we take it from cache, we have to kick in response processing
                // The _CacheStream is good to return as the response stream.
                HttpRequestCacheValidator ctx = (HttpRequestCacheValidator) CacheProtocol.Validator;
                CoreResponseData responseData = new CoreResponseData();
                responseData.m_IsVersionHttp11  = ctx.CacheHttpVersion.Equals(HttpVersion.Version11);
                responseData.m_StatusCode       = ctx.CacheStatusCode;
                responseData.m_StatusDescription= ctx.CacheStatusDescription;
                responseData.m_ResponseHeaders  = ctx.CacheHeaders;
                responseData.m_ContentLength    = CacheProtocol.ResponseStreamLength;
                responseData.m_ConnectStream    = CacheProtocol.ResponseStream;
                _HttpResponse = new HttpWebResponse(GetRemoteResourceUri(), CurrentMethod, responseData,
                    _MediaType, UsesProxySemantics, AutomaticDecompression, IsWebSocketRequest, ConnectionGroupName);
                _HttpResponse.InternalSetFromCache = true;
                _HttpResponse.InternalSetIsCacheFresh = (ctx.CacheFreshnessStatus != CacheFreshnessStatus.Stale);
                ProcessResponse();
                return true;
            }
            catch (Exception exception)
            {
                Abort(exception, AbortState.Public);
                throw;
            }
        }
Exemple #15
0
 internal static void SetResponse(ConnectionReturnResult returnResult, HttpWebRequest request, CoreResponseData coreResponseData) {
     try {
         request.SetResponse(coreResponseData);
     }
     catch {
         if (returnResult != null && returnResult.m_RequestList.Count>0) {
             ThreadPool.QueueUserWorkItem(s_InvokeConnectionCallback, returnResult);
         }
         throw;
     }
     if (returnResult!= null) {
         ConnectionReturnResult.SetResponses(returnResult);
     }
 }
        internal Connection(ConnectionGroup connectionGroup) : base(null) {
            //
            // add this Connection to the pool in the connection group,
            //  keep a weak reference to it
            //
            m_MaximumUnauthorizedUploadLength = SettingsSectionInternal.Section.MaximumUnauthorizedUploadLength;
            if(m_MaximumUnauthorizedUploadLength > 0){
                m_MaximumUnauthorizedUploadLength*=1024;
            }
            m_ResponseData = new CoreResponseData();
            m_ConnectionGroup = connectionGroup;
            m_ReadBuffer = new byte[4096];    // Using a fixed 4k read buffer.
            m_ReadState = ReadState.Start;
            m_WaitList = new List<WaitListItem>();
            m_WriteList = new ArrayList();
            m_AbortDelegate = new HttpAbortDelegate(AbortOrDisassociate);
            m_ConnectionUnlock = new UnlockConnectionDelegate(UnlockRequest);

            // for status line parsing
            m_StatusLineValues = new StatusLineValues();
            m_RecycleTimer = ConnectionGroup.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer();
            // the following line must be the last line of the constructor
            ConnectionGroup.Associate(this);
            m_ReadDone = true;
            m_WriteDone = true;
            m_Error = WebExceptionStatus.Success;
        }
Exemple #17
0
        /*++

            ParseResponseData - Parses the incomming headers, and handles
              creation of new streams that are found while parsing, and passes
              extra data the new streams

            Input:

                returnResult - returns an object containing items that need to be called
                    at the end of the read callback

            Returns:

                bool - true if one should continue reading more data

        --*/
        private DataParseStatus ParseResponseData(ref ConnectionReturnResult returnResult) {

            DataParseStatus parseStatus = DataParseStatus.NeedMoreData;
            DataParseStatus parseSubStatus;

            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData()");

            // loop in case of multiple sets of headers or streams,
            //  that may be generated due to a pipelined response

            do {

                // Invariants: at the start of this loop, m_BytesRead
                // is the number of bytes in the buffer, and m_BytesScanned
                // is how many bytes of the buffer we've consumed so far.
                // and the m_ReadState var will be updated at end of
                // each code path, call to this function to reflect,
                // the state, or error condition of the parsing of data
                //
                // We use the following variables in the code below:
                //
                //  m_ReadState - tracks the current state of our Parsing in a
                //      response. z.B.
                //      Start - initial start state and begining of response
                //      StatusLine - the first line sent in response, include status code
                //      Headers - \r\n delimiated Header parsing until we find entity body
                //      Data - Entity Body parsing, if we have all data, we create stream directly
                //
                //  m_ResponseData - An object used to gather Stream, Headers, and other
                //      tidbits so that a Request/Response can receive this data when
                //      this code is finished processing
                //
                //  m_ReadBuffer - Of course the buffer of data we are parsing from
                //
                //  m_CurrentRequestIndex - index into the window of a buffer where
                //      we are currently parsing.  Since there can be multiple requests
                //      this index is used to the track the offset, based off of 0
                //
                //  m_BytesScanned - The bytes scanned in this buffer so far,
                //      since its always assumed that parse to completion, this
                //      var becomes ended of known data at the end of this function,
                //      based off of 0
                //
                //  m_BytesRead - The total bytes read in buffer, should be const,
                //      till its updated at end of function.
                //
                //  m_HeadersBytesUnparsed - The bytes scanned in the headers,
                //      needs to be seperate because headers are not always completely
                //      parsed to completion on each interation
                //

                //
                // Now attempt to parse the data,
                //   we first parse status line,
                //   then read headers,
                //   and finally transfer results to a new stream, and tell request
                //

                switch (m_ReadState) {

                    case ReadState.Start:

                        m_ResponseData = new CoreResponseData();
                        m_ReadState = ReadState.StatusLine;
                        m_CurrentRequestIndex = m_BytesScanned;

                        InitializeParseStatueLine();

                        goto case ReadState.StatusLine;

                    case ReadState.StatusLine:
                        //
                        // Reads HTTP status response line
                        //
                        parseSubStatus =
                            ParseStatusLine(
                                m_ReadBuffer, // buffer we're working with
                                m_BytesRead,  // total bytes read so far
                                ref m_BytesScanned, // index off of what we've scanned
                                ref m_StatusLineInts,
                                ref m_StatusDescription,
                                ref m_StatusState );

                        if (parseSubStatus == DataParseStatus.Invalid) {
                            //
                            // report error
                            //
                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseStatusLine() ParseHeaders() returned Invalid protocol usage");
                            parseStatus = DataParseStatus.Invalid;

                            // advance back to state 0, in failure
                            m_ReadState = ReadState.Start;

                            break;
                        }
                        else if (parseSubStatus == DataParseStatus.Done) {
                            SetStatusLineParsed();
                            m_ReadState = ReadState.Headers;
                            m_HeadersBytesUnparsed = m_BytesScanned;
                            m_ResponseData.m_ResponseHeaders = new WebHeaderCollection(true);

                            goto case ReadState.Headers;
                        }

                        break; // read more data

                    case ReadState.Headers:
                        //
                        // Parse additional lines of header-name: value pairs
                        //
                        if (m_HeadersBytesUnparsed>=m_BytesRead) {
                            //
                            // we already can tell we need more data
                            //
                            break;
                        }

                        parseSubStatus =
                            m_ResponseData.m_ResponseHeaders.ParseHeaders(
                                m_ReadBuffer,
                                m_BytesRead,
                                ref m_HeadersBytesUnparsed );

                        if (parseSubStatus == DataParseStatus.Invalid) {
                            //
                            // report error
                            //
                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() ParseHeaders() returned Invalid protocol usage");
                            parseStatus = DataParseStatus.Invalid;

                            // advance back to state 0, in failure
                            m_ReadState = ReadState.Start;

                            break;
                        }
                        else if (parseSubStatus == DataParseStatus.Done) {

                            m_BytesScanned = m_HeadersBytesUnparsed; // update actual size of scanned headers

                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() got (" + ((int)m_ResponseData.m_StatusCode).ToString() + ") from the server");

                            // If we have an HTTP continue, eat these headers and look
                            //  for the 200 OK
                            if (m_ResponseData.m_StatusCode == HttpStatusCode.Continue) {

                                HttpWebRequest Request;

                                // wakeup post code if needed
                                lock(this) {

                                    GlobalLog.Assert(
                                        m_WriteList.Count > 0,
                                        "Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData(): m_WriteList.Count <= 0",
                                        "");

                                    if ( m_WriteList.Count == 0 ) {
                                        parseStatus = DataParseStatus.Invalid;

                                        // advance back to state 0, in failure
                                        m_ReadState = ReadState.Start;
                                        break;
                                    }

                                    Request = (HttpWebRequest)m_WriteList[0];
                                }

                                GlobalLog.Assert(
                                    Request != null,
                                    "Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData(): Request == null",
                                    "");

                                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() HttpWebRequest#" + ValidationHelper.HashString(Request));

                                //
                                // we got a 100 Continue. set this on the HttpWebRequest
                                //
                                Request.Saw100Continue = true;
                                if (!m_Server.Understands100Continue) {
                                    //
                                    // and start expecting it again if this behaviour was turned off
                                    //
                                    GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(Request) + " ServicePoint#" + ValidationHelper.HashString(m_Server) + " sent UNexpected 100 Continue");
                                    m_Server.Understands100Continue = true;
                                }

                                //
                                // set Continue Ack on Request.
                                //
                                if (Request.ContinueDelegate != null) {
                                    //
                                    // invoke the 100 continue delegate if the user supplied one
                                    //
                                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() calling ContinueDelegate()");
                                    Request.ContinueDelegate((int)m_ResponseData.m_StatusCode, m_ResponseData.m_ResponseHeaders);
                                }

                                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() calling SetRequestContinue()");
                                Request.SetRequestContinue();
                                m_ReadState = ReadState.Start;

                                goto case ReadState.Start;
                            }

                            m_ReadState = ReadState.Data;
                            goto case ReadState.Data;
                        }

                        // need more data,
                        //
                        // But unfornately ParseHeaders does not work,
                        //   the same way as all other code in this function,
                        //   since its old code, it assumes BytesScanned bytes will be always
                        //   around between calls until it has all the data, but that is NOT
                        //   true, since we can do block copy between calls.
                        //
                        //  To handle this we fix up the offsets.

                        // We assume we scanned all the way to the end of valid buffer data
                        m_BytesScanned = m_BytesRead;

                        break;

                    case ReadState.Data:

                        // (check status code for continue handling)
                        // 1. Figure out if its Chunked, content-length, or encoded
                        // 2. Takes extra data, place in stream(s)
                        // 3. Wake up blocked stream requests
                        //

                        // advance back to state 0
                        m_ReadState = ReadState.Start;

                        // parse and create a stream if needed
                        DataParseStatus result = ParseStreamData(ref returnResult);

                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() result - " + result.ToString());

                        switch (result) {

                            case DataParseStatus.NeedMoreData:
                                //
                                // cont reading. Only way we can get here is if the request consumed
                                // all the bytes in the buffer. So reset everything.
                                //
                                m_BytesRead = 0;
                                m_BytesScanned = 0;
                                m_CurrentRequestIndex = 0;

                                parseStatus = DataParseStatus.NeedMoreData;
                                break;

                            case DataParseStatus.ContinueParsing:

                                continue;

                            case DataParseStatus.Invalid:
                            case DataParseStatus.Done:

                                //
                                // NOTE: WARNING: READ THIS:
                                //  Upon update of this code, keep in mind,
                                //  that when DataParseStatus.Done is returned
                                //  from ParseStreamData, it can mean that ReadStartNextRequest()
                                //  has been called.  That means that we should no longer
                                //  change ALL this.m_* vars, since those variables, can now
                                //  be used on other threads.
                                //


                                // DataParseStatus.Done will cause an error below

                                parseStatus = result;
                                break;
                        }
                        break;
                }

                break;

            } while (true);

            GlobalLog.Print("m_ReadState - " + m_ReadState.ToString());
            GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData()", parseStatus.ToString());
            return parseStatus;
        }
Exemple #18
0
 internal CoreResponseData Clone() {
     CoreResponseData cloneResponseData = new CoreResponseData();
     cloneResponseData.m_StatusCode        = m_StatusCode;
     cloneResponseData.m_StatusDescription = m_StatusDescription;
     cloneResponseData.m_IsVersionHttp11   = m_IsVersionHttp11;
     cloneResponseData.m_ContentLength     = m_ContentLength;
     cloneResponseData.m_ResponseHeaders   = m_ResponseHeaders;
     cloneResponseData.m_ConnectStream     = m_ConnectStream;
     return cloneResponseData;
 }
Exemple #19
0
        /*++

            HandleError - Handle a protocol error from the server.

            This method is called when we've detected some sort of fatal protocol
            violation while parsing a response, receiving data from the server,
            or failing to connect to the server. We'll fabricate
            a WebException and then call CloseConnection which closes the
            connection as well as informs the Request through a callback.

            Input:
                    webExceptionStatus -
                    connectFailure -
                    readFailure -

            Returns: Nothing

        --*/
        private void HandleError(WebExceptionStatus webExceptionStatus, ConnectionFailureGroup failureGroup, ref ConnectionReturnResult returnResult) {

            Monitor.Enter(this);

            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::HandleError() writeListcount: " + m_WriteList.Count.ToString() + " m_WriteDone:" + m_WriteDone.ToString() + " failureGroup:" + failureGroup.ToString());

            if (failureGroup != ConnectionFailureGroup.Receive) {
                if ((m_WriteList.Count!=0) && (failureGroup != ConnectionFailureGroup.Connect)) {
                    HttpWebRequest Request = (HttpWebRequest)m_WriteList[0];
                    Request.OnceFailed = true;
                    GlobalLog.Print("Request = " + ValidationHelper.HashString(Request));
                }
                else {
                    // if there are no WriteList requests, then we can
                    //  assume that WriteDone is true, this is usually
                    //  caused by servers send illegal data (e.g. bad contentlengths),

                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::HandleError() setting m_WriteDone:" + m_WriteDone.ToString() + " to true");
                    m_WriteDone = true;
                }
            }

            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::HandleError() m_WriteDone:" + m_WriteDone.ToString());

            m_ResponseData = null;
            //m_ReadState = ReadState.Start;
            m_ReadDone = true;
            //Tunnelling = false;
            m_Error = webExceptionStatus;

            // It's possible that we could have a write in progress, and we
            // don't want to close the connection underneath him. Since thisConnection
            // is a completion of our read buffer, it's safe for us to
            // set thisConnection.m_ReadDone to true. So if there's not a write in
            // progress, close the connection. If there a write in progress,
            // wait for the write to complete before closing the socket.

            if (m_WriteDone) {
                CloseConnectionSocket(m_Error, ref returnResult);
            }
            else {
                Monitor.Exit(this);
            }
        }
Exemple #20
0
        /*++

        Routine Description:

            Wakes up blocked threads, so they can read response object,
              from the result

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

        Arguments:

            coreData - Contains the data used to create the Response object
            exception - true if we're allowed to throw an exception on error

        Return Value:

            none

        --*/
        internal void SetResponse(CoreResponseData coreResponseData) {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse", "*** SETRESP ***");

            //
            // Since we are no longer attached to this Connection,
            // we null out our abort delegate.
            //

            _AbortDelegate = null;

            try {
                if (coreResponseData != null) {
                    _HttpResponse = new HttpWebResponse(_Uri, _Verb, coreResponseData, _MediaType, UsesProxySemantics);
                    coreResponseData = null;
                }
                else {

                    //
                    // not sure how this would happen, but we should not throw an exception,
                    //  which we were earlier doing.
                    //

                    GlobalLog.Assert(false,
                                 "coreResponseData == null",
                                 "");


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

                //
                // give apps the chance to examine the headers of the new response
                //

                if (_CookieContainer != null) {
                    CookieModule.OnReceivedHeaders(this);
                }

                // New Response

                HttpProcessingResult httpResult = HttpProcessingResult.Continue;

                // handle redirects, authentication, and such
                httpResult = DoSubmitRequestProcessing();

                if (httpResult == HttpProcessingResult.Continue) {
                    //
                    // Now grab crit sec here, before returning,
                    //  this is to prevent some one from reading
                    //  ReadAResult it as null before we finish
                    //  processing our response
                    //

                    LazyAsyncResult asyncResult = null;
                    lock(this)
                    {
                        asyncResult = _ReadAResult;

                        GlobalLog.Assert(asyncResult == null || this == (HttpWebRequest)asyncResult.AsyncObject,
                                     "SetResponse: this != asyncResult.AsyncObject",
                                     "");

                        GlobalLog.Assert(asyncResult == null || !asyncResult.IsCompleted, "SetResponse: asyncResult already completed!", "");

                        _HaveResponse = true;

                        if (asyncResult != null) {
                            _ReadAResult = null;
                        }
                    }

                    if (asyncResult != null) {
                        asyncResult.InvokeCallback(false, _HttpResponse);
                    }

                    if ( _WriteEvent != null ) {
                        GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse(CoreResponseData) calling _WriteEvent.Set()");
                        _WriteEvent.Set();
                    }
                }
            } catch (Exception exception) {
                Abort();
                GlobalLog.LeaveException("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse", exception);
                throw;
            }

            if (_Abort) {
                try {
                    if ( _HttpResponse != null ) {
                        _HttpResponse.Close();
                    }
                }
                catch {
                }

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

            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse");
        }
        /// <summary>
        /// Creates WEB response based on information known just after parsing the status line.
        /// </summary>
        /// <param name="method">Http Verb</param>
        /// <param name="responseUrl">TBD</param>
        /// <param name="data">Response data</param>
        /// <param name="httpWebReq">TBD</param>
        internal HttpWebResponse(string method, Uri responseUrl,
                                  CoreResponseData data, HttpWebRequest httpWebReq)
        {
            m_httpWebRequest = httpWebReq;
            m_method = method;
            m_url = responseUrl;
            m_version = data.m_version;
            m_statusCode = data.m_statusCode;
            m_statusDescription = data.m_statusDescription;

            m_httpResponseHeaders = data.m_headers;

            m_contentLength = data.m_contentLength;
        }
Exemple #22
0
        internal Connection(ConnectionGroup connectionGroup) : base(null) {
            //
            // add this Connection to the pool in the connection group,
            //  keep a weak reference to it
            //
            m_MaximumUnauthorizedUploadLength = SettingsSectionInternal.Section.MaximumUnauthorizedUploadLength;
            if(m_MaximumUnauthorizedUploadLength > 0){
                m_MaximumUnauthorizedUploadLength*=1024;
            }
            m_ResponseData = new CoreResponseData();
            m_ConnectionGroup = connectionGroup;
            m_ReadBuffer = s_PinnableBufferCache.AllocateBuffer();
            m_ReadBufferFromPinnableCache = true;
            m_ReadState = ReadState.Start;
            m_WaitList = new List<WaitListItem>();
            m_WriteList = new ArrayList();
            m_AbortDelegate = new HttpAbortDelegate(AbortOrDisassociate);
            m_ConnectionUnlock = new UnlockConnectionDelegate(UnlockRequest);

            // for status line parsing
            m_StatusLineValues = new StatusLineValues();
            m_RecycleTimer = ConnectionGroup.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer();
            // the following line must be the last line of the constructor
            ConnectionGroup.Associate(this);
            m_ReadDone = true;
            m_WriteDone = true;
            m_Error = WebExceptionStatus.Success;
            if (PinnableBufferCacheEventSource.Log.IsEnabled())
            {
                PinnableBufferCacheEventSource.Log.DebugMessage1("CTOR: In System.Net.Connection.Connnection", this.GetHashCode());
            }
        }
        internal static void Add(ref ConnectionReturnResult returnResult, HttpWebRequest request, CoreResponseData coreResponseData)
        {
            if (coreResponseData == null)
                throw new InternalException(); //This may cause duplicate requests if we let it through in retail

            if (returnResult == null) {
                returnResult = new ConnectionReturnResult();
            }

#if DEBUG
            //This may cause duplicate requests if we let it through in retail but it's may be expensive to catch here
            for (int j = 0; j <  returnResult.m_Context.Count; ++j)
                if ((object)returnResult.m_Context[j].Request == (object) request)
                    throw new InternalException();
#endif

            returnResult.m_Context.Add(new RequestContext(request, coreResponseData));
        }
        /*++

            ParseResponseData - Parses the incomming headers, and handles
              creation of new streams that are found while parsing, and passes
              extra data the new streams

            Input:

                returnResult - returns an object containing items that need to be called
                    at the end of the read callback

            Returns:

                bool - true if one should continue reading more data

        --*/
        private DataParseStatus ParseResponseData(ref ConnectionReturnResult returnResult, out bool requestDone, out CoreResponseData continueResponseData)
        {
            GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData()");

            DataParseStatus parseStatus = DataParseStatus.NeedMoreData;
            DataParseStatus parseSubStatus;

            // Indicates whether or not at least one whole request was processed in this loop.
            // (i.e. Whether ParseStreamData() was called.
            requestDone = false;
            continueResponseData = null;

            // loop in case of multiple sets of headers or streams,
            //  that may be generated due to a pipelined response

                // Invariants: at the start of this loop, m_BytesRead
                // is the number of bytes in the buffer, and m_BytesScanned
                // is how many bytes of the buffer we've consumed so far.
                // and the m_ReadState var will be updated at end of
                // each code path, call to this function to reflect,
                // the state, or error condition of the parsing of data
                //
                // We use the following variables in the code below:
                //
                //  m_ReadState - tracks the current state of our Parsing in a
                //      response. z.B.
                //      Start - initial start state and begining of response
                //      StatusLine - the first line sent in response, include status code
                //      Headers - \r\n delimiated Header parsing until we find entity body
                //      Data - Entity Body parsing, if we have all data, we create stream directly
                //
                //  m_ResponseData - An object used to gather Stream, Headers, and other
                //      tidbits so that a request/Response can receive this data when
                //      this code is finished processing
                //
                //  m_ReadBuffer - Of course the buffer of data we are parsing from
                //
                //  m_BytesScanned - The bytes scanned in this buffer so far,
                //      since its always assumed that parse to completion, this
                //      var becomes ended of known data at the end of this function,
                //      based off of 0
                //
                //  m_BytesRead - The total bytes read in buffer, should be const,
                //      till its updated at end of function.
                //

                //
                // Now attempt to parse the data,
                //   we first parse status line,
                //   then read headers,
                //   and finally transfer results to a new stream, and tell request
                //

                switch (m_ReadState) {

                    case ReadState.Start:


                        if (m_CurrentRequest == null)
                        {
                            lock (this)
                            {
                                if (m_WriteList.Count == 0 || ((m_CurrentRequest = m_WriteList[0] as HttpWebRequest) == null))
                                {
                                    m_ParseError.Section = WebParseErrorSection.Generic;
                                    m_ParseError.Code    = WebParseErrorCode.Generic;
                                    parseStatus = DataParseStatus.Invalid;
                                    break;
                                }
                            }
                        }

                        //
                        // Start of new response. Transfer the keep-alive context from the corresponding request to
                        // the connection
                        //
                        m_KeepAlive &= (m_CurrentRequest.KeepAlive || m_CurrentRequest.NtlmKeepAlive);

                        m_MaximumResponseHeadersLength = m_CurrentRequest.MaximumResponseHeadersLength * 1024;
                        m_ResponseData = new CoreResponseData();
                        m_ReadState = ReadState.StatusLine;
                        m_TotalResponseHeadersLength = 0;

                        InitializeParseStatusLine();
                        goto case ReadState.StatusLine;

                    case ReadState.StatusLine:
                        //
                        // Reads HTTP status response line
                        //
                        if (SettingsSectionInternal.Section.UseUnsafeHeaderParsing)
                        {
                            // This one uses an array to store the parsed values in.  Marshal between this legacy way.
                            int[] statusInts = new int[] { 0, m_StatusLineValues.MajorVersion, m_StatusLineValues.MinorVersion, m_StatusLineValues.StatusCode };
                            if (m_StatusLineValues.StatusDescription == null)
                                m_StatusLineValues.StatusDescription = "";

                            parseSubStatus = ParseStatusLine(
                                m_ReadBuffer, // buffer we're working with
                                m_BytesRead,  // total bytes read so far
                                ref m_BytesScanned, // index off of what we've scanned
                                ref statusInts,
                                ref m_StatusLineValues.StatusDescription,
                                ref m_StatusState,
                                ref m_ParseError);

                            m_StatusLineValues.MajorVersion = statusInts[1];
                            m_StatusLineValues.MinorVersion = statusInts[2];
                            m_StatusLineValues.StatusCode = statusInts[3];
                        }
                        else
                        {
                            parseSubStatus = ParseStatusLineStrict(
                                m_ReadBuffer, // buffer we're working with
                                m_BytesRead,  // total bytes read so far
                                ref m_BytesScanned, // index off of what we've scanned
                                ref m_StatusState,
                                m_StatusLineValues,
                                m_MaximumResponseHeadersLength,
                                ref m_TotalResponseHeadersLength,
                                ref m_ParseError);
                        }

                        if (parseSubStatus == DataParseStatus.Done)
                        {
                            if (Logging.On) Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_received_status_line, m_StatusLineValues.MajorVersion+"."+m_StatusLineValues.MinorVersion, m_StatusLineValues.StatusCode, m_StatusLineValues.StatusDescription));
                            SetStatusLineParsed();
                            m_ReadState = ReadState.Headers;
                            m_ResponseData.m_ResponseHeaders = new WebHeaderCollection(WebHeaderCollectionType.HttpWebResponse);
                            goto case ReadState.Headers;
                        }
                        else if (parseSubStatus != DataParseStatus.NeedMoreData)
                        {
                            //
                            // report error - either Invalid or DataTooBig
                            //
                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() ParseStatusLine() parseSubStatus:" + parseSubStatus.ToString());
                            parseStatus = parseSubStatus;
                            break;
                        }

                        break; // read more data

                    case ReadState.Headers:
                        //
                        // Parse additional lines of header-name: value pairs
                        //
                        if (m_BytesScanned >= m_BytesRead) {
                            //
                            // we already can tell we need more data
                            //
                            break;
                        }

                        if (SettingsSectionInternal.Section.UseUnsafeHeaderParsing)
                        {
                            parseSubStatus = m_ResponseData.m_ResponseHeaders.ParseHeaders(
                                m_ReadBuffer,
                                m_BytesRead,
                                ref m_BytesScanned,
                                ref m_TotalResponseHeadersLength,
                                m_MaximumResponseHeadersLength,
                                ref m_ParseError);
                        }
                        else
                        {
                            parseSubStatus = m_ResponseData.m_ResponseHeaders.ParseHeadersStrict(
                                m_ReadBuffer,
                                m_BytesRead,
                                ref m_BytesScanned,
                                ref m_TotalResponseHeadersLength,
                                m_MaximumResponseHeadersLength,
                                ref m_ParseError);
                        }

                        if (parseSubStatus == DataParseStatus.Invalid || parseSubStatus == DataParseStatus.DataTooBig)
                        {
                            //
                            // report error
                            //
                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() ParseHeaders() parseSubStatus:" + parseSubStatus.ToString());
                            parseStatus = parseSubStatus;
                            break;
                        }
                        else if (parseSubStatus == DataParseStatus.Done)
                        {
                            if (Logging.On) Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_received_headers, m_ResponseData.m_ResponseHeaders.ToString(true)));

                            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() DataParseStatus.Done StatusCode:" + (int)m_ResponseData.m_StatusCode + " m_BytesRead:" + m_BytesRead + " m_BytesScanned:" + m_BytesScanned);

                            //get the IIS server version
                            if(m_IISVersion == -1){
                                string server = m_ResponseData.m_ResponseHeaders.Server;
                                if (server != null && server.ToLower(CultureInfo.InvariantCulture).Contains("microsoft-iis")){
                                    int i = server.IndexOf("/");
                                    if(i++>0 && i <server.Length){
                                        m_IISVersion = server[i++] - '0';
                                        while(i < server.Length && Char.IsDigit(server[i])) {
                                            m_IISVersion = m_IISVersion*10 + server[i++] - '0';
                                        }
                                    }
                                }
                                //we got a response,so if we don't know the server by now and it wasn't a 100 continue,
                                //we can't assume we will ever know it.  IIS5 sends its server header w/ the continue

                                if(m_IISVersion == -1 && m_ResponseData.m_StatusCode != HttpStatusCode.Continue){
                                    m_IISVersion = 0;
                                }
                            }

                            if (m_ResponseData.m_StatusCode == HttpStatusCode.Continue || m_ResponseData.m_StatusCode == HttpStatusCode.BadRequest) {

                                GlobalLog.Assert(m_CurrentRequest != null, "Connection#{0}::ParseResponseData()|m_CurrentRequest == null", ValidationHelper.HashString(this));
                                GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() HttpWebRequest#" + ValidationHelper.HashString(m_CurrentRequest));

                                if (m_ResponseData.m_StatusCode == HttpStatusCode.BadRequest) {
                                    // If we have a 400 and we were sending a chunked request going through to a proxy with a chunked upload,
                                    // this proxy is a partially compliant so shut off fancy features (pipelining and chunked uploads)
                                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() got a 400 StatusDescription:" + m_ResponseData.m_StatusDescription);
                                    if (ServicePoint.HttpBehaviour == HttpBehaviour.HTTP11
                                        && m_CurrentRequest.HttpWriteMode==HttpWriteMode.Chunked
                                        && m_ResponseData.m_ResponseHeaders.Via != null
                                        && string.Compare(m_ResponseData.m_StatusDescription, "Bad Request ( The HTTP request includes a non-supported header. Contact the Server administrator.  )", StringComparison.OrdinalIgnoreCase)==0) {
                                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() downgrading server to HTTP11PartiallyCompliant.");
                                        ServicePoint.HttpBehaviour = HttpBehaviour.HTTP11PartiallyCompliant;
                                    }
                                }
                                else {
                                    // If we have an HTTP continue, eat these headers and look
                                    //  for the 200 OK
                                    //
                                    // we got a 100 Continue. set this on the HttpWebRequest
                                    //
                                    m_CurrentRequest.Saw100Continue = true;
                                    if (!ServicePoint.Understands100Continue) {
                                        //
                                        // and start expecting it again if this behaviour was turned off
                                        //
                                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() HttpWebRequest#" + ValidationHelper.HashString(m_CurrentRequest) + " ServicePoint#" + ValidationHelper.HashString(ServicePoint) + " sent UNexpected 100 Continue");
                                        ServicePoint.Understands100Continue = true;
                                    }

                                    //
                                    // set Continue Ack on request.
                                    //
                                    GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() calling SetRequestContinue()");
                                    continueResponseData = m_ResponseData;

                                    //if we got a 100continue we ---- it and start looking for a final response
                                    goto case ReadState.Start;
                                }
                            }

                            m_ReadState = ReadState.Data;
                            goto case ReadState.Data;
                        }

                        // need more data,
                        break;

                    case ReadState.Data:

                        // (check status code for continue handling)
                        // 1. Figure out if its Chunked, content-length, or encoded
                        // 2. Takes extra data, place in stream(s)
                        // 3. Wake up blocked stream requests
                        //

                        // Got through one entire response
                        requestDone = true;

                        // parse and create a stream if needed
                        parseStatus = ParseStreamData(ref returnResult);

                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() result:" + parseStatus);
                        GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData()" + " WriteDone:" + m_WriteDone + " ReadDone:" + m_ReadDone + " WaitList:" + m_WaitList.Count + " WriteList:" + m_WriteList.Count);
                        break;
                }

            if (m_BytesScanned == m_BytesRead)
                ClearReaderState();

            GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData() m_ReadState:" + m_ReadState);
            GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::ParseResponseData()", parseStatus.ToString());
            return parseStatus;
        }
Exemple #25
0
        internal void SetRequestContinue(CoreResponseData continueResponse)
        {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue");
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue");

            _RequestContinueCount++;

            if (HttpWriteMode == HttpWriteMode.None)
            {
                GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue - not a POST type request, return");
                return;
            }

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

            if (m_ContinueGate.Complete())
            {
                // Invoke the 100 continue delegate if the user supplied one and we received a 100 Continue.
                if (continueResponse != null && ContinueDelegate != null)
                {
                    GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue() calling ContinueDelegate()");
                    ExecutionContext x = Async ? GetWritingContext().ContextCopy : null;
                    if (x == null)
                    {
                        ContinueDelegate((int)continueResponse.m_StatusCode, continueResponse.m_ResponseHeaders);
                    }
                    else
                    {
                        ExecutionContext.Run(x, new ContextCallback(CallContinueDelegateCallback), continueResponse);
                    }
                }

                EndWriteHeaders_Part2();
            }

            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue");
        }
Exemple #26
0
        //
        // When we got a live response, this method will construct the response object
        // and then consult with caching protocol on the appropriate action.
        // On return the response can be re-created.
        // Under some cases this method may initate retrying of the current request.
        //
        private void SetResponse(CoreResponseData coreResponseData) {
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse");
            GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse - coreResponseData=" + ValidationHelper.HashString(coreResponseData));

            try {
                // Consider removing this block as all these should be already signalled
                if (!Async)
                {
                    LazyAsyncResult chkConnectionAsyncResult = ConnectionAsyncResult;
                    LazyAsyncResult chkReaderAsyncResult = ConnectionReaderAsyncResult;

                    chkConnectionAsyncResult.InvokeCallback(coreResponseData); // ref "coreResponseData": could be anything except for AsyncTriState or stream
                    chkReaderAsyncResult.InvokeCallback(coreResponseData);     // ref "coreResponseData": could be anything except for null
                }

                if (coreResponseData != null)
                {
                    if (coreResponseData.m_ConnectStream.CanTimeout)
                    {
                        coreResponseData.m_ConnectStream.WriteTimeout = ReadWriteTimeout;
                        coreResponseData.m_ConnectStream.ReadTimeout = ReadWriteTimeout;
                    }
                    _HttpResponse = new HttpWebResponse(GetRemoteResourceUri(), CurrentMethod,
                        coreResponseData, _MediaType, UsesProxySemantics, AutomaticDecompression,
                        IsWebSocketRequest, ConnectionGroupName);

                    if(Logging.On)Logging.Associate(Logging.Web, this, coreResponseData.m_ConnectStream);
                    if(Logging.On)Logging.Associate(Logging.Web, this, _HttpResponse);
                    ProcessResponse();
                }
                else
                {
                    GlobalLog.Assert("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse()", "coreResponseData == null");
                    Abort(null, AbortState.Public);
                    GlobalLog.LeaveException("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse", new InternalException());
                }
            }
            catch (Exception exception) {
                Abort(exception, AbortState.Internal);
                GlobalLog.LeaveException("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetResponse", exception);
            }
            return;
        }
        private DataParseStatus ParseResponseData(ref ConnectionReturnResult returnResult, out bool requestDone, out CoreResponseData continueResponseData)
        {
            DataParseStatus status2;
            DataParseStatus needMoreData = DataParseStatus.NeedMoreData;
            requestDone = false;
            continueResponseData = null;
            switch (this.m_ReadState)
            {
                case ReadState.Start:
                    break;

                case ReadState.StatusLine:
                    goto Label_00F6;

                case ReadState.Headers:
                    goto Label_0299;

                case ReadState.Data:
                    goto Label_050A;

                default:
                    goto Label_0515;
            }
        Label_002C:
            if (this.m_CurrentRequest == null)
            {
                lock (this)
                {
                    if ((this.m_WriteList.Count == 0) || ((this.m_CurrentRequest = this.m_WriteList[0] as HttpWebRequest) == null))
                    {
                        this.m_ParseError.Section = WebParseErrorSection.Generic;
                        this.m_ParseError.Code = WebParseErrorCode.Generic;
                        needMoreData = DataParseStatus.Invalid;
                        goto Label_0515;
                    }
                }
            }
            this.m_KeepAlive &= this.m_CurrentRequest.KeepAlive || this.m_CurrentRequest.NtlmKeepAlive;
            this.m_MaximumResponseHeadersLength = this.m_CurrentRequest.MaximumResponseHeadersLength * 0x400;
            this.m_ResponseData = new CoreResponseData();
            this.m_ReadState = ReadState.StatusLine;
            this.m_TotalResponseHeadersLength = 0;
            this.InitializeParseStatusLine();
        Label_00F6:
            if (SettingsSectionInternal.Section.UseUnsafeHeaderParsing)
            {
                int[] numArray2 = new int[4];
                numArray2[1] = this.m_StatusLineValues.MajorVersion;
                numArray2[2] = this.m_StatusLineValues.MinorVersion;
                numArray2[3] = this.m_StatusLineValues.StatusCode;
                int[] statusLineInts = numArray2;
                if (this.m_StatusLineValues.StatusDescription == null)
                {
                    this.m_StatusLineValues.StatusDescription = "";
                }
                status2 = this.ParseStatusLine(this.m_ReadBuffer, this.m_BytesRead, ref this.m_BytesScanned, ref statusLineInts, ref this.m_StatusLineValues.StatusDescription, ref this.m_StatusState, ref this.m_ParseError);
                this.m_StatusLineValues.MajorVersion = statusLineInts[1];
                this.m_StatusLineValues.MinorVersion = statusLineInts[2];
                this.m_StatusLineValues.StatusCode = statusLineInts[3];
            }
            else
            {
                status2 = ParseStatusLineStrict(this.m_ReadBuffer, this.m_BytesRead, ref this.m_BytesScanned, ref this.m_StatusState, this.m_StatusLineValues, this.m_MaximumResponseHeadersLength, ref this.m_TotalResponseHeadersLength, ref this.m_ParseError);
            }
            if (status2 == DataParseStatus.Done)
            {
                if (Logging.On)
                {
                    Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_received_status_line", new object[] { this.m_StatusLineValues.MajorVersion + "." + this.m_StatusLineValues.MinorVersion, this.m_StatusLineValues.StatusCode, this.m_StatusLineValues.StatusDescription }));
                }
                this.SetStatusLineParsed();
                this.m_ReadState = ReadState.Headers;
                this.m_ResponseData.m_ResponseHeaders = new WebHeaderCollection(WebHeaderCollectionType.HttpWebResponse);
            }
            else
            {
                if (status2 != DataParseStatus.NeedMoreData)
                {
                    needMoreData = status2;
                }
                goto Label_0515;
            }
        Label_0299:
            if (this.m_BytesScanned >= this.m_BytesRead)
            {
                goto Label_0515;
            }
            if (SettingsSectionInternal.Section.UseUnsafeHeaderParsing)
            {
                status2 = this.m_ResponseData.m_ResponseHeaders.ParseHeaders(this.m_ReadBuffer, this.m_BytesRead, ref this.m_BytesScanned, ref this.m_TotalResponseHeadersLength, this.m_MaximumResponseHeadersLength, ref this.m_ParseError);
            }
            else
            {
                status2 = this.m_ResponseData.m_ResponseHeaders.ParseHeadersStrict(this.m_ReadBuffer, this.m_BytesRead, ref this.m_BytesScanned, ref this.m_TotalResponseHeadersLength, this.m_MaximumResponseHeadersLength, ref this.m_ParseError);
            }
            if ((status2 == DataParseStatus.Invalid) || (status2 == DataParseStatus.DataTooBig))
            {
                needMoreData = status2;
                goto Label_0515;
            }
            if (status2 != DataParseStatus.Done)
            {
                goto Label_0515;
            }
            if (Logging.On)
            {
                Logging.PrintInfo(Logging.Web, this, SR.GetString("net_log_received_headers", new object[] { this.m_ResponseData.m_ResponseHeaders.ToString(true) }));
            }
            if (this.m_IISVersion == -1)
            {
                int num;
                string server = this.m_ResponseData.m_ResponseHeaders.Server;
                if (((server != null) && server.ToLower(CultureInfo.InvariantCulture).Contains("microsoft-iis")) && ((server.IndexOf("/")++ > 0) && (num < server.Length)))
                {
                    this.m_IISVersion = server[num++] - '0';
                    while ((num < server.Length) && char.IsDigit(server[num]))
                    {
                        this.m_IISVersion = ((this.m_IISVersion * 10) + server[num++]) - 0x30;
                    }
                }
                if ((this.m_IISVersion == -1) && (this.m_ResponseData.m_StatusCode != HttpStatusCode.Continue))
                {
                    this.m_IISVersion = 0;
                }
            }
            if ((this.m_ResponseData.m_StatusCode == HttpStatusCode.Continue) || (this.m_ResponseData.m_StatusCode == HttpStatusCode.BadRequest))
            {
                if (this.m_ResponseData.m_StatusCode == HttpStatusCode.BadRequest)
                {
                    if (((this.ServicePoint.HttpBehaviour == HttpBehaviour.HTTP11) && (this.m_CurrentRequest.HttpWriteMode == HttpWriteMode.Chunked)) && ((this.m_ResponseData.m_ResponseHeaders.Via != null) && (string.Compare(this.m_ResponseData.m_StatusDescription, "Bad Request ( The HTTP request includes a non-supported header. Contact the Server administrator.  )", StringComparison.OrdinalIgnoreCase) == 0)))
                    {
                        this.ServicePoint.HttpBehaviour = HttpBehaviour.HTTP11PartiallyCompliant;
                    }
                }
                else
                {
                    this.m_CurrentRequest.Saw100Continue = true;
                    if (!this.ServicePoint.Understands100Continue)
                    {
                        this.ServicePoint.Understands100Continue = true;
                    }
                    continueResponseData = this.m_ResponseData;
                    goto Label_002C;
                }
            }
            this.m_ReadState = ReadState.Data;
        Label_050A:
            requestDone = true;
            needMoreData = this.ParseStreamData(ref returnResult);
        Label_0515:
            if (this.m_BytesScanned == this.m_BytesRead)
            {
                this.ClearReaderState();
            }
            return needMoreData;
        }
Exemple #28
0
        internal void SetRequestContinue(CoreResponseData continueResponse)
        {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue");
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue");

            _RequestContinueCount++;

            if (HttpWriteMode == HttpWriteMode.None)
            {
                GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue - not a POST type request, return");
                return;
            }

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

            if (m_ContinueGate.Complete())
            {
                // Generally, in Sync mode there will not be a timer (instead PollAndRead times out).  However, in mixed mode
                // there can be.  If there is a timer, whether or not to call EndWriteHeaders_Part2 depends on whether
                // we can successfully cancel it here.  Otherwise, the timeout callback should call it.
                //
                // m_ContinueGate guards the synchronization of m_ContinueTimer.
                TimerThread.Timer timer = m_ContinueTimer;
                m_ContinueTimer = null;

                // In the case there was no timer, just call EndWriteHeaders_Part2.
                if (timer == null || timer.Cancel())
                {
                    // Invoke the 100 continue delegate if the user supplied one and we received a 100 Continue.
                    if (continueResponse != null && ContinueDelegate != null)
                    {
                        GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue() calling ContinueDelegate()");
                        ExecutionContext x = null;
                        if (x == null)
                        {
                            ContinueDelegate((int) continueResponse.m_StatusCode, continueResponse.m_ResponseHeaders);
                        }
                        else
                        {
                            ExecutionContext.Run(x, new ContextCallback(CallContinueDelegateCallback), continueResponse);
                        }
                    }

                    EndWriteHeaders_Part2();
                }
               }

            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue");
        }
Exemple #29
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());
                }
            }
        }