Exemplo n.º 1
0
        private async ValueTask <(PacketHeaders, int, bool)> TransmissionControl(Memory <byte> output, CancellationToken token)
        {
            MessageType responseType;
            int         count;
            bool        isContinueReceiving;
            var         resultTask = Cast <Task <Result <bool> > >(task);
            var         stateTask  = transmissionStateTrigger.WaitAsync(this, IsValidStateForResponsePredicate, token);

            // wait for result or state transition
            if (ReferenceEquals(resultTask, await Task.WhenAny(resultTask, stateTask).ConfigureAwait(false)))
            {
                // result obtained, finalize transmission
                task                = null;
                state               = State.ReceivingEntriesFinished;
                remainingCount      = 0;
                count               = IExchange.WriteResult(resultTask.Result, output.Span);
                isContinueReceiving = false;
                responseType        = MessageType.None;
            }
            else
            {
                // should be in sync with IsValidStateForResponse
                switch (state)
                {
                case State.ReceivingEntriesFinished:
                    count = IExchange.WriteResult(await resultTask.ConfigureAwait(false), output.Span);
                    isContinueReceiving = false;
                    responseType        = MessageType.None;
                    break;

                case State.ReadyToReceiveEntry:
                    count = EntriesExchange.CreateNextEntryResponse(output.Span, lookupIndex);
                    isContinueReceiving = true;
                    responseType        = MessageType.NextEntry;
                    break;

                case State.ReceivingEntry:
                    count = 0;
                    isContinueReceiving = true;
                    responseType        = MessageType.Continue;
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }

            return(new PacketHeaders(responseType, FlowControl.Ack), count, isContinueReceiving);
        }