示例#1
0
        protected SocketChannelAsyncOperation PrepareWriteOperation(ArraySegment <byte> buffer)
        {
            SocketChannelAsyncOperation operation = this.WriteOperation;

            operation.SetBuffer(buffer.Array, buffer.Offset, buffer.Count);
            return(operation);
        }
示例#2
0
        protected SocketChannelAsyncOperation PrepareWriteOperation(IList <ArraySegment <byte> > buffers)
        {
            SocketChannelAsyncOperation operation = this.WriteOperation;

            operation.BufferList = buffers;
            return(operation);
        }
示例#3
0
        protected override void ScheduleSocketRead()
        {
            SocketChannelAsyncOperation operation = this.ReadOperation;
            bool pending;

#if NETSTANDARD1_3
            pending = this.Socket.ReceiveAsync(operation);
#else
            if (ExecutionContext.IsFlowSuppressed())
            {
                pending = this.Socket.ReceiveAsync(operation);
            }
            else
            {
                using (ExecutionContext.SuppressFlow())
                {
                    pending = this.Socket.ReceiveAsync(operation);
                }
            }
#endif
            if (!pending)
            {
                // todo: potential allocation / non-static field?
                this.EventLoop.Execute(ReadCompletedSyncCallback, this.Unsafe, operation);
            }
        }
示例#4
0
        protected override void DoClose()
        {
            TaskCompletionSource promise = this.connectPromise;

            if (promise != null)
            {
                // Use TrySetException() instead of SetException() to avoid the race against cancellation due to timeout.
                promise.TrySetException(new ClosedChannelException());
                this.connectPromise = null;
            }

            IScheduledTask cancellationTask = this.connectCancellationTask;

            if (cancellationTask != null)
            {
                cancellationTask.Cancel();
                this.connectCancellationTask = null;
            }

            SocketChannelAsyncOperation readOp = this.readOperation;

            if (readOp != null)
            {
                readOp.Dispose();
                this.readOperation = null;
            }

            SocketChannelAsyncOperation writeOp = this.writeOperation;

            if (writeOp != null)
            {
                writeOp.Dispose();
                this.writeOperation = null;
            }
        }
示例#5
0
        protected override bool DoConnect(EndPoint remoteAddress, EndPoint localAddress)
        {
            if (localAddress != null)
            {
                this.Socket.Bind(localAddress);
            }

            bool success = false;

            try
            {
                var eventPayload = new SocketChannelAsyncOperation(this, false);
                eventPayload.RemoteEndPoint = remoteAddress;
                bool connected = !this.Socket.ConnectAsync(eventPayload);
                success = true;
                return(connected);
            }
            finally
            {
                if (!success)
                {
                    this.DoClose();
                }
            }
        }
示例#6
0
        protected override void ScheduleMessageWrite(object message)
        {
            if (!(message is IAddressedEnvelope <IByteBuffer> envelope))
            {
                throw new InvalidOperationException(
                          $"Unexpected type: {message.GetType().FullName}, expecting DatagramPacket or IAddressedEnvelope.");
            }

            IByteBuffer data   = envelope.Content;
            int         length = data.ReadableBytes;

            if (length == 0)
            {
                return;
            }

            SocketChannelAsyncOperation operation = this.PrepareWriteOperation(data.GetIoBuffer(data.ReaderIndex, length));

            operation.RemoteEndPoint = envelope.Recipient;
            this.SetState(StateFlags.WriteScheduled);
            bool pending = this.Socket.SendToAsync(operation);

            if (!pending)
            {
                ((ISocketChannelUnsafe)this.Unsafe).FinishWrite(operation);
            }
        }
示例#7
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)
                {
                    Util.CompleteChannelCloseTaskSafely(this.channel, this.CloseAsync(new ClosedChannelException("Failed to write", ex), false));
                }

                // 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?
            }
示例#8
0
            public void FinishConnect(SocketChannelAsyncOperation operation)
            {
                Contract.Assert(this.channel.EventLoop.InEventLoop);

                AbstractSocketChannel ch = this.Channel;

                try
                {
                    bool wasActive = ch.Active;
                    ch.DoFinishConnect(operation);
                    this.FulfillConnectPromise(wasActive);
                }
                catch (Exception ex)
                {
                    TaskCompletionSource promise = ch.connectPromise;
                    var remoteAddress            = (EndPoint)promise?.Task.AsyncState;
                    this.FulfillConnectPromise(this.AnnotateConnectException(ex, remoteAddress));
                }
                finally
                {
                    // Check for null as the connectTimeoutFuture is only created if a connectTimeoutMillis > 0 is used
                    // See https://github.com/netty/netty/issues/1770
                    ch.connectCancellationTask?.Cancel();
                    ch.connectPromise = null;
                }
            }
示例#9
0
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     try
     {
         operation.Validate();
     }
     finally
     {
         operation.Dispose();
     }
     this.OnConnected();
 }
示例#10
0
        protected void ResetWriteOperation()
        {
            SocketChannelAsyncOperation operation = this.writeOperation;

            Contract.Assert(operation != null);

            if (operation.BufferList == null)
            {
                operation.SetBuffer(null, 0, 0);
            }
            else
            {
                operation.BufferList = null;
            }
        }
        protected override void ScheduleSocketRead()
        {
            bool closed = false;
            SocketChannelAsyncOperation operation = this.AcceptOperation;

            while (!closed)
            {
                try
                {
                    bool pending = this.Socket.AcceptAsync(operation);
                    if (!pending)
                    {
                        this.EventLoop.Execute(ReadCompletedSyncCallback, this.Unsafe, operation);
                    }
                    return;
                }
                catch (SocketException ex) when(ex.SocketErrorCode == SocketError.OperationAborted || ex.SocketErrorCode == SocketError.InvalidArgument)
                {
                    closed = true;
                }
                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)
                {
                    this.Pipeline.FireExceptionCaught(ex);
                    closed = true;
                }
            }
            if (closed && this.Open)
            {
                this.Unsafe.CloseSafe();
            }
        }
示例#12
0
        protected bool IncompleteWrite(bool scheduleAsync, SocketChannelAsyncOperation operation)
        {
            // Did not write completely.
            if (scheduleAsync)
            {
                this.SetState(StateFlags.WriteScheduled);
                bool pending;

#if NETSTANDARD1_3
                pending = this.Socket.SendAsync(operation);
#else
                if (ExecutionContext.IsFlowSuppressed())
                {
                    pending = this.Socket.SendAsync(operation);
                }
                else
                {
                    using (ExecutionContext.SuppressFlow())
                    {
                        pending = this.Socket.SendAsync(operation);
                    }
                }
#endif

                if (!pending)
                {
                    ((ISocketChannelUnsafe)this.Unsafe).FinishWrite(operation);
                }

                return(pending);
            }
            else
            {
                // Schedule flush again later so other tasks can be picked up input the meantime
                this.EventLoop.Execute(FlushAction, this);

                return(true);
            }
        }
示例#13
0
        protected override void ScheduleSocketRead()
        {
            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 (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);
            }
        }
示例#14
0
        protected override int DoReadMessages(List <object> buf)
        {
            Contract.Requires(buf != null);

            SocketChannelAsyncOperation operation = this.ReadOperation;
            var  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;
            }
        }
            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();
                    }
                }
            }
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     throw new NotSupportedException();
 }
示例#17
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();
                    }
                }
            }
示例#18
0
        //protected long doWriteFileRegion(FileRegion region)
        //{
        //    long position = region.transfered();
        //    return region.transferTo(javaChannel(), position);
        //}

        protected override void DoWrite(ChannelOutboundBuffer input)
        {
            List <ArraySegment <byte> > sharedBufferList = null;

            try
            {
                while (true)
                {
                    int size = input.Size;
                    if (size == 0)
                    {
                        // All written
                        break;
                    }
                    long writtenBytes = 0;
                    bool done         = false;

                    // Ensure the pending writes are made of ByteBufs only.
                    int maxBytesPerGatheringWrite = ((TcpSocketChannelConfig)this.config).GetMaxBytesPerGatheringWrite();
                    sharedBufferList = input.GetSharedBufferList(1024, maxBytesPerGatheringWrite);
                    int    nioBufferCnt         = sharedBufferList.Count;
                    long   expectedWrittenBytes = input.NioBufferSize;
                    Socket socket = this.Socket;

                    List <ArraySegment <byte> > bufferList = sharedBufferList;
                    // Always us nioBuffers() to workaround data-corruption.
                    // See https://github.com/netty/netty/issues/2761
                    switch (nioBufferCnt)
                    {
                    case 0:
                        // We have something else beside ByteBuffers to write so fallback to normal writes.
                        base.DoWrite(input);
                        return;

                    default:
                        for (int i = this.Configuration.WriteSpinCount - 1; i >= 0; i--)
                        {
                            long localWrittenBytes = socket.Send(bufferList, SocketFlags.None, out SocketError errorCode);
                            if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock)
                            {
                                throw new SocketException((int)errorCode);
                            }

                            if (localWrittenBytes == 0)
                            {
                                break;
                            }

                            expectedWrittenBytes -= localWrittenBytes;
                            writtenBytes         += localWrittenBytes;
                            if (expectedWrittenBytes == 0)
                            {
                                done = true;
                                break;
                            }
                            else
                            {
                                bufferList = this.AdjustBufferList(localWrittenBytes, bufferList);
                            }
                        }
                        break;
                    }

                    if (writtenBytes > 0)
                    {
                        // Release the fully written buffers, and update the indexes of the partially written buffer.
                        input.RemoveBytes(writtenBytes);
                    }

                    if (!done)
                    {
                        SocketChannelAsyncOperation asyncOperation = this.PrepareWriteOperation(bufferList);

                        // Did not write all buffers completely.
                        if (this.IncompleteWrite(true, asyncOperation))
                        {
                            break;
                        }
                    }
                }
            }
            finally
            {
                sharedBufferList?.Clear();
            }
        }
            public override void FinishRead(SocketChannelAsyncOperation operation)
            {
                Contract.Assert(this.channel.EventLoop.InEventLoop);

                AbstractSocketMessageChannel ch = this.Channel;

                if ((ch.ResetState(StateFlags.ReadScheduled) & StateFlags.Active) == 0)
                {
                    return; // read was signaled as a result of channel closure
                }
                IChannelConfiguration config = ch.Configuration;

                IChannelPipeline            pipeline    = ch.Pipeline;
                IRecvByteBufAllocatorHandle allocHandle = this.Channel.Unsafe.RecvBufAllocHandle;

                allocHandle.Reset(config);

                bool      closed    = false;
                Exception exception = null;

                try
                {
                    try
                    {
                        do
                        {
                            int localRead = ch.DoReadMessages(this.readBuf);
                            if (localRead == 0)
                            {
                                break;
                            }
                            if (localRead < 0)
                            {
                                closed = true;
                                break;
                            }

                            allocHandle.IncMessagesRead(localRead);
                        }while (allocHandle.ContinueReading());
                    }
                    catch (Exception t)
                    {
                        exception = t;
                    }
                    int size = this.readBuf.Count;
                    for (int i = 0; i < size; i++)
                    {
                        ch.ReadPending = false;
                        pipeline.FireChannelRead(this.readBuf[i]);
                    }

                    this.readBuf.Clear();
                    allocHandle.ReadComplete();
                    pipeline.FireChannelReadComplete();

                    if (exception != null)
                    {
                        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)
                        {
                            this.CloseSafe();
                        }
                    }
                }
                finally
                {
                    // Check if there is a readPending which was not processed yet.
                    // This could be for two reasons:
                    // /// The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method
                    // /// The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method
                    //
                    // See https://github.com/netty/netty/issues/2254
                    if (!closed && (ch.ReadPending || config.AutoRead))
                    {
                        ch.DoBeginRead();
                    }
                }
            }
示例#20
0
 /// <summary>
 ///     Finish the connect
 /// </summary>
 protected abstract void DoFinishConnect(SocketChannelAsyncOperation operation);
示例#21
0
 public abstract void FinishRead(SocketChannelAsyncOperation operation);