/// <summary>
        /// Calls this when got ping messages (pong payload must be 125 bytes or less, pong should contain the same payload as the ping)
        /// </summary>
        /// <param name="payload"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async ValueTask SendPongAsync(ArraySegment <byte> payload, CancellationToken cancellationToken)
        {
            // exceeded max length
            if (payload.Count > 125)
            {
                var ex = new BufferOverflowException($"Max PONG message size is 125 bytes, exceeded: {payload.Count}");
                await this.CloseOutputTimeoutAsync(WebSocketCloseStatus.ProtocolError, ex.Message, ex).ConfigureAwait(false);

                throw ex;
            }

            try
            {
                if (this._state == WebSocketState.Open)
                {
                    using (var stream = this._recycledStreamFactory())
                    {
                        stream.WriteFrame(WebSocketOpCode.Pong, payload, true, this.IsClient);
                        Events.Log.SendingFrame(this.ID, WebSocketOpCode.Pong, true, payload.Count, false);
                        await this.PutOnTheWireAsync(stream, cancellationToken).ConfigureAwait(false);
                    }
                }
            }
            catch (Exception ex)
            {
                await this.CloseOutputTimeoutAsync(WebSocketCloseStatus.EndpointUnavailable, "Unable to send PONG response", ex).ConfigureAwait(false);

                throw;
            }
        }
Esempio n. 2
0
            private void BufferElement(Offer <TOut> offer)
            {
                if (!_buffer.IsFull)
                {
                    EnqueueAndSuccess(offer);
                }
                else
                {
                    switch (_stage._overflowStrategy)
                    {
                    case OverflowStrategy.DropHead:
                        _buffer.DropHead();
                        EnqueueAndSuccess(offer);
                        break;

                    case OverflowStrategy.DropTail:
                        _buffer.DropTail();
                        EnqueueAndSuccess(offer);
                        break;

                    case OverflowStrategy.DropBuffer:
                        _buffer.Clear();
                        EnqueueAndSuccess(offer);
                        break;

                    case OverflowStrategy.DropNew:
                        offer.CompletionSource.SetResult(QueueOfferResult.Dropped.Instance);
                        break;

                    case OverflowStrategy.Fail:
                        var bufferOverflowException =
                            new BufferOverflowException($"Buffer overflow (max capacity was: {_stage._maxBuffer})!");
                        offer.CompletionSource.SetResult(new QueueOfferResult.Failure(bufferOverflowException));
                        _completion.SetException(bufferOverflowException);
                        FailStage(bufferOverflowException);
                        break;

                    case OverflowStrategy.Backpressure:
                        if (_pendingOffer != null)
                        {
                            offer.CompletionSource.SetException(
                                new IllegalStateException(
                                    "You have to wait for previous offer to be resolved to send another request."));
                        }
                        else
                        {
                            _pendingOffer = offer;
                        }
                        break;
                    }
                }
            }
Esempio n. 3
0
            private Action <IInput> Callback()
            {
                return(GetAsyncCallback <IInput>(
                           input =>
                {
                    var offer = input as Offer <TOut>;
                    if (offer != null)
                    {
                        if (_stage._maxBuffer != 0)
                        {
                            BufferElement(offer);
                            if (IsAvailable(_stage.Out))
                            {
                                Push(_stage.Out, _buffer.Dequeue());
                            }
                        }
                        else if (IsAvailable(_stage.Out))
                        {
                            Push(_stage.Out, offer.Element);
                            offer.CompletionSource.SetResult(QueueOfferResult.Enqueued.Instance);
                        }
                        else if (_pendingOffer == null)
                        {
                            _pendingOffer = offer;
                        }
                        else
                        {
                            switch (_stage._overflowStrategy)
                            {
                            case OverflowStrategy.DropHead:
                            case OverflowStrategy.DropBuffer:
                                _pendingOffer.CompletionSource.SetResult(QueueOfferResult.Dropped.Instance);
                                _pendingOffer = offer;
                                break;

                            case OverflowStrategy.DropTail:
                            case OverflowStrategy.DropNew:
                                offer.CompletionSource.SetResult(QueueOfferResult.Dropped.Instance);
                                break;

                            case OverflowStrategy.Backpressure:
                                offer.CompletionSource.SetException(
                                    new IllegalStateException(
                                        "You have to wait for previous offer to be resolved to send another request"));
                                break;

                            case OverflowStrategy.Fail:
                                var bufferOverflowException =
                                    new BufferOverflowException(
                                        $"Buffer overflow (max capacity was: {_stage._maxBuffer})!");
                                offer.CompletionSource.SetResult(new QueueOfferResult.Failure(bufferOverflowException));
                                _completion.SetException(bufferOverflowException);
                                FailStage(bufferOverflowException);
                                break;

                            default:
                                throw new ArgumentOutOfRangeException();
                            }
                        }
                    }

                    var completion = input as Completion;
                    if (completion != null)
                    {
                        if (_stage._maxBuffer != 0 && _buffer.NonEmpty || _pendingOffer != null)
                        {
                            _terminating = true;
                        }
                        else
                        {
                            _completion.SetResult(new object());
                            CompleteStage();
                        }
                    }

                    var failure = input as Failure;
                    if (failure != null)
                    {
                        _completion.SetException(failure.Ex);
                        FailStage(failure.Ex);
                    }
                }));
            }