internal async Task <ExchangeResult> Exchange(IExchange exchange, Memory <byte> buffer, TimeSpan receiveTimeout, CancellationToken token) { var result = ExchangeResult.Success; CancellationTokenSource?timeoutTracker = null, combinedSource = null; try { var(headers, request) = await ReadPacket(buffer, token).ConfigureAwait(false); timeoutTracker = new CancellationTokenSource(receiveTimeout); combinedSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutTracker.Token, token); token = combinedSource.Token; while (await exchange.ProcessInboundMessageAsync(headers, request, Socket.RemoteEndPoint, token).ConfigureAwait(false)) { bool waitForInput; int count; (headers, count, waitForInput) = await exchange.CreateOutboundMessageAsync(AdjustToPayload(buffer), token).ConfigureAwait(false); // transmit packet to the remote endpoint await WritePacket(headers, buffer, count, token).ConfigureAwait(false); if (!waitForInput) { break; } // read response (headers, request) = await ReadPacket(buffer, token).ConfigureAwait(false); } } catch (OperationCanceledException e) { exchange.OnCanceled(e.CancellationToken); result = !(timeoutTracker is null) && timeoutTracker.IsCancellationRequested ? ExchangeResult.TimeOut : ExchangeResult.Stopped; } catch (Exception e) when(e is EndOfStreamException || e is SocketException || e.InnerException is SocketException) { exchange.OnException(e); result = ExchangeResult.SocketError; } catch (Exception e) { exchange.OnException(e); } finally { combinedSource?.Dispose(); timeoutTracker?.Dispose(); } return(result); }
internal async Task Exchange(IExchange exchange, Memory <byte> buffer, CancellationToken token) { PacketHeaders headers; int count; bool waitForInput; ReadOnlyMemory <byte> response; do { (headers, count, waitForInput) = await exchange.CreateOutboundMessageAsync(AdjustToPayload(buffer), token).ConfigureAwait(false); // transmit packet to the remote endpoint await WritePacket(headers, buffer, count, token).ConfigureAwait(false); if (!waitForInput) { break; } // read response (headers, response) = await ReadPacket(buffer, token).ConfigureAwait(false); }while (await exchange.ProcessInboundMessageAsync(headers, response, RemoteEndPoint, token).ConfigureAwait(false)); }