Ejemplo n.º 1
0
            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();
                }
            }
Ejemplo n.º 2
0
        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);
                }
            }
        }
Ejemplo n.º 4
0
        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();
        }
Ejemplo n.º 8
0
            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();
     }
 }
Ejemplo n.º 11
0
 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();
     }
 }
Ejemplo n.º 12
0
            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();
                }
            }
Ejemplo n.º 13
0
            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();
                }
            }
Ejemplo n.º 14
0
        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);
 }
Ejemplo n.º 16
0
        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();
                }
            }
        }
Ejemplo n.º 17
0
            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();
                    }
                }
            }
Ejemplo n.º 18
0
            //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();
                    }
                }
            }
Ejemplo n.º 19
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.º 20
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();

                    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.º 21
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();
                    }
                }
            }
            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.º 23
0
        /// <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);
        }
Ejemplo n.º 24
0
            // 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();
                    }
                }
            }
Ejemplo n.º 25
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.º 26
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();
                    }
                }
            }