コード例 #1
0
        public Connection(ListenerContext context, UvStreamHandle socket) : base(context)
        {
            _socket           = socket;
            socket.Connection = this;
            ConnectionControl = this;

            ConnectionId = GenerateConnectionId(Interlocked.Increment(ref _lastConnectionId));

            if (ServerOptions.Limits.MaxRequestBufferSize.HasValue)
            {
                _bufferSizeControl = new BufferSizeControl(ServerOptions.Limits.MaxRequestBufferSize.Value, this, Thread);
            }

            SocketInput  = new SocketInput(Thread.Memory, ThreadPool, _bufferSizeControl);
            SocketOutput = new SocketOutput(Thread, _socket, this, ConnectionId, Log, ThreadPool);

            var tcpHandle = _socket as UvTcpHandle;

            if (tcpHandle != null)
            {
                RemoteEndPoint = tcpHandle.GetPeerIPEndPoint();
                LocalEndPoint  = tcpHandle.GetSockIPEndPoint();
            }

            _frame         = FrameFactory(this);
            _lastTimestamp = Thread.Loop.Now();
        }
コード例 #2
0
        private async Task ProduceEndAwaited()
        {
            ProduceStart(appCompleted: true);

            // Force flush
            await SocketOutput.WriteAsync(_emptyData);

            await WriteSuffix();
        }
コード例 #3
0
        public void ProduceContinue()
        {
            if (HasResponseStarted)
            {
                return;
            }

            StringValues expect;

            if (_httpVersion == HttpVersionType.Http11 &&
                RequestHeaders.TryGetValue("Expect", out expect) &&
                (expect.FirstOrDefault() ?? "").Equals("100-continue", StringComparison.OrdinalIgnoreCase))
            {
                SocketOutput.Write(_continueBytes);
            }
        }
コード例 #4
0
        public Connection(ListenerContext context, UvStreamHandle socket) : base(context)
        {
            _socket           = socket;
            socket.Connection = this;
            ConnectionControl = this;

            ConnectionId = GenerateConnectionId(Interlocked.Increment(ref _lastConnectionId));

            if (ServerOptions.MaxRequestBufferSize.HasValue)
            {
                _bufferSizeControl = new BufferSizeControl(ServerOptions.MaxRequestBufferSize.Value, this, Thread);
            }

            _rawSocketInput  = new SocketInput(Memory, ThreadPool, _bufferSizeControl);
            _rawSocketOutput = new SocketOutput(Thread, _socket, Memory, this, ConnectionId, Log, ThreadPool, WriteReqPool);
        }
コード例 #5
0
        public async Task WriteAsyncAwaited(ArraySegment <byte> data, CancellationToken cancellationToken)
        {
            await ProduceStartAndFireOnStarting();

            if (_autoChunk)
            {
                if (data.Count == 0)
                {
                    return;
                }
                await WriteChunkedAsync(data, cancellationToken);
            }
            else
            {
                await SocketOutput.WriteAsync(data, cancellationToken : cancellationToken);
            }
        }
コード例 #6
0
        public void Write(ArraySegment <byte> data)
        {
            ProduceStartAndFireOnStarting().GetAwaiter().GetResult();

            if (_autoChunk)
            {
                if (data.Count == 0)
                {
                    return;
                }
                WriteChunked(data);
            }
            else
            {
                SocketOutput.Write(data);
            }
        }
コード例 #7
0
        public Task WriteAsync(ArraySegment <byte> data, CancellationToken cancellationToken)
        {
            if (!HasResponseStarted)
            {
                return(WriteAsyncAwaited(data, cancellationToken));
            }

            if (_autoChunk)
            {
                if (data.Count == 0)
                {
                    return(TaskUtilities.CompletedTask);
                }
                return(WriteChunkedAsync(data, cancellationToken));
            }
            else
            {
                return(SocketOutput.WriteAsync(data, cancellationToken: cancellationToken));
            }
        }
コード例 #8
0
        private void CreateResponseHeader(
            byte[] statusBytes,
            bool appCompleted)
        {
            var responseHeaders = FrameResponseHeaders;

            responseHeaders.SetReadOnly();

            var hasConnection = responseHeaders.HasConnection;

            var end = SocketOutput.ProducingStart();

            if (_keepAlive && hasConnection)
            {
                foreach (var connectionValue in responseHeaders.HeaderConnection)
                {
                    if (connectionValue.IndexOf("close", StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        _keepAlive = false;
                        break;
                    }
                }
            }

            if (_keepAlive && !responseHeaders.HasTransferEncoding && !responseHeaders.HasContentLength)
            {
                if (appCompleted)
                {
                    // Don't set the Content-Length or Transfer-Encoding headers
                    // automatically for HEAD requests or 101, 204, 205, 304 responses.
                    if (Method != "HEAD" && StatusCanHaveBody(StatusCode))
                    {
                        // Since the app has completed and we are only now generating
                        // the headers we can safely set the Content-Length to 0.
                        responseHeaders.SetRawContentLength("0", _bytesContentLengthZero);
                    }
                }
                else
                {
                    // Note for future reference: never change this to set _autoChunk to true on HTTP/1.0
                    // connections, even if we were to infer the client supports it because an HTTP/1.0 request
                    // was received that used chunked encoding. Sending a chunked response to an HTTP/1.0
                    // client would break compliance with RFC 7230 (section 3.3.1):
                    //
                    // A server MUST NOT send a response containing Transfer-Encoding unless the corresponding
                    // request indicates HTTP/1.1 (or later).
                    if (_httpVersion == HttpVersionType.Http11)
                    {
                        _autoChunk = true;
                        responseHeaders.SetRawTransferEncoding("chunked", _bytesTransferEncodingChunked);
                    }
                    else
                    {
                        _keepAlive = false;
                    }
                }
            }

            if (!_keepAlive && !hasConnection && _httpVersion != HttpVersionType.Http10)
            {
                responseHeaders.SetRawConnection("close", _bytesConnectionClose);
            }
            else if (_keepAlive && !hasConnection && _httpVersion == HttpVersionType.Http10)
            {
                responseHeaders.SetRawConnection("keep-alive", _bytesConnectionKeepAlive);
            }

            if (ServerOptions.AddServerHeader && !responseHeaders.HasServer)
            {
                responseHeaders.SetRawServer(Constants.ServerName, _bytesServer);
            }

            if (!responseHeaders.HasDate)
            {
                var dateHeaderValues = DateHeaderValueManager.GetDateHeaderValues();
                responseHeaders.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes);
            }

            end.CopyFrom(_bytesHttpVersion11);
            end.CopyFrom(statusBytes);
            responseHeaders.CopyTo(ref end);
            end.CopyFrom(_bytesEndHeaders, 0, _bytesEndHeaders.Length);

            SocketOutput.ProducingComplete(end);
        }
コード例 #9
0
 private Task WriteChunkedResponseSuffix()
 {
     return(SocketOutput.WriteAsync(_endChunkedResponseBytes));
 }
コード例 #10
0
 private Task WriteChunkedAsync(ArraySegment <byte> data, CancellationToken cancellationToken)
 {
     return(SocketOutput.WriteAsync(data, chunk: true, cancellationToken: cancellationToken));
 }
コード例 #11
0
 private void WriteChunked(ArraySegment <byte> data)
 {
     SocketOutput.Write(data, chunk: true);
 }
コード例 #12
0
        public async Task FlushAsync(CancellationToken cancellationToken)
        {
            await ProduceStartAndFireOnStarting();

            await SocketOutput.WriteAsync(_emptyData, cancellationToken : cancellationToken);
        }
コード例 #13
0
 public void Flush()
 {
     ProduceStartAndFireOnStarting().GetAwaiter().GetResult();
     SocketOutput.Write(_emptyData);
 }
コード例 #14
0
 public WriteContext(SocketOutput self)
 {
     Self = self;
 }