/// <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; } }
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; } } }
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); } })); }