Ejemplo n.º 1
0
            public void FinishWrite(SocketChannelAsyncOperation <TChannel, TUnsafe> operation)
            {
                var  ch = _channel;
                bool resetWritePending = ch.TryResetState(StateFlags.WriteScheduled);

                Debug.Assert(resetWritePending);

                ChannelOutboundBuffer input = OutboundBuffer;

                try
                {
                    operation.Validate();
                    int sent = operation.BytesTransferred;
                    ch.ResetWriteOperation();
                    if (sent > 0)
                    {
                        input.RemoveBytes(sent);
                    }
                }
                catch (Exception ex)
                {
                    _ = ch.Pipeline.FireExceptionCaught(ex);
                    Close(VoidPromise(), ThrowHelper.GetClosedChannelException_FailedToWrite(ex), WriteClosedChannelException, false);
                }

                // Double check if there's no pending flush
                // See https://github.com/Azure/DotNetty/issues/218
                Flush0(); // todo: does it make sense now that we've actually written out everything that was flushed previously? concurrent flush handling?
            }
Ejemplo n.º 2
0
            public void FinishWrite(SocketChannelAsyncOperation operation)
            {
                ChannelOutboundBuffer input = this.OutboundBuffer;

                try
                {
                    operation.Validate();
                    int sent = operation.BytesTransferred;
                    this.Channel.ResetWriteOperation();
                    if (sent > 0)
                    {
                        object msg    = input.Current;
                        var    buffer = msg as IByteBuffer;
                        if (buffer != null)
                        {
                            buffer.SetWriterIndex(buffer.WriterIndex + sent);
                        }
                        // todo: FileRegion support
                    }
                }
                catch (Exception ex)
                {
                    input.FailFlushed(ex, true);
                    throw;
                }

                // directly call super.flush0() to force a flush now
                base.Flush0();
            }
Ejemplo n.º 3
0
            public void FinishWrite(SocketChannelAsyncOperation operation)
            {
                bool resetWritePending = this.Channel.TryResetState(StateFlags.WriteScheduled);

                Contract.Assert(resetWritePending);

                ChannelOutboundBuffer input = this.OutboundBuffer;

                try
                {
                    operation.Validate();
                    int sent = operation.BytesTransferred;
                    this.Channel.ResetWriteOperation();
                    if (sent > 0)
                    {
                        input.RemoveBytes(sent);
                    }
                }
                catch (Exception ex)
                {
                    input.FailFlushed(ex, true);
                    throw;
                }

                // directly call base.Flush0() to force a flush now
                base.Flush0(); // todo: does it make sense now that we've actually written out everything that was flushed previously? concurrent flush handling?
            }
            public void FinishWrite(SocketChannelAsyncOperation operation)
            {
                bool resetWritePending = this.Channel.TryResetState(StateFlags.WriteScheduled);

                Contract.Assert(resetWritePending);

                ChannelOutboundBuffer input = this.OutboundBuffer;

                try
                {
                    operation.Validate();
                    int sent = operation.BytesTransferred;
                    this.Channel.ResetWriteOperation();
                    if (sent > 0)
                    {
                        input.RemoveBytes(sent);
                    }
                }
                catch (Exception ex)
                {
                    input.FailFlushed(ex, true);
                    throw;
                }

                // Double check if there's no pending flush
                // See https://github.com/Azure/DotNetty/issues/218
                this.Flush0(); // todo: does it make sense now that we've actually written out everything that was flushed previously? concurrent flush handling?
            }
Ejemplo n.º 5
0
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     try
     {
         operation.Validate();
     }
     finally
     {
         operation.RemoteEndPoint = null; // cleanup after connect
         operation.Dispose();
     }
 }
Ejemplo n.º 6
0
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     try
     {
         operation.Validate();
     }
     finally
     {
         operation.Dispose();
     }
     this.OnConnected();
 }
Ejemplo n.º 7
0
            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();
                    }
                }
            }
Ejemplo n.º 8
0
            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();

                    Console.WriteLine($"新消息粘包处理,{this.GetType().FullName}");
                    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();
                    }
                }
            }
Ejemplo n.º 9
0
            public void FinishWrite(SocketChannelAsyncOperation operation)
            {
                bool resetWritePending = this.Channel.ResetState(StateFlags.WriteScheduled);

                Contract.Assert(resetWritePending);

                ChannelOutboundBuffer input = this.OutboundBuffer;
                try
                {
                    operation.Validate();
                    int sent = operation.BytesTransferred;
                    this.Channel.ResetWriteOperation();
                    if (sent > 0)
                    {
                        input.RemoveBytes(sent);
                    }
                }
                catch (Exception ex)
                {
                    input.FailFlushed(ex, true);
                    throw;
                }

                // directly call base.Flush0() to force a flush now
                base.Flush0(); // todo: does it make sense now that we've actually written out everything that was flushed previously? concurrent flush handling?
            }
            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;
                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();
                    }
                }
            }
Ejemplo n.º 11
0
            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();
                    }
                }
            }
Ejemplo n.º 12
0
            public void FinishWrite(SocketChannelAsyncOperation operation)
            {
                ChannelOutboundBuffer input = this.OutboundBuffer;
                try
                {
                    operation.Validate();
                    int sent = operation.BytesTransferred;
                    this.Channel.ResetWriteOperation();
                    if (sent > 0)
                    {
                        object msg = input.Current;
                        var buffer = msg as IByteBuffer;
                        if (buffer != null)
                        {
                            buffer.SetWriterIndex(buffer.WriterIndex + sent);
                        }
                        // todo: FileRegion support
                    }
                }
                catch (Exception ex)
                {
                    input.FailFlushed(ex, true);
                    throw;
                }

                // directly call super.flush0() to force a flush now
                base.Flush0();
            }
Ejemplo n.º 13
0
            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();
                    }
                }
            }
Ejemplo n.º 14
0
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     try
     {
         operation.Validate();
     }
     finally
     {
         operation.Dispose();
     }
     this.OnConnected();
 }
            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();
                    }
                }
            }
Ejemplo n.º 16
0
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     try
     {
         operation.Validate();
     }
     finally
     {
         operation.RemoteEndPoint = null; // cleanup after connect
         operation.Dispose();
     }
 }
Ejemplo n.º 17
0
            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();
                    }
                }
            }
Ejemplo n.º 18
0
            public override void FinishRead(SocketChannelAsyncOperation operation)
            {
                Contract.Requires(this.channel.EventLoop.InEventLoop);

                TcpServerSocketChannel ch = this.Channel;
                ch.ResetState(StateFlags.ReadScheduled);
                IChannelConfiguration config = ch.Configuration;

                int maxMessagesPerRead = config.MaxMessagesPerRead;
                IChannelPipeline pipeline = ch.Pipeline;
                bool closed = false;
                Exception exception = null;

                int messageCount = 0;

                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);
                        messageCount++;

                        if (!config.AutoRead && !ch.ReadPending)
                        {
                            // ChannelConfig.setAutoRead(false) was called in the meantime.
                            // Completed Accept has to be processed though.
                            return;
                        }

                        while (messageCount < maxMessagesPerRead)
                        {
                            connectedSocket = null;
                            connectedSocket = ch.Socket.Accept();
                            message = new TcpSocketChannel(ch, connectedSocket, true);
                            pipeline.FireChannelRead(message);

                            // stop reading and remove op
                            if (!config.AutoRead)
                            {
                                break;
                            }
                            messageCount++;
                        }
                    }
                    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.Close();
                                }
                                catch (Exception ex2)
                                {
                                    Logger.Warn("Failed to close a socket.", ex2);
                                }
                            }
                            exception = ex;
                        }
                    }

                    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 && (config.AutoRead || ch.ReadPending))
                    {
                        ch.DoBeginRead();
                    }
                }
            }
            public override void FinishRead(SocketChannelAsyncOperation operation)
            {
                AbstractSocketByteChannel 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;
                }

                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 && (config.AutoRead || ch.ReadPending))
                    {
                        ch.DoBeginRead();
                    }
                }
            }
Ejemplo n.º 20
0
            public override void FinishRead(SocketChannelAsyncOperation operation)
            {
                Contract.Requires(this.channel.EventLoop.InEventLoop);

                TcpServerSocketChannel ch = this.Channel;

                ch.ResetState(StateFlags.ReadScheduled);
                IChannelConfiguration config = ch.Configuration;

                int maxMessagesPerRead     = config.MaxMessagesPerRead;
                IChannelPipeline pipeline  = ch.Pipeline;
                bool             closed    = false;
                Exception        exception = null;

                int messageCount = 0;

                try
                {
                    Socket connectedSocket = null;
                    try
                    {
                        connectedSocket = operation.AcceptSocket;
                        operation.Validate();
                        operation.AcceptSocket = null;

                        var message = new TcpSocketChannel(ch, connectedSocket);
                        ch.ReadPending = false;
                        pipeline.FireChannelRead(message);
                        messageCount++;

                        if (!config.AutoRead && !ch.ReadPending)
                        {
                            // ChannelConfig.setAutoRead(false) was called in the meantime.
                            // Completed Accept has to be processed though.
                            return;
                        }

                        while (messageCount < maxMessagesPerRead)
                        {
                            connectedSocket = null;
                            connectedSocket = ch.Socket.Accept();
                            message         = new TcpSocketChannel(ch, connectedSocket);
                            pipeline.FireChannelRead(message);

                            // stop reading and remove op
                            if (!config.AutoRead)
                            {
                                break;
                            }
                            messageCount++;
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        closed = true;
                    }
                    catch (Exception ex)
                    {
                        var asSocketException = ex as SocketException;
                        if (asSocketException == null || asSocketException.SocketErrorCode != SocketError.WouldBlock)
                        {
                            ChannelEventSource.Log.Warning("Failed to create a new channel from an accepted socket.", ex);
                            if (connectedSocket != null)
                            {
                                try
                                {
                                    connectedSocket.Close();
                                }
                                catch (Exception ex2)
                                {
                                    ChannelEventSource.Log.Warning("Failed to close a socket.", ex2);
                                }
                            }
                            exception = ex;
                        }
                    }

                    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 && (config.AutoRead || ch.ReadPending))
                    {
                        ch.DoBeginRead();
                    }
                }
            }