public override void FinishRead(SocketChannelAsyncOperation operation) { Contract.Requires(this.channel.EventLoop.InEventLoop); AbstractSocketMessageChannel ch = this.Channel; ch.ResetState(StateFlags.ReadScheduled); IChannelConfiguration config = ch.Configuration; if (!config.AutoRead && !ch.ReadPending) { // ChannelConfig.setAutoRead(false) was called in the meantime //removeReadOp(); -- noop with IOCP, just don't schedule receive again return; } int maxMessagesPerRead = config.MaxMessagesPerRead; IChannelPipeline pipeline = ch.Pipeline; bool closed = false; Exception exception = null; try { try { while (true) { int localRead = ch.DoReadMessages(this.readBuf); if (localRead == 0) { break; } if (localRead < 0) { closed = true; break; } // stop reading and remove op if (!config.AutoRead) { break; } if (this.readBuf.Count >= maxMessagesPerRead) { break; } } } catch (Exception t) { exception = t; } ch.ReadPending = false; int size = this.readBuf.Count; for (int i = 0; i < size; i++) { pipeline.FireChannelRead(this.readBuf[i]); } this.readBuf.Clear(); pipeline.FireChannelReadComplete(); if (exception != null) { var asSocketException = exception as SocketException; if (asSocketException != null && asSocketException.SocketErrorCode != SocketError.TryAgain) // todo: other conditions for not closing message-based socket? { // ServerChannel should not be closed even on SocketException because it can often continue // accepting incoming connections. (e.g. too many open files) closed = !(ch is IServerChannel); } pipeline.FireExceptionCaught(exception); } if (closed) { if (ch.Open) { this.CloseAsync(); } } } finally { // Check if there is a readPending which was not processed yet. // This could be for two reasons: // /// The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method // /// The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method // // See https://github.com/netty/netty/issues/2254 if (!closed && (config.AutoRead || ch.ReadPending)) { ch.DoBeginRead(); } } }
public override void FinishRead(SocketChannelAsyncOperation operation) { Contract.Assert(this.channel.EventLoop.InEventLoop); AbstractSocketMessageChannel ch = this.Channel; if ((ch.ResetState(StateFlags.ReadScheduled) & StateFlags.Active) == 0) { return; // read was signaled as a result of channel closure } IChannelConfiguration config = ch.Configuration; IChannelPipeline pipeline = ch.Pipeline; IRecvByteBufAllocatorHandle allocHandle = this.Channel.Unsafe.RecvBufAllocHandle; allocHandle.Reset(config); bool closed = false; Exception exception = null; try { try { do { int localRead = ch.DoReadMessages(this.readBuf); if (localRead == 0) { break; } if (localRead < 0) { closed = true; break; } allocHandle.IncMessagesRead(localRead); }while (allocHandle.ContinueReading()); } catch (Exception t) { exception = t; } int size = this.readBuf.Count; for (int i = 0; i < size; i++) { ch.ReadPending = false; pipeline.FireChannelRead(this.readBuf[i]); } this.readBuf.Clear(); allocHandle.ReadComplete(); pipeline.FireChannelReadComplete(); if (exception != null) { var asSocketException = exception as SocketException; if (asSocketException != null && asSocketException.SocketErrorCode != SocketError.TryAgain) // todo: other conditions for not closing message-based socket? { // ServerChannel should not be closed even on SocketException because it can often continue // accepting incoming connections. (e.g. too many open files) closed = !(ch is IServerChannel); } pipeline.FireExceptionCaught(exception); } if (closed) { if (ch.Open) { this.CloseSafe(); } } } finally { // Check if there is a readPending which was not processed yet. // This could be for two reasons: // /// The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method // /// The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method // // See https://github.com/netty/netty/issues/2254 if (!closed && (ch.ReadPending || config.AutoRead)) { ch.DoBeginRead(); } } }