private void ConnectionCallback(UvStreamHandle listenSocket, int status, UvException error, object state) { var listener = (UvListener)state; if (error != null) { listener.Log.LogError(0, error, "Listener.ConnectionCallback"); } else if (!listener._closed) { UvStreamHandle acceptSocket = null; try { acceptSocket = CreateAcceptSocket(); listenSocket.Accept(acceptSocket); DispatchConnection(acceptSocket); } catch (UvException ex) when(UvConstants.IsConnectionReset(ex.StatusCode)) { Log.ConnectionReset("(null)"); acceptSocket?.Dispose(); } catch (UvException ex) { Log.LogError(0, ex, "Listener.OnConnection"); acceptSocket?.Dispose(); } } }
protected async Task HandleConnectionAsync(UvStreamHandle socket) { try { IPEndPoint remoteEndPoint = null; IPEndPoint localEndPoint = null; if (socket is UvTcpHandle tcpHandle) { try { remoteEndPoint = tcpHandle.GetPeerIPEndPoint(); localEndPoint = tcpHandle.GetSockIPEndPoint(); } catch (UvException ex) when(UvConstants.IsConnectionReset(ex.StatusCode)) { Log.ConnectionReset("(null)"); socket.Dispose(); return; } } var connection = new UvConnection(socket, _thread, remoteEndPoint, localEndPoint, log: Log); await connection.Start(); await Dispatcher.OnConnection(connection); connection.Dispose(); } catch (Exception ex) { Log.LogCritical(ex, $"Unexpected exception in {nameof(UvListener)}.{nameof(HandleConnectionAsync)}."); } }
public async Task Start() { try { StartReading(); Exception inputError = null; Exception outputError = null; try { // This *must* happen after socket.ReadStart // The socket output consumer is the only thing that can close the connection. If the // output pipe is already closed by the time we start then it's fine since, it'll // close gracefully afterwards. await WriteOutputAsync(); } catch (UvException ex) { // The connection reset/error has already been logged by LibuvOutputConsumer if (ex.StatusCode == UvConstants.ECANCELED) { // Connection was aborted. } else if (UvConstants.IsConnectionReset(ex.StatusCode)) { // Don't cause writes to throw for connection resets. outputError = new ConnectionResetException(ex.Message, ex); } else { inputError = ex; outputError = ex; } } finally { // Now, complete the input so that no more reads can happen _receiveFromUV.Writer.Complete(inputError ?? _abortReason ?? new ConnectionAbortedException()); _sendToUV.Reader.Complete(outputError); // Make sure it isn't possible for a paused read to resume reading after calling uv_close // on the stream handle _receiveFromUV.Writer.CancelPendingFlush(); // Send a FIN Log.ConnectionWriteFin(ConnectionId); // We're done with the socket now _socket.Dispose(); ThreadPool.QueueUserWorkItem(state => ((UvConnection)state).CancelConnectionClosedToken(), this); } } catch (Exception e) { Log.LogCritical(0, e, $"{nameof(UvConnection)}.{nameof(Start)}() {ConnectionId}"); } }
public void ReadCallback(UvStreamHandle dispatchPipe, int status) { try { dispatchPipe.Libuv.ThrowIfErrored(status); _bytesRead += status; if (_bytesRead == _bufferLength) { var correctMessage = true; for (var i = 0; i < _bufferLength; i++) { if (_buf[i] != _listener._pipeMessage[i]) { correctMessage = false; } } if (correctMessage) { _listener._dispatchPipes.Add((UvPipeHandle)dispatchPipe); dispatchPipe.ReadStop(); _bufHandle.Free(); } else { throw new IOException("Bad data sent over Kestrel pipe."); } } } catch (Exception ex) { dispatchPipe.Dispose(); _bufHandle.Free(); _listener.Log.LogError(0, ex, "ListenerPrimary.ReadCallback"); } }