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; } }
/// <remarks>PORT NOTE: matches behavior of NioEventLoop.processSelectedKey</remarks> static void OnIoCompleted(object sender, SocketAsyncEventArgs args) { var operation = (SocketChannelAsyncOperation)args; AbstractSocketChannel channel = operation.Channel; var @unsafe = (ISocketChannelUnsafe)channel.Unsafe; IEventLoop eventLoop = channel.EventLoop; switch (args.LastOperation) { case SocketAsyncOperation.Accept: if (eventLoop.InEventLoop) { @unsafe.FinishRead(operation); } else { eventLoop.Execute(ReadCallbackAction, @unsafe, operation); } break; case SocketAsyncOperation.Connect: if (eventLoop.InEventLoop) { @unsafe.FinishConnect(operation); } else { eventLoop.Execute(ConnectCallbackAction, @unsafe, operation); } break; case SocketAsyncOperation.Receive: case SocketAsyncOperation.ReceiveFrom: if (eventLoop.InEventLoop) { @unsafe.FinishRead(operation); } else { eventLoop.Execute(ReadCallbackAction, @unsafe, operation); } break; case SocketAsyncOperation.Send: case SocketAsyncOperation.SendTo: if (eventLoop.InEventLoop) { @unsafe.FinishWrite(operation); } else { eventLoop.Execute(WriteCallbackAction, @unsafe, operation); } break; default: // todo: think of a better way to comm exception throw new ArgumentException("The last operation completed on the socket was not expected"); } }
public SocketChannelAsyncOperation(AbstractSocketChannel channel, bool setEmptyBuffer) { Contract.Requires(channel != null); this.Channel = channel; this.Completed += AbstractSocketChannel.IoCompletedCallback; if (setEmptyBuffer) { this.SetBuffer(ArrayExtensions.ZeroBytes, 0, 0); } }
public SocketChannelAsyncOperation(AbstractSocketChannel channel) : this(channel, true) { }
public sealed override Task ConnectAsync(EndPoint remoteAddress, EndPoint localAddress) { // todo: handle cancellation AbstractSocketChannel ch = this.Channel; if (!ch.Open) { return(this.CreateClosedChannelExceptionTask()); } try { if (ch.connectPromise != null) { throw new InvalidOperationException("connection attempt already made"); } bool wasActive = this.channel.Active; if (ch.DoConnect(remoteAddress, localAddress)) { this.FulfillConnectPromise(wasActive); return(TaskEx.Completed); } else { ch.connectPromise = new TaskCompletionSource(remoteAddress); // Schedule connect timeout. TimeSpan connectTimeout = ch.Configuration.ConnectTimeout; if (connectTimeout > TimeSpan.Zero) { ch.connectCancellationTask = ch.EventLoop.Schedule( (c, a) => { // todo: make static / cache delegate?.. var self = (AbstractSocketChannel)c; // todo: call Socket.CancelConnectAsync(...) TaskCompletionSource promise = self.connectPromise; var cause = new ConnectTimeoutException("connection timed out: " + a.ToString()); if (promise != null && promise.TrySetException(cause)) { self.CloseSafe(); } }, this.channel, remoteAddress, connectTimeout); } ch.connectPromise.Task.ContinueWith( (t, s) => { var c = (AbstractSocketChannel)s; c.connectCancellationTask?.Cancel(); c.connectPromise = null; c.CloseSafe(); }, ch, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously); return(ch.connectPromise.Task); } } catch (Exception ex) { this.CloseIfClosed(); return(TaskEx.FromException(this.AnnotateConnectException(ex, remoteAddress))); } }
protected AbstractSocketUnsafe(AbstractSocketChannel channel) : base(channel) { }