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);
            }
예제 #2
0
            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));
            }