示例#1
0
        static async Task<int> GetResponseAsync(StreamSocketStream nstream, WebConnectionData data, ServicePoint sPoint)
        {
            var isContinue = false;
            var emptyFirstLine = false;

            using (var lineReader = new HttpLineReader(nstream))
            {
                do
                {
                    if (data.ReadState == ReadState.Aborted)
                        return -1;

                    if (data.ReadState == ReadState.None)
                    {
                        var line = await lineReader.ReadLineAsync(CancellationToken.None).ConfigureAwait(false);

                        if (null == line)
                        {
                            data.ReadState = ReadState.Aborted;
                            return 0;
                        }

                        if (string.IsNullOrEmpty(line))
                        {
                            emptyFirstLine = true;
                            continue;
                        }

                        emptyFirstLine = false;
                        data.ReadState = ReadState.Status;

                        var parts = line.Split(' ');
                        if (parts.Length < 2)
                            return -1;

                        if (string.Compare(parts[0], "HTTP/1.1", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            data.Version = HttpVersion.Version11;
                            sPoint.SetVersion(HttpVersion.Version11);
                        }
                        else
                        {
                            data.Version = HttpVersion.Version10;
                            sPoint.SetVersion(HttpVersion.Version10);
                        }

                        data.StatusCode = (int)UInt32.Parse(parts[1]);
                        if (parts.Length >= 3)
                            data.StatusDescription = string.Join(" ", parts, 2, parts.Length - 2);
                        else
                            data.StatusDescription = "";
                    }

                    emptyFirstLine = false;
                    if (data.ReadState == ReadState.Status)
                    {
                        data.ReadState = ReadState.Headers;
                        data.Headers = new WebHeaderCollection();
                        var headers = new List<string>();

                        var finished = false;

                        while (!finished)
                        {
                            var line = await lineReader.ReadLineAsync(CancellationToken.None).ConfigureAwait(false);

                            if (null == line)
                                break;

                            if (string.IsNullOrEmpty(line))
                            {
                                // Empty line: end of headers
                                finished = true;
                                continue;
                            }

                            if (line.Length > 0 && (line[0] == ' ' || line[0] == '\t'))
                            {
                                var count = headers.Count - 1;
                                if (count < 0)
                                    break;

                                var prev = headers[count] + line;
                                headers[count] = prev;
                            }
                            else
                                headers.Add(line);
                        }

                        if (!finished)
                            return 0;

                        lineReader.SyncStream();

                        foreach (var s in headers)
                            data.Headers.SetInternal(s);

                        if (data.StatusCode == (int)HttpStatusCode.Continue)
                        {
                            sPoint.SendContinue = true;

                            if (data.Request.ExpectContinue)
                            {
                                data.Request.DoContinueDelegate(data.StatusCode, data.Headers);
                                // Prevent double calls when getting the
                                // headers in several packets.
                                data.Request.ExpectContinue = false;
                            }

                            data.ReadState = ReadState.None;
                            isContinue = true;
                        }
                        else
                        {
                            data.ReadState = ReadState.Content;
                            return 1;
                        }
                    }
                } while (emptyFirstLine || isContinue);
            }

            return -1;
        }
示例#2
0
        async Task<bool> CreateStreamAsync(HttpWebRequest request)
        {
            try
            {
                var serverStream = new StreamSocketStream(_socket, false);

                _ssl = request.Address.Scheme == Uri.UriSchemeHttps;
                _nstream = serverStream;
            }
            catch (Exception)
            {
                if (!request.Aborted)
                    _status = WebExceptionStatus.ConnectFailure;
                return false;
            }

            return true;
        }
示例#3
0
        async Task<bool> CreateTunnelAsync(HttpWebRequest request, Uri connectUri,
            StreamSocketStream stream /*, out byte[] buffer */)
        {
            bool haveAuth;

            var connectBytes = CreateConnectBytes(request, connectUri, out haveAuth);

            await stream.WriteAsync(connectBytes, 0, connectBytes.Length).ConfigureAwait(false);

            var readHeaders = await ReadHeadersAsync(stream).ConfigureAwait(false);

            var status = readHeaders.Item1;
            var result = readHeaders.Item2;

            if ((!haveAuth || _connectNtlmAuthState == NtlmAuthState.Challenge) &&
                result != null && status == 407)
            {
                // Needs proxy auth
                var connectionHeader = result["Connection"];
                if (_socket != null && !string.IsNullOrEmpty(connectionHeader) &&
                    connectionHeader.ToLower() == "close")
                {
                    // The server is requesting that this connection be closed
                    _socket.Dispose();
                    _socket = null;
                }

                Data.StatusCode = status;
                Data.Challenge = result.GetValues_internal("Proxy-Authenticate", false);
                return false;
            }

            if (status != 200)
            {
                var msg = String.Format("The remote server returned a {0} status code.", status);
                HandleError(WebExceptionStatus.SecureChannelFailure, null, msg);
                return false;
            }

            return result != null;
        }
示例#4
0
        async Task<Tuple<int, WebHeaderCollection>> ReadHeadersAsync(StreamSocketStream stream)
        {
            var status = 200;

            //var ms = new MemoryStream();
            var gotStatus = false;
            using (var lineReader = new HttpLineReader(stream))
            {
                while (true)
                {
                    //var n = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
                    //if (n == 0)
                    //{
                    //    HandleError(WebExceptionStatus.ServerProtocolViolation, null, "ReadHeaders");
                    //    return null;
                    //}

                    //ms.Write(buffer, 0, n);
                    //var start = 0;
                    var headers = new WebHeaderCollection();
                    for (; ; )
                    {
                        var str = await lineReader.ReadLineAsync(CancellationToken.None).ConfigureAwait(false);

                        if (str == null)
                        {
                            var contentLen = 0L;
                            try
                            {
                                if (!long.TryParse(headers["Content-Length"], out contentLen))
                                    contentLen = 0;
                            }
                            catch
                            {
                                contentLen = 0;
                            }

                            lineReader.SyncStream();

                            //if (false) //ms.Length - start - contentLen > 0)
                            //{
                            //    // we've read more data than the response header and contents,
                            //    // give back extra data to the caller
                            //    //retBuffer = new byte[ms.Length - start - contentLen];
                            //    //Buffer.BlockCopy(ms.GetBuffer(), (int) (start + contentLen), retBuffer, 0, retBuffer.Length);
                            //}
                            if (contentLen > 0)
                            {
                                // haven't read in some or all of the contents for the response, do so now
                                await FlushContentsAsync(stream, contentLen).ConfigureAwait(false);
                            }

                            return Tuple.Create(status, headers);
                        }

                        if (gotStatus)
                        {
                            headers.Add(str);
                            continue;
                        }

                        var spaceidx = str.IndexOf(' ');
                        if (spaceidx == -1)
                        {
                            HandleError(WebExceptionStatus.ServerProtocolViolation, null, "ReadHeaders2");
                            return null;
                        }

                        status = (int)UInt32.Parse(str.Substring(spaceidx + 1, 3));
                        gotStatus = true;
                    }
                }
            }
        }
示例#5
0
        //internal IAsyncResult BeginWrite(HttpWebRequest request, byte[] buffer, int offset, int size, AsyncCallback cb, object state)
        //{
        //    Stream s = null;
        //    lock (this)
        //    {
        //        if (Data.Request != request)
        //            throw new ObjectDisposedException(typeof (StreamSocketStream).FullName);
        //        if (_nstream == null)
        //            return null;
        //        s = _nstream;
        //    }

        //    IAsyncResult result = null;
        //    try
        //    {
        //        result = s.BeginWrite(buffer, offset, size, cb, state);
        //        var x = s.WriteAsync(buffer, offset, size).ConfigureAwait(false)
        //    }
        //    catch (Exception)
        //    {
        //        _status = WebExceptionStatus.SendFailure;
        //        throw;
        //    }

        //    return result;
        //}

        //internal bool EndWrite(HttpWebRequest request, bool throwOnError, IAsyncResult result)
        //{
        //    if (request.FinishedReading)
        //        return true;

        //    Stream s = null;
        //    lock (this)
        //    {
        //        if (Data.Request != request)
        //            throw new ObjectDisposedException(typeof(StreamSocketStream).FullName);
        //        if (_nstream == null)
        //            throw new ObjectDisposedException(typeof(StreamSocketStream).FullName);
        //        s = _nstream;
        //    }

        //    try
        //    {
        //        s.EndWrite(result);
        //        return true;
        //    }
        //    catch (Exception exc)
        //    {
        //        _status = WebExceptionStatus.SendFailure;
        //        if (throwOnError && exc.InnerException != null)
        //            throw exc.InnerException;
        //        return false;
        //    }
        //}

        //internal int Read(HttpWebRequest request, byte[] buffer, int offset, int size)
        //{
        //    Stream s = null;
        //    lock (this)
        //    {
        //        if (Data.Request != request)
        //            throw new ObjectDisposedException(typeof(StreamSocketStream).FullName);
        //        if (_nstream == null)
        //            return 0;
        //        s = _nstream;
        //    }

        //    var result = 0;
        //    try
        //    {
        //        var done = false;
        //        if (!_chunkedRead)
        //        {
        //            result = s.Read(buffer, offset, size);
        //            done = (result == 0);
        //        }

        //        if (_chunkedRead)
        //        {
        //            try
        //            {
        //                _chunkStream.WriteAndReadBack(buffer, offset, size, ref result);
        //                if (!done && result == 0 && _chunkStream.WantMore)
        //                    result = EnsureReadAsync(buffer, offset, size);
        //            }
        //            catch (Exception e)
        //            {
        //                HandleError(WebExceptionStatus.ReceiveFailure, e, "chunked Read1");
        //                throw;
        //            }

        //            if ((done || result == 0) && _chunkStream.WantMore)
        //            {
        //                HandleError(WebExceptionStatus.ReceiveFailure, null, "chunked Read2");
        //                throw new WebException("Read error", null, WebExceptionStatus.ReceiveFailure, null);
        //            }
        //        }
        //    }
        //    catch (Exception e)
        //    {
        //        HandleError(WebExceptionStatus.ReceiveFailure, e, "Read");
        //    }

        //    return result;
        //}

        internal bool Write(HttpWebRequest request, byte[] buffer, int offset, int size, ref string err_msg)
        {
            err_msg = null;
            Stream s = null;
            lock (this)
            {
                if (Data.Request != request)
                    throw new ObjectDisposedException(typeof(StreamSocketStream).FullName);
                s = _nstream;
                if (s == null)
                    return false;
            }

            try
            {
                s.Write(buffer, offset, size);
                // here SSL handshake should have been done
                if (_ssl && !_certsAvailable)
                    GetCertificates(s);
            }
            catch (Exception e)
            {
                err_msg = e.Message;
                var wes = WebExceptionStatus.SendFailure;
                var msg = "Write: " + err_msg;
                if (e is WebException)
                {
                    HandleError(wes, e, msg);
                    return false;
                }

                // if SSL is in use then check for TrustFailure
                if (_ssl)
                {
#if SECURITY_DEP && MONOTOUCH
                    HttpsClientStream https = (s as HttpsClientStream);
                    if (https.TrustFailure) {
#else
                    if ((bool)_piTrustFailure.GetValue(s, null))
                    {
#endif
                        wes = WebExceptionStatus.TrustFailure;
                        msg = "Trust failure";
                    }
                }

                HandleError(wes, e, msg);
                return false;
            }
            return true;
        }

        internal void Close(bool sendNext)
        {
            lock (this)
            {
                if (Data != null && Data.Request != null && Data.Request.ReuseConnection)
                {
                    Data.Request.ReuseConnection = false;
                    return;
                }

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

                if (_socket != null)
                {
                    try
                    {
                        _socket.Dispose();
                    }
                    catch
                    { }
                    _socket = null;
                }

                if (_ntlmAuthenticated)
                    ResetNtlm();
                if (Data != null)
                {
                    lock (Data)
                    {
                        Data.ReadState = ReadState.Aborted;
                    }
                }
                _state.SetIdle();
                Data = new WebConnectionData();
                if (sendNext)
                    SendNext();

                _connectRequest = null;
                _connectNtlmAuthState = NtlmAuthState.None;
            }
        }

        void Abort(object sender, EventArgs args)
        {
            lock (this)
            {
                lock (_queue)
                {
                    var req = (HttpWebRequest)sender;
                    if (Data.Request == req || Data.Request == null)
                    {
                        if (!req.FinishedReading)
                        {
                            _status = WebExceptionStatus.RequestCanceled;
                            Close(false);
                            if (_queue.Count > 0)
                            {
                                Data.Request = _queue.Dequeue();
                                SendRequest(Data.Request);
                            }
                        }
                        return;
                    }

                    req.FinishedReading = true;
                    req.SetResponseError(WebExceptionStatus.RequestCanceled, null, "User aborted");
                    if (_queue.Count > 0 && _queue.Peek() == sender)
                        _queue.Dequeue();
                    else if (_queue.Count > 0)
                    {
                        var old = _queue.ToArray();
                        _queue.Clear();
                        for (var i = old.Length - 1; i >= 0; i--)
                        {
                            if (old[i] != sender)
                                _queue.Enqueue(old[i]);
                        }
                    }
                }
            }
        }