public void Decode() { EmbeddedChannel ch = new EmbeddedChannel( new DelimiterBasedFrameDecoder(8192, true, Delimiters.LineDelimiter())); ch.WriteInbound(Unpooled.CopiedBuffer("first\r\nsecond\nthird", Encoding.ASCII)); var buf = ch.ReadInbound <IByteBuffer>(); Assert.Equal("first", buf.ToString(Encoding.ASCII)); var buf2 = ch.ReadInbound <IByteBuffer>(); Assert.Equal("second", buf2.ToString(Encoding.ASCII)); Assert.Null(ch.ReadInbound <IByteBuffer>()); ch.Finish(); ReferenceCountUtil.Release(ch.ReadInbound <IByteBuffer>()); buf.Release(); buf2.Release(); }
public void Clear(DnsSection section) { object recordOrList = SectionAt(section); SetSection(section, null); if (recordOrList is IReferenceCounted) { ((IReferenceCounted)recordOrList).Release(); } else if (recordOrList is IList) { List <IDnsRecord> list = (List <IDnsRecord>)recordOrList; if (list.Count == 0) { foreach (var r in list) { ReferenceCountUtil.Release(r); } } } }
public void DecodeSimpleArray() { Assert.False(this.channel.WriteInbound(ByteBufOf("*3\r\n"))); Assert.False(this.channel.WriteInbound(ByteBufOf(":1234\r\n"))); Assert.False(this.channel.WriteInbound(ByteBufOf("+sim"))); Assert.False(this.channel.WriteInbound(ByteBufOf("ple\r\n-err"))); Assert.True(this.channel.WriteInbound(ByteBufOf("or\r\n"))); var msg = this.channel.ReadInbound <IArrayRedisMessage>(); IList <IRedisMessage> children = msg.Children; Assert.Equal(3, msg.Children.Count); Assert.IsType <IntegerRedisMessage>(children[0]); Assert.Equal(1234L, ((IntegerRedisMessage)children[0]).Value); Assert.IsType <SimpleStringRedisMessage>(children[1]); Assert.Equal("simple", ((SimpleStringRedisMessage)children[1]).Content); Assert.IsType <ErrorRedisMessage>(children[2]); Assert.Equal("error", ((ErrorRedisMessage)children[2]).Content); ReferenceCountUtil.Release(msg); }
public Task WriteAsync(object msg) { 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(ClosedChannelException)); } int size; try { msg = this.channel.FilterOutboundMessage(msg); size = this.channel.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) { IByteBuffer byteBuffer = message as IByteBuffer; if (byteBuffer != null) { if (byteBuffer.HasArray) { int length = byteBuffer.ReadableBytes; byte[] array = new byte[length]; byteBuffer.GetBytes(byteBuffer.ReaderIndex, array); _ms.OnReceiveUpTransmisstion(array); } else { Logger.Log.Info(true, "主节点,没有读到有效的数据"); } ReferenceCountUtil.Release(message); } }
public void DecodeInlineCommand() { EmbeddedChannel ch = NewChannel(true); try { Assert.False(ch.WriteInbound(ByteBufOf("P"))); Assert.False(ch.WriteInbound(ByteBufOf("I"))); Assert.False(ch.WriteInbound(ByteBufOf("N"))); Assert.False(ch.WriteInbound(ByteBufOf("G"))); Assert.True(ch.WriteInbound(ByteBufOf("\r\n"))); var msg = ch.ReadInbound <InlineCommandRedisMessage>(); Assert.Equal("PING", msg.Content); ReferenceCountUtil.Release(msg); } finally { ch.CloseAsync().Wait(TimeSpan.FromSeconds(10)); } }
public void Write(object msg, IPromise promise) { AssertEventLoop(); ChannelOutboundBuffer outboundBuffer = Volatile.Read(ref v_outboundBuffer); if (outboundBuffer is 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 Util.SafeSetFailure(promise, WriteClosedChannelException, Logger); // release message now to prevent resource-leak _ = ReferenceCountUtil.Release(msg); return; } int size; try { var ch = _channel; msg = ch.FilterOutboundMessage(msg); size = ch._pipeline.EstimatorHandle.Size(msg); if ((uint)size > SharedConstants.TooBigOrNegative) // < 0 { size = 0; } } catch (Exception t) { Util.SafeSetFailure(promise, t, Logger); _ = ReferenceCountUtil.Release(msg); return; } outboundBuffer.AddMessage(msg, size, promise); }
public Task InvokeWriteAsync(IChannelHandlerContext ctx, object msg) { Contract.Requires(msg != null); // todo: check for cancellation //if (!validatePromise(ctx, promise, false)) { // // promise cancelled // return; //} if (Executor.InEventLoop) { return(ChannelHandlerInvokerUtil.InvokeWriteAsyncNow(ctx, msg)); } var channel = (AbstractChannel)ctx.Channel; var promise = new TaskCompletionSource(ctx); try { var size = channel.EstimatorHandle.Size(msg); if (size > 0) { var 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); } } Executor.Execute(InvokeWriteAsyncAction, promise, msg); } catch (Exception cause) { ReferenceCountUtil.Release(msg); promise.TrySetException(cause); } return(promise.Task); }
/// <summary> /// Closes channel /// </summary> async void Shutdown(IChannelHandlerContext context, Exception cause) { if (this.IsInState(StateFlags.Closed)) { return; } 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); } }
static void AssertHasOutboundMessages(EmbeddedChannel channel, bool hasMessages) { object o; if (hasMessages) { while (true) { o = channel.ReadOutbound <object>(); Assert.NotNull(o); ReferenceCountUtil.Release(o); if (o is ILastHttpContent) { break; } } } else { o = channel.ReadOutbound <object>(); Assert.Null(o); } }
/// <summary> /// Puts the new work to backlog queue and resume work if worker is idle. /// </summary> /// <param name="context"></param> /// <param name="workItem"></param> public virtual void Post(IChannelHandlerContext context, TWork workItem) { switch (this.State) { case States.Idle: this.backlogQueue.Enqueue(workItem); this.State = States.Processing; this.StartWorkQueueProcessingAsync(context); break; case States.Processing: case States.FinalProcessing: this.backlogQueue.Enqueue(workItem); break; case States.Aborted: ReferenceCountUtil.Release(workItem); break; default: throw new ArgumentOutOfRangeException(); } }
private void Btn_tool_qqencrypt_calc_Click(object sender, EventArgs e) { string qq = Frm.txt_tool_qqencrypt_qq.Text; string pass = Frm.txt_tool_qqencrypt_pass.Text; var buf = Unpooled.Buffer(); try { buf.WriteBytes(Util.GenerateMD5Byte(pass)) .WriteInt(0) .WriteInt((int)Convert.ToInt64(qq)); Frm.txt_tool_qqencrypt_ret.Text = buf.Copy().Array.Md5().HexDump(); } catch (Exception ex) { Toast.Warn(ex.Message); } finally { ReferenceCountUtil.Release(buf); } }
public void DecodeSimpleString(string value) { var channel = new EmbeddedChannel( new RedisDecoder(), new RedisBulkStringAggregator(), new RedisArrayAggregator()); Assert.False(channel.WriteInbound("+".Buffer())); foreach (char c in value) { string charValue = new string(new[] { c }); Assert.False(channel.WriteInbound(charValue.Buffer())); } Assert.True(channel.WriteInbound("\r\n".Buffer())); var message = channel.ReadInbound <SimpleStringRedisMessage>(); Assert.NotNull(message); Assert.Equal(value, message.Content); ReferenceCountUtil.Release(message); Assert.False(channel.Finish()); }
private static void Upgrade0(EmbeddedChannel ch, WebSocketServerHandshaker13 handshaker) { var req = new DefaultFullHttpRequest(Http11, HttpMethod.Get, "/chat"); req.Headers.Set(HttpHeaderNames.Host, "server.example.com"); req.Headers.Set(HttpHeaderNames.Upgrade, HttpHeaderValues.Websocket); req.Headers.Set(HttpHeaderNames.Connection, "Upgrade"); req.Headers.Set(HttpHeaderNames.SecWebsocketKey, "dGhlIHNhbXBsZSBub25jZQ=="); req.Headers.Set(HttpHeaderNames.SecWebsocketOrigin, "http://example.com"); req.Headers.Set(HttpHeaderNames.SecWebsocketProtocol, "chat, superchat"); req.Headers.Set(HttpHeaderNames.SecWebsocketVersion, "13"); Assert.True(handshaker.HandshakeAsync(ch, req).Wait(TimeSpan.FromSeconds(2))); var resBuf = ch.ReadOutbound <IByteBuffer>(); var ch2 = new EmbeddedChannel(new HttpResponseDecoder()); ch2.WriteInbound(resBuf); var res = ch2.ReadInbound <IHttpResponse>(); Assert.True(res.Headers.TryGet(HttpHeaderNames.SecWebsocketAccept, out ICharSequence value)); Assert.Equal("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", value.ToString()); var subProtocols = handshaker.Subprotocols(); if (subProtocols.Any()) { Assert.True(res.Headers.TryGet(HttpHeaderNames.SecWebsocketProtocol, out value)); Assert.Equal("chat", value.ToString()); } else { Assert.False(res.Headers.TryGet(HttpHeaderNames.SecWebsocketProtocol, out _)); } ReferenceCountUtil.Release(res); req.Release(); }
public void DecodeEmptyBulkString() { var channel = new EmbeddedChannel( new RedisDecoder(), new RedisBulkStringAggregator(), new RedisArrayAggregator()); byte[] content = "".Bytes(); Assert.False(channel.WriteInbound("$".Buffer())); Assert.False(channel.WriteInbound(content.Length.ToString().Buffer())); Assert.False(channel.WriteInbound("\r\n".Buffer())); Assert.False(channel.WriteInbound(content.Buffer())); Assert.True(channel.WriteInbound("\r\n".Buffer())); var message = channel.ReadInbound <IFullBulkStringRedisMessage>(); byte[] output = message.Content.Bytes(); Assert.Equal(content.Length, output.Length); Assert.True(content.SequenceEqual(output)); ReferenceCountUtil.Release(message); Assert.False(channel.Finish()); }
public override void ChannelRead(IChannelHandlerContext ctx, object msg) { bool release = true; try { if (TryAcceptInboundMessage(msg, out I imsg)) { ChannelRead0(ctx, imsg); } else { release = false; _ = ctx.FireChannelRead(msg); } } finally { if (_autoRelease && release) { _ = ReferenceCountUtil.Release(msg); } } }
public void Abort() { switch (this.state) { case State.Idle: case State.Processing: case State.FinalProcessing: this.state = State.Aborted; Queue <T> queue = this.backlogQueue; while (queue.Count > 0) { T packet = queue.Dequeue(); ReferenceCountUtil.Release(packet); } break; case State.Aborted: break; default: throw new ArgumentOutOfRangeException(); } }
public void DecodeNullBulkString() { Assert.False(this.channel.WriteInbound(ByteBufOf("$"))); Assert.False(this.channel.WriteInbound(ByteBufOf(Convert.ToString(-1)))); Assert.True(this.channel.WriteInbound(ByteBufOf("\r\n"))); Assert.True(this.channel.WriteInbound(ByteBufOf("$"))); Assert.True(this.channel.WriteInbound(ByteBufOf(Convert.ToString(-1)))); Assert.True(this.channel.WriteInbound(ByteBufOf("\r\n"))); var msg1 = this.channel.ReadInbound <IFullBulkStringRedisMessage>(); Assert.True(msg1.IsNull); ReferenceCountUtil.Release(msg1); var msg2 = this.channel.ReadInbound <IFullBulkStringRedisMessage>(); Assert.True(msg2.IsNull); ReferenceCountUtil.Release(msg2); var msg3 = this.channel.ReadInbound <IFullBulkStringRedisMessage>(); Assert.Null(msg3); }
public void UserEventTriggered(IChannelHandlerContext context, object evt) => ReferenceCountUtil.Release(evt);
public async Task TestFlowToggleAutoRead() { IChannel channel = null; var mre = new ManualResetEventSlim(false); var msgRcvLatch1 = new CountdownEvent(1); var msgRcvLatch2 = new CountdownEvent(1); var msgRcvLatch3 = new CountdownEvent(1); var setAutoReadLatch1 = new CountdownEvent(1); var setAutoReadLatch2 = new CountdownEvent(1); int msgRcvCount = 0; int expectedMsgCount = 0; ChannelHandlerAdapter handler = new TestHandler( onActive: ctx => { Interlocked.Exchange(ref channel, ctx.Channel); mre.Set(); ctx.FireChannelActive(); }, onRead: (ctx, msg) => { ReferenceCountUtil.Release(msg); // Disable auto reading after each message ctx.Channel.Configuration.AutoRead = false; if (msgRcvCount++ != expectedMsgCount) { return; } switch (msgRcvCount) { case 1: msgRcvLatch1.Signal(); if (setAutoReadLatch1.Wait(TimeSpan.FromSeconds(1))) { ++expectedMsgCount; } break; case 2: msgRcvLatch2.Signal(); if (setAutoReadLatch2.Wait(TimeSpan.FromSeconds(1))) { ++expectedMsgCount; } break; default: msgRcvLatch3.Signal(); break; } } ); var flow = new FlowControlHandler(); IChannel server = await this.NewServer(true, flow, handler); IChannel client = await this.NewClient(server.LocalAddress); try { // The client connection on the server side mre.Wait(TimeSpan.FromSeconds(1)); IChannel peer = Interlocked.Exchange(ref channel, null); await client.WriteAndFlushAsync(NewOneMessage()); // channelRead(1) Assert.True(msgRcvLatch1.Wait(TimeSpan.FromSeconds(1))); // channelRead(2) peer.Configuration.AutoRead = true; setAutoReadLatch1.Signal(); Assert.True(msgRcvLatch1.Wait(TimeSpan.FromSeconds(1))); // channelRead(3) peer.Configuration.AutoRead = true; setAutoReadLatch2.Signal(); Assert.True(msgRcvLatch3.Wait(TimeSpan.FromSeconds(1))); Assert.True(flow.IsQueueEmpty); } finally { Task.WhenAll(client.CloseAsync(), server.CloseAsync()).Wait(TimeSpan.FromSeconds(5)); } }
public override void ChannelRead(IChannelHandlerContext context, object message) { ReferenceCountUtil.Release(message); }
public override void ChannelRead(IChannelHandlerContext ctx, object msg) { //consume this msg ReferenceCountUtil.Release(msg); }
public void Fail(Exception error) { _ = ReferenceCountUtil.Release(Message); _ = Promise.TrySetException(error); }
void DoFlush(IChannelHandlerContext context) { IChannel channel = context.Channel; if (!channel.Active) { Discard(); return; } bool requiresFlush = true; IByteBufferAllocator allocator = context.Allocator; while (channel.IsWritable) { PendingWrite currentWrite = _queue.FirstOrDefault; if (currentWrite is null) { break; } if (currentWrite.Promise.IsCompleted) { // This might happen e.g. in the case when a write operation // failed, but there're still unconsumed chunks left. // Most chunked input sources would stop generating chunks // and report end of input, but this doesn't work with any // source wrapped in HttpChunkedInput. // Note, that we're not trying to release the message/chunks // as this had to be done already by someone who resolved the // promise (using ChunkedInput.close method). // See https://github.com/netty/netty/issues/8700. _ = _queue.RemoveFromFront(); continue; } object pendingMessage = currentWrite.Message; if (pendingMessage is IChunkedInput <T> chunks) { bool endOfInput; bool suspend; object message = null; try { message = chunks.ReadChunk(allocator); endOfInput = chunks.IsEndOfInput; if (message is null) { // No need to suspend when reached at the end. suspend = !endOfInput; } else { suspend = false; } } catch (Exception exception) { _ = _queue.RemoveFromFront(); if (message is object) { _ = ReferenceCountUtil.Release(message); } CloseInput(chunks); currentWrite.Fail(exception); break; } if (suspend) { // ChunkedInput.nextChunk() returned null and it has // not reached at the end of input. Let's wait until // more chunks arrive. Nothing to write or notify. break; } if (message is null) { // If message is null write an empty ByteBuf. // See https://github.com/netty/netty/issues/1671 message = Unpooled.Empty; } // Flush each chunk to conserve memory Task future = context.WriteAndFlushAsync(message); if (endOfInput) { _ = _queue.RemoveFromFront(); if (future.IsCompleted) { HandleEndOfInputFuture(future, currentWrite); } else { // Register a listener which will close the input once the write is complete. // This is needed because the Chunk may have some resource bound that can not // be closed before its not written. // // See https://github.com/netty/netty/issues/303 _ = future.ContinueWith(LinkOutcomeWhenIsEndOfChunkedInputAction, currentWrite, TaskContinuationOptions.ExecuteSynchronously); } } else { var resume = !channel.IsWritable; if (future.IsCompleted) { HandleFuture(future, this, channel, currentWrite, resume); } else { _ = future.ContinueWith(LinkOutcomeAction, Tuple.Create(this, channel, currentWrite, resume), TaskContinuationOptions.ExecuteSynchronously); } } requiresFlush = false; } else { _ = _queue.RemoveFromFront(); _ = context.WriteAsync(pendingMessage, currentWrite.Promise); requiresFlush = true; } if (!channel.Active) { Discard(new ClosedChannelException()); break; } } if (requiresFlush) { _ = context.Flush(); } }
void DoFlush(IChannelHandlerContext context) { IChannel channel = context.Channel; if (!channel.Active) { this.Discard(); return; } bool requiresFlush = true; IByteBufferAllocator allocator = context.Allocator; while (channel.IsWritable) { if (this.currentWrite == null) { this.currentWrite = this.queue.Count > 0 ? this.queue.Dequeue() : null; } if (this.currentWrite == null) { break; } PendingWrite current = this.currentWrite; object pendingMessage = current.Message; var chunks = pendingMessage as IChunkedInput <T>; if (chunks != null) { bool endOfInput; bool suspend; object message = null; try { message = chunks.ReadChunk(allocator); endOfInput = chunks.IsEndOfInput; if (message == null) { // No need to suspend when reached at the end. suspend = !endOfInput; } else { suspend = false; } } catch (Exception exception) { this.currentWrite = null; if (message != null) { ReferenceCountUtil.Release(message); } current.Fail(exception); CloseInput(chunks); break; } if (suspend) { // ChunkedInput.nextChunk() returned null and it has // not reached at the end of input. Let's wait until // more chunks arrive. Nothing to write or notify. break; } if (message == null) { // If message is null write an empty ByteBuf. // See https://github.com/netty/netty/issues/1671 message = Unpooled.Empty; } Task future = context.WriteAsync(message); if (endOfInput) { this.currentWrite = null; // Register a listener which will close the input once the write is complete. // This is needed because the Chunk may have some resource bound that can not // be closed before its not written. // // See https://github.com/netty/netty/issues/303 future.ContinueWith((_, state) => { var pendingTask = (PendingWrite)state; CloseInput((IChunkedInput <T>)pendingTask.Message); pendingTask.Success(); }, current, TaskContinuationOptions.ExecuteSynchronously); } else if (channel.IsWritable) { future.ContinueWith((task, state) => { var pendingTask = (PendingWrite)state; if (task.IsFaulted) { CloseInput((IChunkedInput <T>)pendingTask.Message); pendingTask.Fail(task.Exception); } else { pendingTask.Progress(chunks.Progress, chunks.Length); } }, current, TaskContinuationOptions.ExecuteSynchronously); } else { future.ContinueWith((task, state) => { var handler = (ChunkedWriteHandler <T>)state; if (task.IsFaulted) { CloseInput((IChunkedInput <T>)handler.currentWrite.Message); handler.currentWrite.Fail(task.Exception); } else { handler.currentWrite.Progress(chunks.Progress, chunks.Length); if (channel.IsWritable) { handler.ResumeTransfer(); } } }, this, TaskContinuationOptions.ExecuteSynchronously); } // Flush each chunk to conserve memory context.Flush(); requiresFlush = false; } else { context.WriteAsync(pendingMessage) .ContinueWith((task, state) => { var pendingTask = (PendingWrite)state; if (task.IsFaulted) { pendingTask.Fail(task.Exception); } else { pendingTask.Success(); } }, current, TaskContinuationOptions.ExecuteSynchronously); this.currentWrite = null; requiresFlush = true; } if (!channel.Active) { this.Discard(new ClosedChannelException()); break; } } if (requiresFlush) { context.Flush(); } }
public override Task WriteAsync(IChannelHandlerContext ctx, object msg) { Task result; ThreadLocalObjectList output = null; try { if (this.AcceptOutboundMessage(msg)) { output = ThreadLocalObjectList.NewInstance(); var cast = (T)msg; try { this.Encode(ctx, cast, output); } finally { ReferenceCountUtil.Release(cast); } if (output.Count == 0) { output.Return(); output = null; throw new EncoderException(this.GetType().Name + " must produce at least one message."); } } else { return(ctx.WriteAsync(msg)); } } catch (EncoderException e) { return(TaskEx.FromException(e)); } catch (Exception ex) { return(TaskEx.FromException(new EncoderException(ex))); // todo: we don't have a stack on EncoderException but it's present on inner exception. } finally { if (output != null) { int lastItemIndex = output.Count - 1; if (lastItemIndex == 0) { result = ctx.WriteAsync(output[0]); } else if (lastItemIndex > 0) { for (int i = 0; i < lastItemIndex; i++) { // we don't care about output from these messages as failure while sending one of these messages will fail all messages up to the last message - which will be observed by the caller in Task result. ctx.WriteAsync(output[i]); // todo: optimize: once IChannelHandlerContext allows, pass "not interested in task" flag } result = ctx.WriteAsync(output[lastItemIndex]); } else { // 0 items in output - must never get here result = null; } output.Return(); } else { // output was reset during exception handling - must never get here result = null; } } return(result); }
/// <summary> /// Handles conversion of <see cref="IHttpMessage"/> and <see cref="IHttpContent"/> to HTTP/2 frames. /// </summary> public override void Write(IChannelHandlerContext ctx, object msg, IPromise promise) { var httpMsg = msg as IHttpMessage; var contentMsg = msg as IHttpContent; if (httpMsg is null && contentMsg is null) { _ = ctx.WriteAsync(msg, promise); return; } var release = true; var promiseAggregator = new SimplePromiseAggregator(promise); try { var encoder = Encoder; var endStream = false; if (httpMsg is object) { // Provide the user the opportunity to specify the streamId _currentStreamId = GetStreamId(httpMsg.Headers); // Convert and write the headers. var http2Headers = HttpConversionUtil.ToHttp2Headers(httpMsg, _validateHeaders); endStream = msg is IFullHttpMessage fullHttpMsg && !fullHttpMsg.Content.IsReadable(); WriteHeaders(ctx, encoder, _currentStreamId, httpMsg.Headers, http2Headers, endStream, promiseAggregator); } if (!endStream && contentMsg is object) { var isLastContent = false; HttpHeaders trailers = EmptyHttpHeaders.Default; IHttp2Headers http2Trailers = EmptyHttp2Headers.Instance; if (msg is ILastHttpContent lastContentMsg) { isLastContent = true; // Convert any trailing headers. trailers = lastContentMsg.TrailingHeaders; http2Trailers = HttpConversionUtil.ToHttp2Headers(trailers, _validateHeaders); } // Write the data var content = contentMsg.Content; endStream = isLastContent && trailers.IsEmpty; _ = encoder.WriteDataAsync(ctx, _currentStreamId, content, 0, endStream, promiseAggregator.NewPromise()); release = false; if (!trailers.IsEmpty) { // Write trailing headers. WriteHeaders(ctx, encoder, _currentStreamId, trailers, http2Trailers, true, promiseAggregator); } } } catch (Exception t) { OnError(ctx, true, t); promiseAggregator.SetException(t); } finally { if (release) { _ = ReferenceCountUtil.Release(msg); } _ = promiseAggregator.DoneAllocatingPromises(); } }
static void AssertNotNullAndRelease(object msg) { Assert.NotNull(msg); ReferenceCountUtil.Release(msg); }
public void Fail(Exception error) { ReferenceCountUtil.Release(this.Message); this.promise.TrySetException(error); }
/// <inheritdoc /> public override void Write(IChannelHandlerContext ctx, object msg, IPromise promise) { ThreadLocalObjectList output = null; try { if (AcceptOutboundMessage(msg)) { output = ThreadLocalObjectList.NewInstance(); var cast = (T)msg; try { Encode(ctx, cast, output); } finally { _ = ReferenceCountUtil.Release(cast); } if (0u >= (uint)output.Count) { CThrowHelper.ThrowEncoderException_MustProduceAtLeastOneMsg(GetType()); } } else { _ = ctx.WriteAsync(msg, promise); } } catch (EncoderException) { throw; } catch (Exception ex) { CThrowHelper.ThrowEncoderException(ex); // todo: we don't have a stack on EncoderException but it's present on inner exception. } finally { if (output is object) { try { int lastItemIndex = output.Count - 1; if (0u >= (uint)lastItemIndex) { _ = ctx.WriteAsync(output[0], promise); } else if (lastItemIndex > 0) { // Check if we can use a voidPromise for our extra writes to reduce GC-Pressure // See https://github.com/netty/netty/issues/2525 if (promise == ctx.VoidPromise()) { WriteVoidPromise(ctx, output); } else { WritePromiseCombiner(ctx, output, promise); } } } finally { output.Return(); } } } }