private async Task ProcessReceives() { while (true) { // Ensure we have some reasonable amount of buffer space var buffer = ReceiverPipe.GetMemory(MemoryPool.MaxBufferSize); //var buffer = ReceiverPipe.GetMemory(_udpConfiguration.ReceiveBufferSize); var bytesReceived = await _receiver.ReceiveAsync(buffer); if (bytesReceived == 0) { // FIN _logger.LogTrace("No bytes received", null); break; } ReceiverPipe.Advance(bytesReceived); var flushTask = ReceiverPipe.FlushAsync(); var result = await flushTask; if (result.IsCompleted || result.IsCanceled) { // Pipe consumer is shut down, do we stop writing break; } } }
private async Task ReadPipeAsync() { Exception shutdownReason = null; Exception unexpectedError = null; try { await ProcessMessagesAsync(); } catch (Exception ex) when((ex is SocketException socketEx && IsConnectionAbortError(socketEx.SocketErrorCode)) || ex is ObjectDisposedException) { // This should always be ignored since Shutdown() must have already been called by Abort(). shutdownReason = ex; } catch (Exception ex) { shutdownReason = ex; unexpectedError = ex; _logger.LogTrace(unexpectedError); } finally { Shutdown(shutdownReason); // Complete the output after disposing the socket ReaderPipe.Complete(unexpectedError); // Cancel any pending flushes so that the input loop is un-paused ReceiverPipe.CancelPendingFlush(); } }
private async Task FillPipeAsync() { Exception error = null; try { await ProcessReceives(); } 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. _logger.LogError(error); } } catch (Exception ex) { // This is unexpected. error = ex; _logger.LogError(error); } finally { // If Shutdown() has already bee called, assume that was the reason ProcessReceives() exited. ReceiverPipe.Complete(_shutdownReason ?? error); } }