protected override void Decode(IChannelHandlerContext context, IHttpObject message, List <object> output) { // Determine if we're already handling an upgrade request or just starting a new one. this.handlingUpgrade |= IsUpgradeRequest(message); if (!this.handlingUpgrade) { // Not handling an upgrade request, just pass it to the next handler. ReferenceCountUtil.Retain(message); output.Add(message); return; } if (message is IFullHttpRequest fullRequest) { ReferenceCountUtil.Retain(fullRequest); output.Add(fullRequest); } else { // Call the base class to handle the aggregation of the full request. base.Decode(context, message, output); if (output.Count == 0) { // The full request hasn't been created yet, still awaiting more data. return; } // Finished aggregating the full request, get it from the output list. Debug.Assert(output.Count == 1); this.handlingUpgrade = false; fullRequest = (IFullHttpRequest)output[0]; } if (this.Upgrade(context, fullRequest)) { // The upgrade was successful, remove the message from the output list // so that it's not propagated to the next handler. This request will // be propagated as a user event instead. output.Clear(); } // The upgrade did not succeed, just allow the full request to propagate to the // next handler. }
async void StartQueueProcessingAsync(IChannelHandlerContext context) { try { Queue <T> queue = this.backlogQueue; while (queue.Count > 0 && this.state != State.Closed) { T message = queue.Dequeue(); try { await this.ProcessAsync(context, message); message = default(T); // dismissing packet reference as it has been successfully handed off in a form of message } finally { if (message != null) { ReferenceCountUtil.SafeRelease(message); } } } switch (this.state) { case State.Processing: this.state = State.Idle; break; case State.Closed: this.closedPromise.TryComplete(); break; default: throw new ArgumentOutOfRangeException(); } } catch (Exception ex) { this.closedPromise.TrySetException(new ChannelMessageProcessingException(ex, context)); this.Close(); } }
public void DecodeError(string value) { var channel = new EmbeddedChannel( new RedisDecoder(), new RedisBulkStringAggregator(), new RedisArrayAggregator()); Assert.False(channel.WriteInbound("-".Buffer())); Assert.False(channel.WriteInbound(value.Buffer())); Assert.False(channel.WriteInbound("\r".Buffer())); Assert.True(channel.WriteInbound("\n".Buffer())); var message = channel.ReadInbound <ErrorRedisMessage>(); Assert.Equal(value, message.Content); ReferenceCountUtil.Release(message); Assert.False(channel.Finish()); }
public void DecodeBulkString() { const string Buf1 = "bulk\nst"; const string Buf2 = "ring\ntest\n1234"; byte[] content = BytesOf(Buf1 + Buf2); Assert.False(this.channel.WriteInbound(ByteBufOf("$"))); Assert.False(this.channel.WriteInbound(ByteBufOf(Convert.ToString(content.Length)))); Assert.False(this.channel.WriteInbound(ByteBufOf("\r\n"))); Assert.False(this.channel.WriteInbound(ByteBufOf(Buf1))); Assert.False(this.channel.WriteInbound(ByteBufOf(Buf2))); Assert.True(this.channel.WriteInbound(ByteBufOf("\r\n"))); var msg = this.channel.ReadInbound <FullBulkStringRedisMessage>(); Assert.Equal(content, BytesOf(msg.Content)); ReferenceCountUtil.Release(msg); }
public override void ChannelRead(IChannelHandlerContext context, object msg) { Contract.Requires(context != null); var channel = context.Channel; var session = _appSessionContainer.Get(channel.Id.ToString()); if (session != null) { session.LastAccessTime = DateTime.Now; } bool release = true; try { if (msg is IPacket packet) { _logger.LogInformation($"The msg {msg} from {channel} has been read."); var requestContext = new RequestContext() { AppSession = session, Request = packet }; _messageRouter.Route(requestContext); } else { _logger.LogInformation($"The msg {msg} is not type of IMessage."); release = false; context.FireChannelRead(msg); } } catch (Exception ex) { _logger.LogError($"ChannelRead error", ex); } finally { if (_autoRelease && release) { ReferenceCountUtil.Release(msg); } } }
static object SafeDuplicate(FABMessage message) { //AbstractByteBuffer buffer = new AbstractByteBuffer(message.DataLength); var buffer = message.Data as IByteBuffer; if (buffer != null) { return(buffer.Duplicate().Retain()); } var byteBufferHolder = message.Data as IByteBufferHolder; if (byteBufferHolder != null) { return(byteBufferHolder.Duplicate().Retain()); } return(ReferenceCountUtil.Retain(message)); }
public Task HandshakeAsync(IChannel channel, IHttpRequest req, HttpHeaders responseHeaders) { if (req is IFullHttpRequest request) { return(this.HandshakeAsync(channel, request, responseHeaders)); } if (Logger.DebugEnabled) { Logger.Debug("{} WebSocket version {} server handshake", channel, this.version); } IChannelPipeline p = channel.Pipeline; IChannelHandlerContext ctx = p.Context <HttpRequestDecoder>(); if (ctx == null) { // this means the user use a HttpServerCodec ctx = p.Context <HttpServerCodec>(); if (ctx == null) { return(TaskEx.FromException(new InvalidOperationException("No HttpDecoder and no HttpServerCodec in the pipeline"))); } } // Add aggregator and ensure we feed the HttpRequest so it is aggregated. A limit o 8192 should be more then // enough for the websockets handshake payload. // // TODO: Make handshake work without HttpObjectAggregator at all. string aggregatorName = "httpAggregator"; p.AddAfter(ctx.Name, aggregatorName, new HttpObjectAggregator(8192)); var completion = new TaskCompletionSource(); p.AddAfter(aggregatorName, "handshaker", new Handshaker(this, channel, responseHeaders, completion)); try { ctx.FireChannelRead(ReferenceCountUtil.Retain(req)); } catch (Exception cause) { completion.TrySetException(cause); } return(completion.Task); }
public void UnsupportedVersion() { var ch = new EmbeddedChannel(); WebSocketServerHandshakerFactory.SendUnsupportedVersionResponse(ch); ch.RunPendingTasks(); var response = ch.ReadOutbound <IFullHttpResponse>(); Assert.NotNull(response); Assert.Equal(HttpResponseStatus.UpgradeRequired, response.Status); Assert.True(response.Headers.TryGet(HttpHeaderNames.SecWebsocketVersion, out ICharSequence value)); Assert.Equal(WebSocketVersion.V13.ToHttpHeaderValue(), value); Assert.True(HttpUtil.IsContentLengthSet(response)); Assert.Equal(0, HttpUtil.GetContentLength(response)); ReferenceCountUtil.Release(response); Assert.False(ch.Finish()); }
/// <summary> /// Compose <paramref name="cumulation"/> and <paramref name="next"/> into a new <see cref="CompositeByteBuffer"/>. /// </summary> /// <param name="alloc"></param> /// <param name="cumulation"></param> /// <param name="next"></param> /// <returns></returns> protected IByteBuffer ComposeIntoComposite(IByteBufferAllocator alloc, IByteBuffer cumulation, IByteBuffer next) { // Create a composite buffer to accumulate this pair and potentially all the buffers // in the queue. Using +2 as we have already dequeued current and next. var composite = alloc.CompositeBuffer(Size() + 2); try { _ = composite.AddComponent(true, cumulation); _ = composite.AddComponent(true, next); } catch (Exception) { _ = composite.Release(); ReferenceCountUtil.SafeRelease(next); throw; } return(composite); }
public void ShortCircuitWithoutConnectionShouldStayOpen() { CorsConfig config = CorsConfigBuilder.ForOrigin((AsciiString)"http://localhost:8080") .ShortCircuit().Build(); var channel = new EmbeddedChannel(new CorsHandler(config)); IFullHttpRequest request = CreateHttpRequest(HttpMethod.Get); request.Headers.Set(HttpHeaderNames.Origin, (AsciiString)"http://localhost:8888"); Assert.False(channel.WriteInbound(request)); var response = channel.ReadOutbound <IHttpResponse>(); Assert.True(HttpUtil.IsKeepAlive(response)); Assert.True(channel.IsOpen); Assert.Equal(HttpResponseStatus.Forbidden, response.Status); Assert.True(ReferenceCountUtil.Release(response)); Assert.False(channel.Finish()); }
/// <summary> /// Performs the opening handshake /// When call this method you <c>MUST NOT</c> retain the <see cref="IHttpRequest"/> which is passed in. /// </summary> /// <param name="channel">Channel</param> /// <param name="req">HTTP Request</param> /// <param name="responseHeaders">Extra headers to add to the handshake response or <code>null</code> if no extra headers should be added</param> /// <returns></returns> public Task HandshakeAsync(IChannel channel, IHttpRequest req, HttpHeaders responseHeaders) { if (req is IFullHttpRequest request) { return(HandshakeAsync(channel, request, responseHeaders)); } if (Logger.DebugEnabled) { Logger.WebSocketVersionServerHandshake(channel, _version); } IChannelPipeline p = channel.Pipeline; IChannelHandlerContext ctx = p.Context <HttpRequestDecoder>(); if (ctx is null) { // this means the user use an HttpServerCodec ctx = p.Context <HttpServerCodec>(); if (ctx is null) { return(ThrowHelper.ThrowInvalidOperationException_NoHttpDecoderAndServerCodec()); } } // Add aggregator and ensure we feed the HttpRequest so it is aggregated. A limit o 8192 should be more then // enough for the websockets handshake payload. // // TODO: Make handshake work without HttpObjectAggregator at all. string aggregatorName = "httpAggregator"; _ = p.AddAfter(ctx.Name, aggregatorName, new HttpObjectAggregator(8192)); var completion = channel.NewPromise(); _ = p.AddAfter(aggregatorName, "handshaker", new Handshaker(this, channel, responseHeaders, completion)); try { _ = ctx.FireChannelRead(ReferenceCountUtil.Retain(req)); } catch (Exception cause) { _ = completion.TrySetException(cause); } return(completion.Task); }
public void TooManyResponses() { var ch = new EmbeddedChannel(new HttpContentCompressor()); ch.WriteInbound(NewRequest()); ch.WriteOutbound(new DefaultFullHttpResponse(HttpVersion.Http11, HttpResponseStatus.OK, Unpooled.Empty)); try { ch.WriteOutbound(new DefaultFullHttpResponse(HttpVersion.Http11, HttpResponseStatus.OK, Unpooled.Empty)); Assert.True(false, "Should not get here, expecting exception thrown"); } catch (AggregateException e) { Assert.Single(e.InnerExceptions); Assert.IsType <EncoderException>(e.InnerExceptions[0]); Exception exception = e.InnerExceptions[0]; Assert.IsType <InvalidOperationException>(exception.InnerException); } Assert.True(ch.Finish()); for (;;) { var message = ch.ReadOutbound <object>(); if (message == null) { break; } ReferenceCountUtil.Release(message); } for (;;) { var message = ch.ReadInbound <object>(); if (message == null) { break; } ReferenceCountUtil.Release(message); } }
public override void ChannelRead(IChannelHandlerContext context, object message) { ThreadLocalObjectList output = ThreadLocalObjectList.NewInstance(); try { if (this.AcceptInboundMessage(message)) { var cast = (T)message; try { this.Decode(context, cast, output); } finally { ReferenceCountUtil.Release(cast); } } else { output.Add(message); } } catch (DecoderException e) { throw; } catch (Exception e) { throw new DecoderException(e); } finally { int size = output.Count; for (int i = 0; i < size; i++) { context.FireChannelRead(output[i]); } output.Return(); } base.ChannelRead(context, message); }
public override void channelRead(ChannelHandlerContext ctx, Object msg) { // CodecOutputList outBuffers = CodecOutputList.newInstance(); try { if (acceptInboundMessage(msg)) { I cast = (I)msg; try { // decode(ctx, cast, outBuffers); } finally { ReferenceCountUtil.release(cast); } } else { // outBuffers.add(msg); } } catch (DecoderException e) { throw e; } catch (Exception e) { throw new DecoderException("channelRead", e); } finally { // int size = outBuffers.size(); // for (int i = 0; i < size; i++) // { // ctx.fireChannelRead(outBuffers.getUnsafe(i)); // } // outBuffers.recycle(); } }
public Task WriteAndFlushAsync(object message, IChannelMatcher matcher, bool voidPromise) { if (message is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.message); } if (matcher is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.matcher); } Task result; if (voidPromise) { foreach (IChannel c in _nonServerChannels.Values) { if (matcher.Matches(c)) { _ = c.WriteAndFlushAsync(SafeDuplicate(message), c.VoidPromise()); } } result = TaskUtil.Completed; } else { var futures = new Dictionary <IChannel, Task>(_nonServerChannels.Count, ChannelComparer.Default); foreach (IChannel c in _nonServerChannels.Values) { if (matcher.Matches(c)) { futures.Add(c, c.WriteAndFlushAsync(SafeDuplicate(message))); } } result = new DefaultChannelGroupCompletionSource(this, futures /*, this.executor*/).Task; } _ = ReferenceCountUtil.Release(message); return(result); }
public DefaultHttp2FrameWriterTest() { _http2HeadersEncoder = new DefaultHttp2HeadersEncoder( NeverSensitiveDetector.Instance, new HpackEncoder(false, 16, 0)); _frameWriter = new DefaultHttp2FrameWriter(new DefaultHttp2HeadersEncoder( NeverSensitiveDetector.Instance, new HpackEncoder(false, 16, 0))); _outbound = Unpooled.Buffer(); _expectedOutbound = Unpooled.Empty; _promise = new TaskCompletionSource(); _channel = new Mock <IChannel>(); Task localAnswer(object msg) { if (msg is IByteBuffer buf) { _outbound.WriteBytes(buf); } ReferenceCountUtil.Release(msg); return(TaskUtil.Completed); } Task localAnswer0(object msg, IPromise promise) { if (msg is IByteBuffer buf) { _outbound.WriteBytes(buf); } ReferenceCountUtil.Release(msg); return(TaskUtil.Completed); } _ctx = new Mock <IChannelHandlerContext>(); _ctx.Setup(x => x.WriteAsync(It.IsAny <object>())).Returns <object>(localAnswer); _ctx.Setup(x => x.WriteAsync(It.IsAny <object>(), It.IsAny <IPromise>())).Returns <object, IPromise>(localAnswer0); _ctx.Setup(x => x.Allocator).Returns(UnpooledByteBufferAllocator.Default); _ctx.Setup(x => x.Channel).Returns(_channel.Object); }
public void DecodeWithoutStrip() { EmbeddedChannel ch = new EmbeddedChannel(new LineBasedFrameDecoder(8192, false, false)); ch.WriteInbound(Unpooled.CopiedBuffer("first\r\nsecond\nthird", Encoding.ASCII)); var buf = ch.ReadInbound <IByteBuffer>(); Assert.Equal("first\r\n", buf.ToString(Encoding.ASCII)); var buf2 = ch.ReadInbound <IByteBuffer>(); Assert.Equal("second\n", buf2.ToString(Encoding.ASCII)); Assert.Null(ch.ReadInbound <IByteBuffer>()); ch.Finish(); ReferenceCountUtil.Release(ch.ReadInbound <IByteBuffer>()); buf.Release(); buf2.Release(); }
async void RetransmitPublishMessage(IChannelHandlerContext context, MessageWithFeedback messageWithFeedback, AckPendingMessageState messageInfo) { PublishPacket packet = null; try { using (IMessage message = messageWithFeedback.Message) { message.Properties[TemplateParameters.DeviceIdTemplateParam] = this.DeviceId; packet = Util.ComposePublishPacket(context, message, messageInfo.QualityOfService, context.Channel.Allocator); messageInfo.ResetMessage(message, messageWithFeedback.FeedbackChannel); await this.publishPubAckProcessor.RetransmitAsync(context, packet, messageInfo); } } catch (Exception ex) { ReferenceCountUtil.SafeRelease(packet); ShutdownOnError(context, "<- PUBLISH (retransmission)", ex); } }
public int Cancel() { if (!this.Cancelled) { this.Cancelled = true; int pSize = this.PendingSize; // release message and replace with an empty buffer ReferenceCountUtil.SafeRelease(this.Message); this.Message = Unpooled.Empty; this.PendingSize = 0; this.Total = 0; this.Progress = 0; this.Buffers = null; this.Buffer = null; return(pSize); } return(0); }
IByteBuffer CreateNewDirectBuffer(IByteBuffer buffer) { Contract.Requires(buffer != null); int readableBytes = buffer.ReadableBytes; if (readableBytes == 0) { ReferenceCountUtil.SafeRelease(buffer); return(Unpooled.Empty); } // Composite IByteBuffer data = this.Allocator.Buffer(readableBytes); data.WriteBytes(buffer, buffer.ReaderIndex, readableBytes); ReferenceCountUtil.SafeRelease(buffer); return(data); }
/// <summary> /// Remove a pending write operation and fail it with the given <see cref="Exception"/>. The message will be /// released via <see cref="ReferenceCountUtil.SafeRelease(object)"/>. /// </summary> /// <param name="cause">The <see cref="Exception"/> to fail with.</param> public void RemoveAndFail(Exception cause) { Debug.Assert(_ctx.Executor.InEventLoop); if (cause is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.cause); } PendingWrite write = _head; if (write is null) { return; } ReferenceCountUtil.SafeRelease(write.Msg); IPromise promise = write.Promise; Util.SafeSetFailure(promise, cause, Logger); Recycle(write, true); }
public override void ChannelRead(IChannelHandlerContext context, object message) { if (message is IHttpRequest req && HttpUtil.Is100ContinueExpected(req)) { IHttpResponse accept = this.AcceptMessage(req); if (accept is null) { // the expectation failed so we refuse the request. IHttpResponse rejection = this.RejectResponse(req); _ = ReferenceCountUtil.Release(message); _ = context.WriteAndFlushAsync(rejection).ContinueWith(CloseOnFailureAction, context, TaskContinuationOptions.ExecuteSynchronously); return; } _ = context.WriteAndFlushAsync(accept).ContinueWith(CloseOnFailureAction, context, TaskContinuationOptions.ExecuteSynchronously); _ = req.Headers.Remove(HttpHeaderNames.Expect); } _ = context.FireChannelRead(message); }
public int Cancel() { if (!Cancelled) { Cancelled = true; int pSize = PendingSize; // release message and replace with an empty buffer ReferenceCountUtil.SafeRelease(Message); Message = Unpooled.Empty; PendingSize = 0; Total = 0L; Progress = 0L; Buffers = null; Buffer = new ArraySegment <byte>(); return(pSize); } return(0); }
public override void ChannelRead(IChannelHandlerContext ctx, object message) { Task.Factory.StartNew(() => { if (message is IFullHttpRequest request) { try { this.Process(ctx, request); } finally { ReferenceCountUtil.Release(message); } } else { ctx.FireChannelRead(message); } }); }
public static string HexDump(this IByteBuffer buffer) { try { string hexStr = ByteBufferUtil.HexDump(buffer); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hexStr.Length; i++) { if (i % 2 == 0) { sb.Append(hexStr, i, 2).Append(" "); } } return(sb.ToString().Trim().ToUpper()); } finally { ReferenceCountUtil.Release(buffer); } }
public void TestRpcCodecWithBody() { var inputBody = new byte[3] { 1, 2, 3 }; var req = new RequestHeartBeat() { MilliSeconds = 456 }; var rpcMessage = new RpcMessage(req, inputBody); var buffer = rpcCodec.Encode(allocator, rpcMessage) as IByteBuffer; var bufferLength = buffer.ReadableBytes; var(length, typeName, msg) = rpcCodec.Decode(buffer); RpcMessageEqual(rpcMessage, bufferLength, msg as RpcMessage, (int)length); ReferenceCountUtil.Release(buffer); }
public Task WriteAsync(object msg) { this.AssertEventLoop(); ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null) { // If the outboundBuffer is null we know the channel was closed and so // need to fail the future right away. If it is not null the handling of the rest // will be done input flush0() // See https://github.com/netty/netty/issues/2362 // release message now to prevent resource-leak ReferenceCountUtil.Release(msg); return(TaskEx.FromException(new ClosedChannelException())); } int size; try { msg = this.channel.FilterOutboundMessage(msg); size = this.channel.pipeline.EstimatorHandle.Size(msg); if (size < 0) { size = 0; } } catch (Exception t) { ReferenceCountUtil.Release(msg); return(TaskEx.FromException(t)); } var promise = new TaskCompletionSource(); outboundBuffer.AddMessage(msg, size, promise); return(promise.Task); }
public override void ChannelRead(IChannelHandlerContext context, object message) { var output = RecyclableArrayList.Take(); try { if (AcceptInboundMessage(message)) { var cast = (TMessage)message; try { Decode(context, cast, output); } finally { ReferenceCountUtil.Release(cast); } } else { output.Add(message); } } catch (DecoderException) { throw; } catch (Exception ex) { throw new DecoderException(ex); } finally { var size = output.Count; for (var i = 0; i < size; i++) { context.FireChannelRead(output[i]); } output.Return(); } }
/// <summary> /// Closes channel /// </summary> async void Shutdown(IChannelHandlerContext context, Exception cause) { if (this.IsInState(StateFlags.Closed)) { return; } this.lifetimeCancellation.Cancel(); this.qos2Semaphore?.Dispose(); try { this.stateFlags |= StateFlags.Closed; // "or" not to interfere with ongoing logic which has to honor Closed state when it's right time to do (case by case) // only decrement connection current counter if the state had connected state in this session if (this.IsInState(StateFlags.Connected)) { PerformanceCounters.ConnectionsCurrent.Decrement(); } Queue <Packet> connectQueue = this.connectPendingQueue; if (connectQueue != null) { while (connectQueue.Count > 0) { Packet packet = connectQueue.Dequeue(); ReferenceCountUtil.Release(packet); } } PublishPacket will = (cause != null) && this.IsInState(StateFlags.Connected) ? this.willPacket : null; await this.CloseServiceConnection(context, cause, will); await context.CloseAsync(); } catch (Exception ex) { CommonEventSource.Log.Warning("Error occurred while shutting down the channel.", ex, this.ChannelId, this.Id); } }
public Task InvokeWriteAsync(IChannelHandlerContext ctx, object msg) { Contract.Requires(msg != null); // todo: check for cancellation //if (!validatePromise(ctx, promise, false)) { // // promise cancelled // return; //} if (this.executor.InEventLoop) { return(ChannelHandlerInvokerUtil.InvokeWriteAsyncNow(ctx, msg)); } else { var channel = (AbstractChannel)ctx.Channel; var promise = new TaskCompletionSource(ctx); try { int size = channel.EstimatorHandle.Size(msg); if (size > 0) { ChannelOutboundBuffer buffer = channel.Unsafe.OutboundBuffer; // Check for null as it may be set to null if the channel is closed already if (buffer != null) { buffer.IncrementPendingOutboundBytes(size); } } this.executor.Execute(InvokeWriteAsyncAction, promise, msg); } catch (Exception cause) { ReferenceCountUtil.Release(msg); // todo: safe release? promise.TrySetException(cause); } return(promise.Task); } }