public Task BindAsync(EndPoint localAddress) { // todo: cancellation support if (/*!promise.setUncancellable() || */ !_channel.IsOpen) { return(CreateClosedChannelExceptionTask()); } bool wasActive = this._channel.IsActive; var promise = new TaskCompletionSource(); try { this._channel.DoBind(localAddress); } catch (Exception t) { PromiseUtil.SafeSetFailure(promise, t, Logger); this.CloseIfClosed(); return(promise.Task); } if (!wasActive && _channel.IsActive) { InvokeLater(() => this._channel._pipeline.FireChannelActive()); } SafeSetSuccess(promise); return(promise.Task); }
void Register0(TaskCompletionSource promise) { try { // check if the channel is still open as it could be closed input the mean time when the register // call was outside of the eventLoop if (!promise.SetUncancellable() || !EnsureOpen(promise)) { PromiseUtil.SafeSetFailure(promise, ClosedChannelException.Instance, Logger); return; } bool firstRegistration = this.neverRegistered; this._channel.DoRegister(); this.neverRegistered = false; this._channel._registered = true; this._channel._eventLoop.AcceptNewTasks(); PromiseUtil.SafeSetSuccess(promise, Logger); _channel._pipeline.FireChannelRegistered(); // Only fire a channelActive if the channel has never been registered. This prevents firing // multiple channel actives if the channel is deregistered and re-registered. if (firstRegistration && this._channel.IsActive) { _channel._pipeline.FireChannelActive(); } } catch (Exception t) { // Close the channel directly to avoid FD leak. CloseForcibly(); _channel._closeTask.Complete(); PromiseUtil.SafeSetFailure(promise, t, Logger); } }
internal void Close(ClosedChannelException cause) { if (_inFail) { return; } if (!IsEmpty) { throw new InvalidOperationException("close() must be called after all flushed writes are handled."); } _inFail = true; try { var e = _unflushedEntry; while (e != null) { // No triggering anymore events, as we are shutting down if (!e.Cancelled) { ReferenceCountUtil.SafeRelease(e.Message); PromiseUtil.SafeSetFailure(e.Promise, cause, Logger); } e = e.RecycleAndGetNext(); } } finally { _inFail = false; } }
private bool Remove(Exception cause, bool notifyWritability) { var e = _flushedEntry; if (e == null) { return(false); } var msg = e.Message; var promise = e.Promise; var size = e.PendingSize; RemoveEntry(e); if (!e.Cancelled) { // only release message, notify and decrement if it was not canceled before. ReferenceCountUtil.SafeRelease(msg); PromiseUtil.SafeSetFailure(promise, cause, Logger); DecrementPendingOutboundBytes(size, notifyWritability); } e.Recycle(); return(true); }
protected bool EnsureOpen(TaskCompletionSource promise) { if (this._channel.IsOpen) { return(true); } PromiseUtil.SafeSetFailure(promise, ClosedChannelException.Instance, Logger); return(false); }
public Task RegisterAsync(IEventLoop eventLoop) { Contract.Requires(eventLoop != null); if (this._channel.Registered) { return(TaskEx.FromException(new InvalidOperationException("registered to an event loop already"))); } if (!this._channel.IsCompatible(eventLoop)) { return (TaskEx.FromException( new InvalidOperationException("incompatible event loop type: " + eventLoop.GetType().Name))); } // It's necessary to reuse the wrapped eventloop object. Otherwise the user will end up with multiple // objects that do not share a common state. if (this._channel._eventLoop == null) { this._channel._eventLoop = new PausableChannelEventLoop(this._channel, eventLoop); } else { this._channel._eventLoop.Unwrapped = eventLoop; } var promise = new TaskCompletionSource(); if (eventLoop.InEventLoop) { this.Register0(promise); } else { try { eventLoop.Execute(() => this.Register0(promise)); } catch (Exception ex) { Logger.Warning( "Force-closing a channel whose registration task was not accepted by an event loop: {0}; Cause: {1}", _channel, ex); CloseForcibly(); _channel._closeTask.TryComplete(); PromiseUtil.SafeSetFailure(promise, ex, Logger); } } return(promise.Task); }
public override Task ConnectAsync(EndPoint remoteAddress, EndPoint localAddress) { if (Local._state == State.Connected) { var cause = new AlreadyConnectedException(); Local.Pipeline.FireExceptionCaught(cause); return(TaskEx.FromException(cause)); } if (Local._connectPromise != null) { throw new ConnectionPendingException(); } Local._connectPromise = new TaskCompletionSource(); if (Local._state != State.Bound) { // Not bound yet and no LocalAddress specified. Get one if (localAddress == null) { localAddress = new LocalAddress(Local); } } if (localAddress != null) { try { Local.DoBind(localAddress); } catch (Exception ex) { PromiseUtil.SafeSetFailure(Local._connectPromise, ex, Logger); return(CloseAsync()); } } var boundChannel = LocalChannelRegistry.Get(remoteAddress); if (!(boundChannel is LocalServerChannel)) { var cause = new ChannelException("connection refused"); PromiseUtil.SafeSetFailure(Local._connectPromise, cause, Logger); return(CloseAsync()); } var serverChannel = boundChannel as LocalServerChannel; Local._peer = serverChannel.Serve(Local); return(TaskEx.Completed); }
static void SafeSetFailure(TaskCompletionSource promise, Exception cause) { PromiseUtil.SafeSetFailure(promise, cause, Logger); }