Esempio n. 1
0
        /// <summary>
        /// Send over unix domain sockets
        /// </summary>
        /// <param name="udsPath"></param>
        /// <param name="request"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private async Task <HttpResponseMessage> SendOverUnixDomainSocketAsync(string udsPath,
                                                                               HttpRequestMessage request, CancellationToken ct)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            if (string.IsNullOrEmpty(udsPath))
            {
                throw new ArgumentNullException(nameof(udsPath));
            }
            using (var socket = new Socket(AddressFamily.Unix, SocketType.Stream,
                                           ProtocolType.Unspecified)) {
                await socket.ConnectAsync(new UdsEndPoint(udsPath)).ConfigureAwait(false);

                using (var stream = new HttpLineReader(new NetworkStream(socket, true))) {
                    var requestBytes = GetRequestBuffer(request);
                    await stream.WriteAsync(requestBytes, 0, requestBytes.Length, ct)
                    .ConfigureAwait(false);

                    if (request.Content != null)
                    {
                        await request.Content.CopyToAsync(stream).ConfigureAwait(false);
                    }
                    return(await ReadResponseAsync(stream, ct).ConfigureAwait(false));
                }
            }
        }
        private void NextChunk()
        {
            var chunkLengthHex = HttpLineReader.ReadLine(RawStream);

            if (String.IsNullOrEmpty(chunkLengthHex))
            {
                CurrentChunkLength    = 0;
                CurrentChunkRemaining = 0;
            }
            else
            {
                CurrentChunkLength    = Convert.ToInt64(chunkLengthHex, 16);
                CurrentChunkRemaining = CurrentChunkLength;
            }
        }
        static string[] ReadAllLines(string asciiInput)
        {
            var inputBytes = Encoding.ASCII.GetBytes(asciiInput);

            using (var memStream = new MemoryStream(inputBytes))
            {
                memStream.Seek(0, SeekOrigin.Begin);
                var    lines = new List <string>();
                string line  = null;
                while ((line = HttpLineReader.ReadLine(memStream)) != null)
                {
                    lines.Add(line);
                }
                return(lines.ToArray());
            }
        }
        public override int Read(byte[] buffer, int offset, int length)
        {
            if (EndOfDataReached)
            {
                return(0);
            }

            int totalRead = 0;

            while (totalRead < length)
            {
                if (CurrentChunkRemaining == 0)
                {
                    if (CurrentChunkLength > 0)
                    {
                        // Read the empty line that follows the previous chunk
                        HttpLineReader.ReadLine(RawStream);
                    }

                    NextChunk();

                    // Chunk length zero means end of data.
                    if (CurrentChunkLength == 0)
                    {
                        Close();
                        EndOfDataReached = true;
                        break;
                    }
                }

                int maxLength    = (int)Math.Min(length - totalRead, CurrentChunkRemaining);
                int actualLength = RawStream.Read(buffer, offset, maxLength);
                totalRead += actualLength;
                offset    += actualLength;

                CurrentChunkRemaining -= actualLength;

                if (actualLength == 0)
                {
                    break;
                }
            }

            return(totalRead);
        }
Esempio n. 5
0
        public static async ValueTask ProcessWorkItemAsync(Socket tcpClient)
        {
            Interlocked.Increment(ref _usersCount);
            Interlocked.Increment(ref _busyThreads);
            var finalized = false;

            try
            {
                var stream = Ssl
                    ? await AuthenticateSsl(tcpClient)
                    : new NetworkStream(tcpClient);

                var requestData = await HttpLineReader.ReadLineSizedBuffered(stream, 2048);

                if (requestData == null || requestData.Length < 10)
                {
                    return;
                }

                var request = HttpRequestParser.ParseRequest(requestData);
                if (request == null)
                {
                    return;
                }

                using var holder = new HttpClientHolder(stream, tcpClient, (HttpInitialRequest)request);
                finalized        = true;
                await HttpClientProcessor.ProcessClient(holder, (HttpInitialRequest)request);
            }
            catch (Exception e)
            {
                ILogManager.Log("Http work pool error.", "Client.Work.Pool", LogType.Error, true, true, e);
            }
            finally
            {
                if (!finalized)
                {
                    HttpClientHolder.Close(tcpClient);
                }
                Interlocked.Decrement(ref _busyThreads);
            }
        }
Esempio n. 6
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;
        }
Esempio n. 7
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;
                    }
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Deserialize response
        /// </summary>
        /// <param name="bufferedStream"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private async Task <HttpResponseMessage> ReadResponseAsync(
            HttpLineReader bufferedStream, CancellationToken ct)
        {
            var response = new HttpResponseMessage();

            var statusLine = await bufferedStream.ReadLineAsync(ct)
                             .ConfigureAwait(false);

            if (string.IsNullOrWhiteSpace(statusLine))
            {
                throw new HttpRequestException("Response is empty.");
            }
            var statusParts = statusLine.Split(new[] { kSpace }, 3);

            if (statusParts.Length < 3)
            {
                throw new HttpRequestException("Status line is not valid.");
            }
            var httpVersion = statusParts[0].Split(new[] { kProtoVersionSep }, 2);

            if (httpVersion.Length < 2 ||
                !Version.TryParse(httpVersion[1], out var version))
            {
                throw new HttpRequestException(
                          $"Version is not valid {statusParts[0]}.");
            }
            response.Version = version;
            if (!Enum.TryParse(statusParts[1], out HttpStatusCode statusCode))
            {
                throw new HttpRequestException(
                          $"StatusCode is not valid {statusParts[1]}.");
            }
            response.StatusCode   = statusCode;
            response.ReasonPhrase = statusParts[2];

            // parse headers
            var headers = new List <string>();
            var line    = await bufferedStream.ReadLineAsync(ct)
                          .ConfigureAwait(false);

            while (!string.IsNullOrWhiteSpace(line))
            {
                headers.Add(line);
                line = await bufferedStream.ReadLineAsync(ct)
                       .ConfigureAwait(false);
            }

            response.Content = new StreamContent(bufferedStream);
            foreach (var header in headers)
            {
                if (string.IsNullOrWhiteSpace(header))
                {
                    // headers end
                    break;
                }
                var headerSeparatorPosition = header.IndexOf(kHeaderSeparator);
                if (headerSeparatorPosition <= 0)
                {
                    throw new HttpRequestException($"Header is invalid {header}.");
                }
                var name     = header.Substring(0, headerSeparatorPosition).Trim();
                var value    = header.Substring(headerSeparatorPosition + 1).Trim();
                var wasAdded = response.Headers.TryAddWithoutValidation(name, value);
                if (!wasAdded)
                {
                    if (name.EqualsIgnoreCase(kContentLength))
                    {
                        if (!long.TryParse(value, out var length))
                        {
                            throw new HttpRequestException(
                                      $"Header value is invalid for {name}.");
                        }
                        await response.Content.LoadIntoBufferAsync(length)
                        .ConfigureAwait(false);
                    }
                    response.Content.Headers.TryAddWithoutValidation(name, value);
                }
            }
            return(response);
        }