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(); }
private async Task ProduceEndAwaited() { ProduceStart(appCompleted: true); // Force flush await SocketOutput.WriteAsync(_emptyData); await WriteSuffix(); }
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); } }
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); }
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); } }
public void Write(ArraySegment <byte> data) { ProduceStartAndFireOnStarting().GetAwaiter().GetResult(); if (_autoChunk) { if (data.Count == 0) { return; } WriteChunked(data); } else { SocketOutput.Write(data); } }
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)); } }
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); }
private Task WriteChunkedResponseSuffix() { return(SocketOutput.WriteAsync(_endChunkedResponseBytes)); }
private Task WriteChunkedAsync(ArraySegment <byte> data, CancellationToken cancellationToken) { return(SocketOutput.WriteAsync(data, chunk: true, cancellationToken: cancellationToken)); }
private void WriteChunked(ArraySegment <byte> data) { SocketOutput.Write(data, chunk: true); }
public async Task FlushAsync(CancellationToken cancellationToken) { await ProduceStartAndFireOnStarting(); await SocketOutput.WriteAsync(_emptyData, cancellationToken : cancellationToken); }
public void Flush() { ProduceStartAndFireOnStarting().GetAwaiter().GetResult(); SocketOutput.Write(_emptyData); }
public WriteContext(SocketOutput self) { Self = self; }