Наследование: System.Net.Sockets.SocketAsyncEventArgs
Пример #1
0
            public void FinishWrite(SocketChannelAsyncOperation operation)
            {
                bool resetWritePending = this.Channel.ResetState(StateFlags.WriteScheduled);

                Contract.Assert(resetWritePending);
                var input = OutboundBuffer;

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

                // directly call super.flush0() to force a flush now
                base.Flush0();
            }
Пример #2
0
        protected void IncompleteWrite(bool scheduleAsync, SocketChannelAsyncOperation operation)
        {
            // Did not write completely.
            if (scheduleAsync)
            {
                this.SetState(StateFlags.WriteScheduled);
                bool pending;

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

                if (!pending)
                {
                    ((ISocketChannelUnsafe)this.Unsafe).FinishWrite(operation);
                }
            }
            else
            {
                // Schedule flush again later so other tasks can be picked up input the meantime
                this.EventLoop.Execute(FlushAction, this);
            }
        }
Пример #3
0
        protected SocketChannelAsyncOperation PrepareWriteOperation(ArraySegment <byte> buffer)
        {
            SocketChannelAsyncOperation operation = WriteOperation;

            operation.SetBuffer(buffer.Array, buffer.Offset, buffer.Count);
            return(operation);
        }
Пример #4
0
        protected override bool DoConnect(EndPoint remoteAddress, EndPoint localAddress)
        {
            if (localAddress != null)
            {
                Socket.Bind(localAddress);
            }

            var success = false;

            try
            {
                var eventPayload = new SocketChannelAsyncOperation(this, false);
                eventPayload.RemoteEndPoint = remoteAddress;
                var connected = !Socket.ConnectAsync(eventPayload);
                success = true;
                return(connected);
            }
            finally
            {
                if (!success)
                {
                    DoClose();
                }
            }
        }
Пример #5
0
        protected override void DoClose()
        {
            var promise = _connectPromise;

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

            var cancellationTask = _connectCancellationTask;

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

            var readOp = _readOperation;

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

            var writeOp = _writeOperation;

            if (writeOp != null)
            {
                writeOp.Dispose();
                _writeOperation = null;
            }
        }
Пример #6
0
        protected SocketChannelAsyncOperation PrepareWriteOperation(IList <ArraySegment <byte> > buffers)
        {
            SocketChannelAsyncOperation operation = WriteOperation;

            operation.BufferList = buffers;
            return(operation);
        }
Пример #7
0
            public void FinishWrite(SocketChannelAsyncOperation operation)
            {
                var input = OutboundBuffer;

                try
                {
                    operation.Validate();
                    var sent = operation.BytesTransferred;
                    Channel.ResetWriteOperation();
                    if (sent > 0)
                    {
                        var msg    = input.Current;
                        var buffer = msg as IByteBuf;
                        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();
            }
Пример #8
0
            public void FinishConnect(SocketChannelAsyncOperation operation)
            {
                Contract.Assert(_channel.EventLoop.InEventLoop);

                var ch = Channel;

                try
                {
                    var wasActive = ch.IsActive;
                    ch.DoFinishConnect(operation);
                    FulfillConnectPromise(wasActive);
                }
                catch (Exception ex)
                {
                    var promise       = ch._connectPromise;
                    var remoteAddress = promise == null ? null : (EndPoint)promise.Task.AsyncState;
                    FulfillConnectPromise(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
                    if (ch._connectCancellationTask != null)
                    {
                        ch._connectCancellationTask.Cancel();
                    }
                    ch._connectPromise = null;
                }
            }
Пример #9
0
        protected override void ScheduleSocketRead()
        {
            SocketChannelAsyncOperation operation = this.AcceptOperation;
            bool pending = this.Socket.AcceptAsync(operation);

            if (!pending)
            {
                this.EventLoop.Execute(ReadCompletedSyncCallback, this.Unsafe, operation);
            }
        }
Пример #10
0
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     try
     {
         operation.Validate();
     }
     finally
     {
         operation.Dispose();
     }
     OnConnected();
 }
Пример #11
0
        protected SocketChannelAsyncOperation PrepareWriteOperation(IByteBuf buffer)
        {
            var operation = _writeOperation ?? (_writeOperation = new SocketChannelAsyncOperation(this, false));

            if (!buffer.HasArray)
            {
                throw new NotImplementedException(
                          "IByteBuffer implementations not backed by array are currently not supported.");
            }
            operation.SetBuffer(buffer.Array, buffer.ArrayOffset + buffer.WriterIndex, buffer.WritableBytes);
            return(operation);
        }
Пример #12
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.Warning(ex, "Failed to create a new channel from an accepted socket.");
                            if (connectedSocket != null)
                            {
                                try
                                {
                                    connectedSocket.Close();
                                }
                                catch (Exception ex2)
                                {
                                    Logger.Warning(ex2, "Failed to close a socket.");
                                }
                            }
                            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.IsOpen)
                        {
                            this.CloseAsync();
                        }
                    }
                }
                finally
                {
                    // Check if there is a readPending which was not processed yet.
                    if (!closed && (config.AutoRead || ch.ReadPending))
                    {
                        ch.DoBeginRead();
                    }
                }
            }
Пример #13
0
        protected void IncompleteWrite(bool scheduleAsync, SocketChannelAsyncOperation operation)
        {
            // Did not write completely.
            if (scheduleAsync)
            {
                this.SetState(StateFlags.WriteScheduled);
                bool pending;

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

                if (!pending)
                {
                    ((ISocketChannelUnsafe) this.Unsafe).FinishWrite(operation);
                }
            }
            else
            {
                // Schedule flush again later so other tasks can be picked up input the meantime
                this.EventLoop.Execute(FlushAction, this);
            }
        }
Пример #14
0
 public abstract void FinishRead(SocketChannelAsyncOperation operation);
Пример #15
0
        protected override void DoClose()
        {
            var promise = _connectPromise;
            if (promise != null)
            {
                // Use TrySetException() instead of SetException() to avoid the race against cancellation due to timeout.
                promise.TrySetException(ClosedChannelException.Instance);
                _connectPromise = null;
            }

            var cancellationTask = _connectCancellationTask;
            if (cancellationTask != null)
            {
                cancellationTask.Cancel();
                _connectCancellationTask = null;
            }

            var readOp = _readOperation;
            if (readOp != null)
            {
                readOp.Dispose();
                _readOperation = null;
            }

            var writeOp = _writeOperation;
            if (writeOp != null)
            {
                writeOp.Dispose();
                _writeOperation = null;
            }
        }
Пример #16
0
 /// <summary>
 ///     Finish the connect
 /// </summary>
 protected abstract void DoFinishConnect(SocketChannelAsyncOperation operation);
Пример #17
0
            public override void FinishRead(SocketChannelAsyncOperation operation)
            {
                var ch = Channel;
                ch.ResetState(StateFlags.ReadScheduled);
                var config = ch.Configuration;
                var pipeline = ch.Pipeline;
                var allocator = config.Allocator;
                var maxMessagesPerRead = config.MaxMessagesPerRead;
                var allocHandle = RecvBufAllocHandle;

                IByteBuf byteBuf = null;
                var messages = 0;
                var close = false;
                try
                {
                    operation.Validate();

                    var totalReadAmount = 0;
                    var readPendingReset = false;
                    do
                    {
                        byteBuf = allocHandle.Allocate(allocator);
                        var writable = byteBuf.WritableBytes;
                        var 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)
                    {
                        CloseOnRead();
                        close = false;
                    }
                }
                catch (Exception t)
                {
                    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();
                    }
                }
            }
Пример #18
0
        protected override void DoWrite(ChannelOutboundBuffer input)
        {
            while (true)
            {
                int size = input.Count;
                if (size == 0)
                {
                    // All written
                    break;
                }
                long writtenBytes = 0;
                bool done         = false;
                bool setOpWrite   = false;

                // Ensure the pending writes are made of ByteBufs only.
                List <ArraySegment <byte> > nioBuffers = input.GetNioBuffers();
                int    nioBufferCnt         = nioBuffers.Count;
                long   expectedWrittenBytes = input.NioBufferSize;
                Socket socket = this.Socket;

                // Always use 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;

                case 1:
                    // Only one ByteBuf so use non-gathering write
                    ArraySegment <byte> nioBuffer = nioBuffers[0];
                    for (int i = this.Configuration.WriteSpinCount - 1; i >= 0; i--)
                    {
                        SocketError errorCode;
                        int         localWrittenBytes = socket.Send(nioBuffer.Array, nioBuffer.Offset, nioBuffer.Count,
                                                                    SocketFlags.None, out errorCode);
                        if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock)
                        {
                            throw new SocketException((int)errorCode);
                        }

                        if (localWrittenBytes == 0)
                        {
                            setOpWrite = true;
                            break;
                        }
                        expectedWrittenBytes -= localWrittenBytes;
                        writtenBytes         += localWrittenBytes;
                        if (expectedWrittenBytes == 0)
                        {
                            done = true;
                            break;
                        }
                    }
                    break;

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


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

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

                    // Did not write all buffers completely.
                    this.IncompleteWrite(setOpWrite, asyncOperation);
                    break;
                }
            }
        }
Пример #19
0
 /// <summary>
 ///     Finish the connect
 /// </summary>
 protected abstract void DoFinishConnect(SocketChannelAsyncOperation operation);
Пример #20
0
 public abstract void FinishRead(SocketChannelAsyncOperation operation);
Пример #21
0
            public void FinishConnect(SocketChannelAsyncOperation operation)
            {
                Contract.Assert(_channel.EventLoop.InEventLoop);

                var ch = Channel;
                try
                {
                    var wasActive = ch.IsActive;
                    ch.DoFinishConnect(operation);
                    FulfillConnectPromise(wasActive);
                }
                catch (Exception ex)
                {
                    var promise = ch._connectPromise;
                    var remoteAddress = promise == null ? null : (EndPoint) promise.Task.AsyncState;
                    FulfillConnectPromise(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
                    if (ch._connectCancellationTask != null)
                    {
                        ch._connectCancellationTask.Cancel();
                    }
                    ch._connectPromise = null;
                }
            }
Пример #22
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.Warning(ex, "Failed to create a new channel from an accepted socket.");
                            if (connectedSocket != null)
                            {
                                try
                                {
                                    connectedSocket.Close();
                                }
                                catch (Exception ex2)
                                {
                                    Logger.Warning(ex2, "Failed to close a socket.");
                                }
                            }
                            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.IsOpen)
                        {
                            this.CloseAsync();
                        }
                    }
                }
                finally
                {
                    // Check if there is a readPending which was not processed yet.
                    if (!closed && (config.AutoRead || ch.ReadPending))
                    {
                        ch.DoBeginRead();
                    }
                }
            }
Пример #23
0
            public void FinishWrite(SocketChannelAsyncOperation operation)
            {
                bool resetWritePending = this.Channel.ResetState(StateFlags.WriteScheduled);

                Contract.Assert(resetWritePending);
                var input = OutboundBuffer;
                try
                {
                    operation.Validate();
                    var sent = operation.BytesTransferred;
                    Channel.ResetWriteOperation();
                    if (sent > 0)
                    {
                        input.RemoveBytes(sent);
                    }
                }
                catch (Exception ex)
                {
                    input.FailFlushed(ex, true);
                    throw;
                }

                // directly call super.flush0() to force a flush now
                base.Flush0();
            }
Пример #24
0
        protected override bool DoConnect(EndPoint remoteAddress, EndPoint localAddress)
        {
            if (localAddress != null)
            {
                Socket.Bind(localAddress);
            }

            var success = false;
            try
            {
                var eventPayload = new SocketChannelAsyncOperation(this, false);
                eventPayload.RemoteEndPoint = remoteAddress;
                var connected = !Socket.ConnectAsync(eventPayload);
                success = true;
                return connected;
            }
            finally
            {
                if (!success)
                {
                    DoClose();
                }
            }
        }
Пример #25
0
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     throw new NotSupportedException();
 }
Пример #26
0
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     try
     {
         operation.Validate();
     }
     finally
     {
         operation.Dispose();
     }
     OnConnected();
 }
            public override void FinishRead(SocketChannelAsyncOperation operation)
            {
                var ch = Channel;

                ch.ResetState(StateFlags.ReadScheduled);
                var 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;
                }

                var pipeline           = ch.Pipeline;
                var allocator          = config.Allocator;
                var maxMessagesPerRead = config.MaxMessagesPerRead;
                var allocHandle        = RecvBufAllocHandle;

                IByteBuf byteBuf  = null;
                var      messages = 0;
                var      close    = false;

                try
                {
                    operation.Validate();

                    var totalReadAmount  = 0;
                    var readPendingReset = false;
                    do
                    {
                        byteBuf = allocHandle.Allocate(allocator);
                        var writable        = byteBuf.WritableBytes;
                        var 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)
                    {
                        CloseOnRead();
                        close = false;
                    }
                }
                catch (Exception t)
                {
                    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();
                    }
                }
            }
Пример #28
0
 protected override void DoFinishConnect(SocketChannelAsyncOperation operation)
 {
     throw new NotSupportedException();
 }