/// <remarks>PORT NOTE: matches behavior of NioEventLoop.processSelectedKey</remarks> static void OnIoCompleted(object sender, SocketAsyncEventArgs args) { var operation = (FABSocketChannelAsyncOperation)args; FABSocketChannel channel = operation.Channel; var @unsafe = (IFABChannelUnsafe)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 void FinishConnect(FABSocketChannelAsyncOperation operation) { Contract.Assert(this.channel.EventLoop.InEventLoop); FABSocketChannel 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 if (ch.connectCancellationTask != null) { ch.connectCancellationTask.Cancel(); } ch.connectPromise = null; } }
public FABSocketChannelAsyncOperation(FABSocketChannel channel, bool setEmptyBuffer) { Contract.Requires(channel != null); this.Channel = channel; this.Completed += FABSocketChannel.IoCompletedCallback; if (setEmptyBuffer) { this.SetBuffer(ArrayExtensions.ZeroBytes, 0, 0); } }
public sealed override Task ConnectAsync(EndPoint remoteAddress, EndPoint localAddress) { // todo: handle cancellation FABSocketChannel 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 = (FABSocketChannel)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 = (FABSocketChannel)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 FABSocketUnsafe(FABSocketChannel channel) : base(channel) { }
public FABSocketChannelAsyncOperation(FABSocketChannel channel) : this(channel, true) { }