Example #1
0
    private async Task ProcessReceives()
    {
        while (true)
        {
            // Ensure we have some reasonable amount of buffer space
            var buffer = _application.Output.GetMemory();

            var bytesReceived = await _receiver.ReceiveAsync(buffer);

            if (bytesReceived == 0)
            {
                // FIN
                break;
            }

            _application.Output.Advance(bytesReceived);

            var flushTask = _application.Output.FlushAsync();

            if (!flushTask.IsCompleted)
            {
                await flushTask;
            }

            var result = flushTask.GetAwaiter().GetResult();
            if (result.IsCompleted)
            {
                // Pipe consumer is shut down, do we stop writing
                break;
            }
        }
    }
        private async Task ProcessReceives()
        {
            while (true)
            {
                var buffer        = _application.Output.GetMemory();
                var bytesReceived = await _receiver.ReceiveAsync(buffer);

                if (bytesReceived == 0)
                {
                    break;
                }

                _application.Output.Advance(bytesReceived);
                var flushTask = _application.Output.FlushAsync();
                if (!flushTask.IsCompleted)
                {
                    await flushTask.ConfigureAwait(false);
                }

                var result = flushTask.Result;
                if (result.IsCompleted)
                {
                    break;
                }
            }
        }
Example #3
0
        private async ValueTask <bool> WaitForDisconnect(Socket socket, CancellationToken cancellationToken)
        {
            var receiveBufferBytes = m_arrayPool.Rent(1);

            try
            {
                var socketReceiver = new SocketReceiver(socket);
                var receiveCount   = await socketReceiver.ReceiveAsync(receiveBufferBytes, cancellationToken).ConfigureAwait(false);

                return(receiveCount <= 0);
            }
            catch (SocketException socketException) when(socketException.SocketErrorCode == SocketError.ConnectionReset)
            {
                return(true);
            }
            catch (SocketException)
            {
                return(false);
            }
            finally
            {
                m_arrayPool.Return(receiveBufferBytes);
            }
        }
Example #4
0
    private async Task DoReceive()
    {
        Exception?error = null;

        try
        {
            while (true)
            {
                if (_waitForData)
                {
                    // Wait for data before allocating a buffer.
                    await _receiver.WaitForDataAsync(_socket);
                }

                // Ensure we have some reasonable amount of buffer space
                var buffer = Input.GetMemory(MinAllocBufferSize);

                var bytesReceived = await _receiver.ReceiveAsync(_socket, buffer);

                if (bytesReceived == 0)
                {
                    // FIN
                    SocketsLog.ConnectionReadFin(_logger, this);
                    break;
                }

                Input.Advance(bytesReceived);

                var flushTask = Input.FlushAsync();

                var paused = !flushTask.IsCompleted;

                if (paused)
                {
                    SocketsLog.ConnectionPause(_logger, this);
                }

                var result = await flushTask;

                if (paused)
                {
                    SocketsLog.ConnectionResume(_logger, this);
                }

                if (result.IsCompleted || result.IsCanceled)
                {
                    // Pipe consumer is shut down, do we stop writing
                    break;
                }
            }
        }
        catch (SocketException ex) when(IsConnectionResetError(ex.SocketErrorCode))
        {
            // This could be ignored if _shutdownReason is already set.
            error = new ConnectionResetException(ex.Message, ex);

            // There's still a small chance that both DoReceive() and DoSend() can log the same connection reset.
            // Both logs will have the same ConnectionId. I don't think it's worthwhile to lock just to avoid this.
            if (!_socketDisposed)
            {
                SocketsLog.ConnectionReset(_logger, this);
            }
        }
        catch (Exception ex)
            when((ex is SocketException socketEx && IsConnectionAbortError(socketEx.SocketErrorCode)) ||
                 ex is ObjectDisposedException)
            {
                // This exception should always be ignored because _shutdownReason should be set.
                error = ex;

                if (!_socketDisposed)
                {
                    // This is unexpected if the socket hasn't been disposed yet.
                    SocketsLog.ConnectionError(_logger, this, error);
                }
            }
        catch (Exception ex)
        {
            // This is unexpected.
            error = ex;
            SocketsLog.ConnectionError(_logger, this, error);
        }
        finally
        {
            // If Shutdown() has already bee called, assume that was the reason ProcessReceives() exited.
            Input.Complete(_shutdownReason ?? error);

            FireConnectionClosed();

            await _waitForConnectionClosedTcs.Task;
        }
    }