void FinishRead(ReadOperation operation) { NativeChannel ch = this.Channel; IChannelPipeline pipeline = ch.Pipeline; IRecvByteBufAllocatorHandle allocHandle = this.RecvBufAllocHandle; IByteBuffer buffer = operation.Buffer; allocHandle.LastBytesRead = operation.Status; if (allocHandle.LastBytesRead <= 0) { // nothing was read -> release the buffer. buffer.SafeRelease(); } else { buffer.SetWriterIndex(buffer.WriterIndex + operation.Status); pipeline.FireChannelRead(buffer); } allocHandle.IncMessagesRead(1); allocHandle.ReadComplete(); pipeline.FireChannelReadComplete(); if (operation.Error != null) { pipeline.FireExceptionCaught(operation.Error); } if (operation.Error != null || operation.EndOfStream) { ch.DoClose(); } }
protected override async void DoBeginRead() { IByteBuffer byteBuffer = null; IRecvByteBufAllocatorHandle allocHandle = null; try { if (!this.Open || this.ReadPending) { return; } this.ReadPending = true; IByteBufferAllocator allocator = this.Configuration.Allocator; allocHandle = this.Configuration.RecvByteBufAllocator.NewHandle(); allocHandle.Reset(this.Configuration); do { byteBuffer = allocHandle.Allocate(allocator); var data = new byte[byteBuffer.Capacity]; IBuffer buffer = data.AsBuffer(); IBuffer completion = await this.streamSocket.InputStream.ReadAsync(buffer, (uint)byteBuffer.WritableBytes, InputStreamOptions.Partial); allocHandle.LastBytesRead = (int)completion.Length; if (allocHandle.LastBytesRead > 0) { byteBuffer.WriteBytes(data, 0, (int)completion.Length); } else { // nothing was read -> release the buffer. byteBuffer.Release(); byteBuffer = null; break; } this.Pipeline.FireChannelRead(byteBuffer); allocHandle.IncMessagesRead(1); }while (allocHandle.ContinueReading()); allocHandle.ReadComplete(); this.ReadPending = false; this.Pipeline.FireChannelReadComplete(); } catch (Exception e) { // Since this method returns void, all exceptions must be handled here. byteBuffer?.Release(); allocHandle?.ReadComplete(); this.ReadPending = false; this.Pipeline.FireChannelReadComplete(); this.Pipeline.FireExceptionCaught(e); if (this.Active) { await this.CloseAsync(); } } }
protected override async void DoBeginRead() { IByteBuffer byteBuffer = null; IRecvByteBufAllocatorHandle allocHandle = null; bool close = false; try { if (!Open || ReadPending) { return; } ReadPending = true; IByteBufferAllocator allocator = Configuration.Allocator; allocHandle = Configuration.RecvByteBufAllocator.NewHandle(); allocHandle.Reset(Configuration); do { byteBuffer = allocHandle.Allocate(allocator); allocHandle.LastBytesRead = await DoReadBytes(byteBuffer).ConfigureAwait(false); if (allocHandle.LastBytesRead <= 0) { // nothing was read -> release the buffer. byteBuffer.Release(); byteBuffer = null; close = allocHandle.LastBytesRead < 0; break; } Pipeline.FireChannelRead(byteBuffer); allocHandle.IncMessagesRead(1); }while (allocHandle.ContinueReading()); allocHandle.ReadComplete(); ReadPending = false; Pipeline.FireChannelReadComplete(); } catch (Exception e) when(!e.IsFatal()) { // Since this method returns void, all exceptions must be handled here. byteBuffer?.Release(); allocHandle?.ReadComplete(); ReadPending = false; Pipeline.FireChannelReadComplete(); Pipeline.FireExceptionCaught(e); close = true; } if (close) { if (Active) { await HandleCloseAsync().ConfigureAwait(false); } } }
protected override void ScheduleSocketRead() { try { SocketChannelAsyncOperation operation = this.ReadOperation; operation.RemoteEndPoint = this.anyRemoteEndPoint; IRecvByteBufAllocatorHandle handle = this.Unsafe.RecvBufAllocHandle; IByteBuffer buffer = handle.Allocate(this.config.Allocator); handle.AttemptedBytesRead = buffer.WritableBytes; operation.UserToken = buffer; ArraySegment <byte> bytes = buffer.GetIoBuffer(0, buffer.WritableBytes); operation.SetBuffer(bytes.Array, bytes.Offset, bytes.Count); bool pending; #if NETSTANDARD1_3 pending = this.Socket.ReceiveFromAsync(operation); #else if (this.isConnected) { if (ExecutionContext.IsFlowSuppressed()) { pending = this.Socket.ReceiveAsync(operation); } else { using (ExecutionContext.SuppressFlow()) { pending = this.Socket.ReceiveAsync(operation); } } } else { if (ExecutionContext.IsFlowSuppressed()) { pending = this.Socket.ReceiveFromAsync(operation); } else { using (ExecutionContext.SuppressFlow()) { pending = this.Socket.ReceiveFromAsync(operation); } } } #endif if (!pending) { this.EventLoop.Execute(ReceiveFromCompletedSyncCallback, this.Unsafe, operation); } } catch (Exception e) { this.Pipeline.FireExceptionCaught(e); } }
public AdaptiveRecvByteBufAllocatorTest() { _config = new Mock <IChannelConfiguration>(); _config.SetupGet(x => x.IsAutoRead).Returns(true); AdaptiveRecvByteBufAllocator recvByteBufAllocator = new AdaptiveRecvByteBufAllocator(64, 512, 1024 * 1024 * 10); _handle = recvByteBufAllocator.NewHandle(); _handle.Reset(_config.Object); }
// Read callback from libuv thread void INativeUnsafe.FinishRead(ReadOperation operation) { var ch = (NativeChannel)this.channel; IChannelConfiguration config = ch.Configuration; IChannelPipeline pipeline = ch.Pipeline; OperationException error = operation.Error; bool close = error != null || operation.EndOfStream; IRecvByteBufAllocatorHandle allocHandle = this.RecvBufAllocHandle; allocHandle.Reset(config); IByteBuffer buffer = operation.Buffer; Debug.Assert(buffer != null); allocHandle.LastBytesRead = operation.Status; if (allocHandle.LastBytesRead <= 0) { // nothing was read -> release the buffer. buffer.Release(); } else { buffer.SetWriterIndex(buffer.WriterIndex + operation.Status); allocHandle.IncMessagesRead(1); ch.ReadPending = false; pipeline.FireChannelRead(buffer); } allocHandle.ReadComplete(); pipeline.FireChannelReadComplete(); if (close) { if (error != null) { pipeline.FireExceptionCaught(new ChannelException(error)); } this.CloseSafe(); } else { // If read is called from channel read or read complete // do not stop reading if (!ch.ReadPending && !config.AutoRead) { ch.DoStopRead(); } } }
private static void AllocRead(IRecvByteBufAllocatorHandle handle, IByteBufferAllocator alloc, int expectedBufferSize, int lastRead) { IByteBuffer buf = handle.Allocate(alloc); Assert.Equal(expectedBufferSize, buf.Capacity); handle.AttemptedBytesRead = expectedBufferSize; handle.LastBytesRead = lastRead; handle.IncMessagesRead(1); buf.Release(); }
ReadOperation INativeUnsafe.PrepareRead() { NativeChannel ch = this.Channel; IChannelConfiguration config = ch.Configuration; IByteBufferAllocator allocator = config.Allocator; IRecvByteBufAllocatorHandle allocHandle = this.RecvBufAllocHandle; allocHandle.Reset(config); IByteBuffer buffer = allocHandle.Allocate(allocator); allocHandle.AttemptedBytesRead = buffer.WritableBytes; return(new ReadOperation(this, buffer)); }
// Allocate callback from libuv thread uv_buf_t INativeUnsafe.PrepareRead(ReadOperation readOperation) { Debug.Assert(readOperation != null); var ch = (NativeChannel)this.channel; IChannelConfiguration config = ch.Configuration; IByteBufferAllocator allocator = config.Allocator; IRecvByteBufAllocatorHandle allocHandle = this.RecvBufAllocHandle; IByteBuffer buffer = allocHandle.Allocate(allocator); allocHandle.AttemptedBytesRead = buffer.WritableBytes; return(readOperation.GetBuffer(buffer)); }
void HandleReadException(IChannelPipeline pipeline, IByteBuffer byteBuf, Exception cause, bool close, IRecvByteBufAllocatorHandle allocHandle) { if (byteBuf != null) { if (byteBuf.IsReadable()) { this.Channel.ReadPending = false; pipeline.FireChannelRead(byteBuf); } else { byteBuf.Release(); } } allocHandle.ReadComplete(); pipeline.FireChannelReadComplete(); pipeline.FireExceptionCaught(cause); if (close || cause is SocketException) { this.CloseOnRead(); } }
void Accept(Tcp tcp) { var ch = (TcpServerChannel)this.channel; IChannelPipeline pipeline = ch.Pipeline; IRecvByteBufAllocatorHandle allocHandle = this.RecvBufAllocHandle; bool closed = false; Exception exception = null; try { var tcpChannel = new TcpChannel(ch, tcp); ch.Pipeline.FireChannelRead(tcpChannel); allocHandle.IncMessagesRead(1); } catch (ObjectDisposedException) { closed = true; } catch (Exception ex) { exception = ex; } allocHandle.ReadComplete(); pipeline.FireChannelReadComplete(); if (exception != null) { pipeline.FireExceptionCaught(exception); } if (closed && ch.Open) { this.CloseSafe(); } }
void Accept(Tcp tcp) { var ch = _channel; IChannelPipeline pipeline = ch.Pipeline; IRecvByteBufAllocatorHandle allocHandle = RecvBufAllocHandle; bool closed = false; Exception exception = null; try { var tcpChannel = ch._channelFactory.CreateChannel(ch, tcp); // ## 苦竹 修改 ## new TcpChannel(ch, tcp); _ = ch.Pipeline.FireChannelRead(tcpChannel); allocHandle.IncMessagesRead(1); } catch (ObjectDisposedException) { closed = true; } catch (Exception ex) { exception = ex; } allocHandle.ReadComplete(); _ = pipeline.FireChannelReadComplete(); if (exception is object) { _ = pipeline.FireExceptionCaught(exception); } if (closed && ch.Open) { CloseSafe(); } }
protected override int DoReadMessages(List <object> buf) { Contract.Requires(buf != null); SocketChannelAsyncOperation operation = this.ReadOperation; IByteBuffer data = (IByteBuffer)operation.UserToken; bool free = true; try { IRecvByteBufAllocatorHandle handle = this.Unsafe.RecvBufAllocHandle; int received = operation.BytesTransferred; if (received <= 0) { return(0); } handle.LastBytesRead = received; data.SetWriterIndex(data.WriterIndex + received); EndPoint remoteAddress = operation.RemoteEndPoint; buf.Add(new DatagramPacket(data, remoteAddress, this.LocalAddress)); free = false; return(1); } finally { if (free) { data.Release(); } operation.UserToken = null; } }
private static void AllocReadExpected(IRecvByteBufAllocatorHandle handle, IByteBufferAllocator alloc, int expectedSize) { AllocRead(handle, alloc, expectedSize, expectedSize); }
protected override async void DoBeginRead() { IByteBuffer byteBuffer = null; IRecvByteBufAllocatorHandle allocHandle = null; bool close = false; try { if (!this.Open || this.ReadPending) { return; } this.ReadPending = true; IByteBufferAllocator allocator = this.Configuration.Allocator; allocHandle = this.Configuration.RecvByteBufAllocator.NewHandle(); allocHandle.Reset(this.Configuration); do { byteBuffer = allocHandle.Allocate(allocator); allocHandle.LastBytesRead = await this.DoReadBytes(byteBuffer); if (allocHandle.LastBytesRead <= 0) { // nothing was read -> release the buffer. byteBuffer.Release(); byteBuffer = null; close = allocHandle.LastBytesRead < 0; break; } this.Pipeline.FireChannelRead(byteBuffer); allocHandle.IncMessagesRead(1); }while (allocHandle.ContinueReading()); allocHandle.ReadComplete(); this.ReadPending = false; this.Pipeline.FireChannelReadComplete(); } catch (Exception e) when(!e.IsFatal()) { Events.ReadException(this.correlationId, e); // Since this method returns void, all exceptions must be handled here. byteBuffer.SafeRelease(); allocHandle?.ReadComplete(); this.ReadPending = false; // WebSocket should change its state when an exception is thrown, // but it doesn't (see https://github.com/dotnet/corefx/issues/26219) // so we'll abort the connection here. this.Abort(); this.Pipeline.FireChannelReadComplete(); this.Pipeline.FireExceptionCaught(e); close = true; } if (close) { if (this.Active) { await this.HandleCloseAsync(); } } }
public override void FinishRead(SocketChannelAsyncOperation operation) { Contract.Assert(this.channel.EventLoop.InEventLoop); AbstractSocketMessageChannel ch = this.Channel; ch.ResetState(StateFlags.ReadScheduled); 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.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 && (ch.ReadPending || config.AutoRead)) { ch.DoBeginRead(); } } }
//new AbstractSocketMessageChannel Channel => (AbstractSocketMessageChannel)this.channel; public override void FinishRead(SocketChannelAsyncOperation <TChannel, TUnsafe> operation) { Debug.Assert(_channel.EventLoop.InEventLoop); var ch = _channel; if (0u >= (uint)(ch.ResetState(StateFlags.ReadScheduled) & StateFlags.Active)) { return; // read was signaled as a result of channel closure } IChannelConfiguration config = ch.Configuration; IChannelPipeline pipeline = ch.Pipeline; IRecvByteBufAllocatorHandle allocHandle = ch.Unsafe.RecvBufAllocHandle; allocHandle.Reset(config); bool closed = false; Exception exception = null; try { try { do { int localRead = ch.DoReadMessages(_readBuf); uint uLocalRead = (uint)localRead; if (0u >= uLocalRead) { break; } if (uLocalRead > SharedConstants.TooBigOrNegative) // localRead < 0 { closed = true; break; } allocHandle.IncMessagesRead(localRead); }while (allocHandle.ContinueReading()); } catch (Exception t) { exception = t; } int size = _readBuf.Count; for (int i = 0; i < size; i++) { ch.ReadPending = false; _ = pipeline.FireChannelRead(_readBuf[i]); } _readBuf.Clear(); allocHandle.ReadComplete(); _ = pipeline.FireChannelReadComplete(); if (exception is object) { if (exception is SocketException asSocketException && 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) { Close(VoidPromise()); } } } 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(); } } }
public override void FinishRead(SocketChannelAsyncOperation operation) { Contract.Assert(this.channel.EventLoop.InEventLoop); TcpServerSocketChannel 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 { Socket connectedSocket = null; try { connectedSocket = operation.AcceptSocket; operation.AcceptSocket = null; operation.Validate(); var message = this.PrepareChannel(connectedSocket); connectedSocket = null; ch.ReadPending = false; pipeline.FireChannelRead(message); allocHandle.IncMessagesRead(1); if (!config.AutoRead && !ch.ReadPending) { // ChannelConfig.setAutoRead(false) was called in the meantime. // Completed Accept has to be processed though. return; } while (allocHandle.ContinueReading()) { connectedSocket = ch.Socket.Accept(); message = this.PrepareChannel(connectedSocket); connectedSocket = null; ch.ReadPending = false; pipeline.FireChannelRead(message); allocHandle.IncMessagesRead(1); } } catch (SocketException ex) when(ex.SocketErrorCode == SocketError.OperationAborted || ex.SocketErrorCode == SocketError.InvalidArgument) { closed = true; } catch (SocketException ex) when(ex.SocketErrorCode == SocketError.WouldBlock) { } catch (SocketException ex) { // socket exceptions here are internal to channel's operation and should not go through the pipeline // especially as they have no effect on overall channel's operation Logger.Info("Exception on accept.", ex); } catch (ObjectDisposedException) { closed = true; } catch (Exception ex) { exception = ex; } allocHandle.ReadComplete(); pipeline.FireChannelReadComplete(); if (exception != null) { // ServerChannel should not be closed even on SocketException because it can often continue // accepting incoming connections. (e.g. too many open files) pipeline.FireExceptionCaught(exception); } if (closed && ch.Open) { this.CloseSafe(); } } finally { // Check if there is a readPending which was not processed yet. if (!closed && (ch.ReadPending || config.AutoRead)) { ch.DoBeginRead(); } } }
public override void FinishRead(SocketChannelAsyncOperation operation) { AbstractSocketByteChannel 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; IByteBufferAllocator allocator = config.Allocator; IRecvByteBufAllocatorHandle allocHandle = this.RecvBufAllocHandle; allocHandle.Reset(config); IByteBuffer byteBuf = null; bool close = false; try { operation.Validate(); do { byteBuf = allocHandle.Allocate(allocator); //int writable = byteBuf.WritableBytes; allocHandle.LastBytesRead = ch.DoReadBytes(byteBuf); if (allocHandle.LastBytesRead <= 0) { // nothing was read -> release the buffer. byteBuf.Release(); byteBuf = null; close = allocHandle.LastBytesRead < 0; break; } allocHandle.IncMessagesRead(1); this.Channel.ReadPending = false; pipeline.FireChannelRead(byteBuf); byteBuf = null; }while (allocHandle.ContinueReading()); allocHandle.ReadComplete(); pipeline.FireChannelReadComplete(); if (close) { this.CloseOnRead(); } } catch (Exception t) { this.HandleReadException(pipeline, byteBuf, t, close, allocHandle); } 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() input channelRead(...) method // /// The user called Channel.read() or ChannelHandlerContext.read() input channelReadComplete(...) method // // See https://github.com/netty/netty/issues/2254 if (!close && (ch.ReadPending || config.AutoRead)) { ch.DoBeginRead(); } } }
public override void FinishRead(SocketChannelAsyncOperation operation) { AbstractSocketByteChannel ch = this.Channel; ch.ResetState(StateFlags.ReadScheduled); IChannelConfiguration config = ch.Configuration; IChannelPipeline pipeline = ch.Pipeline; IByteBufferAllocator allocator = config.Allocator; int maxMessagesPerRead = config.MaxMessagesPerRead; IRecvByteBufAllocatorHandle allocHandle = this.RecvBufAllocHandle; IByteBuffer byteBuf = null; int messages = 0; bool close = false; try { operation.Validate(); int totalReadAmount = 0; bool readPendingReset = false; do { byteBuf = allocHandle.Allocate(allocator); int writable = byteBuf.WritableBytes; int localReadAmount = ch.DoReadBytes(byteBuf); if (localReadAmount <= 0) { // not was read release the buffer byteBuf.Release(); byteBuf = null; close = localReadAmount < 0; break; } if (!readPendingReset) { readPendingReset = true; ch.ReadPending = false; } pipeline.FireChannelRead(byteBuf); byteBuf = null; if (totalReadAmount >= int.MaxValue - localReadAmount) { // Avoid overflow. totalReadAmount = int.MaxValue; break; } totalReadAmount += localReadAmount; // stop reading if (!config.AutoRead) { break; } if (localReadAmount < writable) { // Read less than what the buffer can hold, // which might mean we drained the recv buffer completely. break; } }while (++messages < maxMessagesPerRead); pipeline.FireChannelReadComplete(); allocHandle.Record(totalReadAmount); if (close) { this.CloseOnRead(); close = false; } } catch (Exception t) { this.HandleReadException(pipeline, byteBuf, t, close); } 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() input channelRead(...) method // /// The user called Channel.read() or ChannelHandlerContext.read() input channelReadComplete(...) method // // See https://github.com/netty/netty/issues/2254 if (!close && (ch.ReadPending || config.AutoRead)) { ch.DoBeginRead(); } } }
public override void FinishRead(SocketChannelAsyncOperation <TServerChannel, TcpServerSocketChannelUnsafe> operation) { Debug.Assert(_channel.EventLoop.InEventLoop); var ch = _channel; if (0u >= (uint)(ch.ResetState(StateFlags.ReadScheduled) & StateFlags.Active)) { return; // read was signaled as a result of channel closure } IChannelConfiguration config = ch.Configuration; IChannelPipeline pipeline = ch.Pipeline; IRecvByteBufAllocatorHandle allocHandle = ch.Unsafe.RecvBufAllocHandle; allocHandle.Reset(config); var closed = false; var aborted = false; Exception exception = null; try { Socket connectedSocket = null; try { connectedSocket = operation.AcceptSocket; operation.AcceptSocket = null; operation.Validate(); var message = PrepareChannel(connectedSocket); connectedSocket = null; ch.ReadPending = false; _ = pipeline.FireChannelRead(message); allocHandle.IncMessagesRead(1); if (!config.IsAutoRead && !ch.ReadPending) { // ChannelConfig.setAutoRead(false) was called in the meantime. // Completed Accept has to be processed though. return; } while (allocHandle.ContinueReading()) { connectedSocket = ch.Socket.Accept(); message = PrepareChannel(connectedSocket); connectedSocket = null; ch.ReadPending = false; _ = pipeline.FireChannelRead(message); allocHandle.IncMessagesRead(1); } } catch (SocketException ex) when(ex.SocketErrorCode.IsSocketAbortError()) { ch.Socket.SafeClose(); // Unbind...... exception = ex; aborted = true; } catch (SocketException ex) when(ex.SocketErrorCode == SocketError.WouldBlock) { } catch (SocketException ex) { // socket exceptions here are internal to channel's operation and should not go through the pipeline // especially as they have no effect on overall channel's operation if (Logger.InfoEnabled) { Logger.ExceptionOnAccept(ex); } } catch (ObjectDisposedException) { closed = true; } catch (Exception ex) { exception = ex; } allocHandle.ReadComplete(); _ = pipeline.FireChannelReadComplete(); if (exception is object) { // ServerChannel should not be closed even on SocketException because it can often continue // accepting incoming connections. (e.g. too many open files) _ = pipeline.FireExceptionCaught(exception); } if (ch.IsOpen) { if (closed) { Close(VoidPromise()); } else if (aborted) { ch.CloseSafe(); } } } finally { // Check if there is a readPending which was not processed yet. if (!closed && (ch.ReadPending || config.IsAutoRead)) { ch.DoBeginRead(); } } }
/// <summary> /// Creates a new predictor that always returns the same prediction of /// the specified buffer size. /// </summary> public FixedRecvByteBufAllocator(int bufferSize) { Contract.Requires(bufferSize > 0); this.handle = new HandleImpl(bufferSize); }
// Read callback from libuv thread void INativeUnsafe.FinishRead(ReadOperation operation) { var ch = _channel; IChannelConfiguration config = ch.Configuration; IChannelPipeline pipeline = ch.Pipeline; OperationException error = operation.Error; bool close = error is object || operation.EndOfStream; IRecvByteBufAllocatorHandle allocHandle = RecvBufAllocHandle; allocHandle.Reset(config); IByteBuffer buffer = operation.Buffer; Debug.Assert(buffer is object); allocHandle.LastBytesRead = operation.Status; if (allocHandle.LastBytesRead <= 0) { // nothing was read -> release the buffer. _ = buffer.Release(); close = allocHandle.LastBytesRead < 0; if (close) { // There is nothing left to read as we received an EOF. ch.ReadPending = false; } } else { _ = buffer.SetWriterIndex(buffer.WriterIndex + operation.Status); allocHandle.IncMessagesRead(1); ch.ReadPending = false; _ = pipeline.FireChannelRead(buffer); } allocHandle.ReadComplete(); _ = pipeline.FireChannelReadComplete(); if (close) { if (error is object) { _ = pipeline.FireExceptionCaught(ThrowHelper.GetChannelException(error)); } if (ch.Open) { Close(VoidPromise()); } // ## 苦竹 修改 this.CloseSafe(); ## } else { // If read is called from channel read or read complete // do not stop reading if (!ch.ReadPending && !config.AutoRead) { ch.DoStopRead(); } } }
public override void FinishRead(SocketChannelAsyncOperation <TChannel, TUnsafe> operation) { var ch = _channel; if (0u >= (uint)(ch.ResetState(StateFlags.ReadScheduled) & StateFlags.Active)) { return; // read was signaled as a result of channel closure } IChannelConfiguration config = ch.Configuration; if (ch.ShouldBreakReadReady(config)) { ch.ClearReadPending(); return; } IChannelPipeline pipeline = ch.Pipeline; IByteBufferAllocator allocator = config.Allocator; IRecvByteBufAllocatorHandle allocHandle = RecvBufAllocHandle; allocHandle.Reset(config); IByteBuffer byteBuf = null; bool close = false; try { operation.Validate(); do { byteBuf = allocHandle.Allocate(allocator); allocHandle.LastBytesRead = ch.DoReadBytes(byteBuf); if ((uint)(allocHandle.LastBytesRead - 1) > SharedConstants.TooBigOrNegative) // <= 0 { // nothing was read -> release the buffer. _ = byteBuf.Release(); byteBuf = null; close = (uint)allocHandle.LastBytesRead > SharedConstants.TooBigOrNegative; // < 0 if (close) { // There is nothing left to read as we received an EOF. ch.ReadPending = false; } break; } allocHandle.IncMessagesRead(1); ch.ReadPending = false; _ = pipeline.FireChannelRead(byteBuf); byteBuf = null; }while (allocHandle.ContinueReading()); allocHandle.ReadComplete(); _ = pipeline.FireChannelReadComplete(); if (close) { CloseOnRead(); } } catch (Exception t) { HandleReadException(pipeline, byteBuf, t, close, allocHandle); } 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() input channelRead(...) method // /// The user called Channel.read() or ChannelHandlerContext.read() input channelReadComplete(...) method // // See https://github.com/netty/netty/issues/2254 if (!close && (ch.ReadPending || config.IsAutoRead)) { ch.DoBeginRead(); } } }
public override void FinishRead(SocketChannelAsyncOperation operation) { Contract.Assert(this.channel.EventLoop.InEventLoop); TcpServerSocketChannel 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 { Socket connectedSocket = null; try { connectedSocket = operation.AcceptSocket; operation.Validate(); operation.AcceptSocket = null; var message = new TcpSocketChannel(ch, connectedSocket, true); ch.ReadPending = false; pipeline.FireChannelRead(message); allocHandle.IncMessagesRead(1); if (!config.AutoRead && !ch.ReadPending) { // ChannelConfig.setAutoRead(false) was called in the meantime. // Completed Accept has to be processed though. return; } while (allocHandle.ContinueReading()) { connectedSocket = null; connectedSocket = ch.Socket.Accept(); message = new TcpSocketChannel(ch, connectedSocket, true); ch.ReadPending = false; pipeline.FireChannelRead(message); allocHandle.IncMessagesRead(1); } } catch (ObjectDisposedException) { closed = true; } catch (Exception ex) { var asSocketException = ex as SocketException; if (asSocketException == null || asSocketException.SocketErrorCode != SocketError.WouldBlock) { Logger.Warn("Failed to create a new channel from an accepted socket.", ex); if (connectedSocket != null) { try { connectedSocket.Dispose(); } catch (Exception ex2) { Logger.Warn("Failed to close a socket.", ex2); } } exception = ex; } } allocHandle.ReadComplete(); pipeline.FireChannelReadComplete(); if (exception != null) { // ServerChannel should not be closed even on SocketException because it can often continue // accepting incoming connections. (e.g. too many open files) pipeline.FireExceptionCaught(exception); } if (closed) { if (ch.Open) { this.CloseAsync(); } } } finally { // Check if there is a readPending which was not processed yet. if (!closed && (ch.ReadPending || config.AutoRead)) { ch.DoBeginRead(); } } }