Exemple #1
0
        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)}.");
            }
        }
Exemple #2
0
        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();
                }
            }
        }
Exemple #3
0
        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}");
            }
        }
Exemple #4
0
 private Exception LogAndWrapReadError(UvException uvError)
 {
     if (uvError.StatusCode == UvConstants.ECANCELED)
     {
         // The operation was canceled by the server not the client. No need for additional logs.
         return(new ConnectionAbortedException(uvError.Message, uvError));
     }
     else if (UvConstants.IsConnectionReset(uvError.StatusCode))
     {
         // Log connection resets at a lower (Debug) level.
         Log.ConnectionReset(ConnectionId);
         return(new ConnectionResetException(uvError.Message, uvError));
     }
     else
     {
         Log.ConnectionError(ConnectionId, uvError);
         return(new IOException(uvError.Message, uvError));
     }
 }
Exemple #5
0
        private void ReadStartCallback(UvStreamHandle handle, int status)
        {
            if (status < 0)
            {
                if (status != UvConstants.EOF)
                {
                    _thread.Loop.Libuv.Check(status, out var ex);
                    Log.LogError(0, ex, "DispatchPipe.ReadStart");
                }

                DispatchPipe.Dispose();
                return;
            }

            if (_closed || DispatchPipe.PendingCount() == 0)
            {
                return;
            }

            var acceptSocket = CreateAcceptSocket();

            try
            {
                DispatchPipe.Accept(acceptSocket);

                // REVIEW: This task should be tracked by the server for graceful shutdown
                // Today it's handled specifically for http but not for aribitrary middleware
                _ = HandleConnectionAsync(acceptSocket);
            }
            catch (UvException ex) when(UvConstants.IsConnectionReset(ex.StatusCode))
            {
                Log.ConnectionReset("(null)");
                acceptSocket.Dispose();
            }
            catch (UvException ex)
            {
                Log.LogError(0, ex, "DispatchPipe.Accept");
                acceptSocket.Dispose();
            }
        }
Exemple #6
0
 private void LogWriteInfo(int status, Exception error)
 {
     if (error == null)
     {
         Log.ConnectionWriteCallback(ConnectionId, status);
     }
     else
     {
         // Log connection resets at a lower (Debug) level.
         if (status == UvConstants.ECANCELED)
         {
             // Connection was aborted.
         }
         else if (UvConstants.IsConnectionReset(status))
         {
             Log.ConnectionReset(ConnectionId);
         }
         else
         {
             Log.ConnectionError(ConnectionId, error);
         }
     }
 }