private void FinishPeerRead0(LocalChannel peer) { var finishPeerReadTask = peer._finishReadTask; if (finishPeerReadTask != null) { if (!finishPeerReadTask.IsCompleted) { RunFinishPeerReadTask(peer); return; } // TODO: might need to make this lazy in order to avoid a premature unset while scheduling a new task peer._finishReadTask = null; } var peerPipeline = peer.Pipeline; if (peer._readInProgress) { peer._readInProgress = false; while (true) { if (peer._inboundBuffer.Count == 0) { break; } var received = peer._inboundBuffer.Dequeue(); peerPipeline.FireChannelRead(received); } peerPipeline.FireChannelReadComplete(); } }
private void DoPeerClose(LocalChannel peer, bool peerWriteInProgress) { if (peerWriteInProgress) { FinishPeerRead0(peer); } peer.Unsafe.CloseAsync(); }
public LocalChannel(LocalServerChannel parent, LocalChannel peer) : base(parent) { _peer = peer; _localAddress = parent.LocalAddress; _remoteAddress = peer.LocalAddress; Configuration = new DefaultChannelConfiguration(this); _shutdownHook = new ShutdownHook(this); _readTask = new ReadTask(this); }
private void FinishPeerRead(LocalChannel peer) { // If the peer is also writing, then we must schedule the event on the event loop to preserve read order. if (peer.EventLoop == EventLoop && !peer._writeInProgress) { FinishPeerRead0(peer); } else { RunFinishPeerReadTask(peer); } }
public LocalChannel Serve(LocalChannel peer) { var child = new LocalChannel(this, peer); if (EventLoop.InEventLoop) { Serve0(child); } else { EventLoop.Execute(ServeAction, this, child); } return(child); }
private void RunFinishPeerReadTask(LocalChannel peer) { try { if (peer._writeInProgress) { peer._finishReadTask = _peer.EventLoop.SubmitAsync(DoFinishPeerReadAsync, this, peer); } else { peer.EventLoop.Execute(DoFinishPeerRead, this, peer); } } catch (Exception) { _peer.ReleaseInboundBuffers(); throw; } }
private void Serve0(LocalChannel child) { _inboundBuffer.Enqueue(child); if (_acceptInProgress) { _acceptInProgress = false; var pipeline = Pipeline; while (true) { if (_inboundBuffer.Count == 0) { break; } var m = _inboundBuffer.Dequeue(); pipeline.FireChannelRead(m); } pipeline.FireChannelReadComplete(); } }
public ShutdownHook(LocalChannel channel) { _channel = channel; }
public ReadTask(LocalChannel channel) { _channel = channel; }
protected override void DoClose() { var peer = _peer; if (_state != State.Closed) { // Update all internal state before the CloseTask is notified if (_localAddress != null) { if (Parent == null) { LocalChannelRegistry.Unregister(_localAddress); } _localAddress = null; } // State change must happen before finishPeerRead to ensure writes are released either in doWrite or // channelRead. _state = State.Closed; var promise = _connectPromise; if (promise != null) { promise.TrySetException(ClosedChannelException.Instance); _connectPromise = null; } // To preserve ordering of events we must process any pending reads if (_writeInProgress && peer != null) { FinishPeerRead(peer); } } if (peer != null && peer.IsActive) { if (peer.EventLoop.InEventLoop && !_registerInProgress) { DoPeerClose(peer, peer._writeInProgress); } else { // This value may change, and so we should save it before executing the IRunnable var peerWriteInProgress = peer._writeInProgress; try { peer.EventLoop.Execute((context, state) => // todo: allocation { var p = (LocalChannel) context; var wIP = (bool) state; DoPeerClose(p, wIP); }, peer, peerWriteInProgress); } catch (Exception ex) { // The peer close may attempt to drain this._inboundBuffers. If that fails make sure it is drained. ReleaseInboundBuffers(); throw; } } _peer = null; } }
private void Serve0(LocalChannel child) { _inboundBuffer.Enqueue(child); if (_acceptInProgress) { _acceptInProgress = false; var pipeline = Pipeline; while (true) { if (_inboundBuffer.Count == 0) break; var m = _inboundBuffer.Dequeue(); pipeline.FireChannelRead(m); } pipeline.FireChannelReadComplete(); } }
public LocalUnsafe(LocalChannel channel) : base(channel) { Local = channel; }
public LocalChannel Serve(LocalChannel peer) { var child = new LocalChannel(this, peer); if (EventLoop.InEventLoop) { Serve0(child); } else { EventLoop.Execute(ServeAction, this, child); } return child; }
protected override void DoClose() { var peer = _peer; if (_state != State.Closed) { // Update all internal state before the CloseTask is notified if (_localAddress != null) { if (Parent == null) { LocalChannelRegistry.Unregister(_localAddress); } _localAddress = null; } // State change must happen before finishPeerRead to ensure writes are released either in doWrite or // channelRead. _state = State.Closed; var promise = _connectPromise; if (promise != null) { promise.TrySetException(ClosedChannelException.Instance); _connectPromise = null; } // To preserve ordering of events we must process any pending reads if (_writeInProgress && peer != null) { FinishPeerRead(peer); } } if (peer != null && peer.IsActive) { if (peer.EventLoop.InEventLoop && !_registerInProgress) { DoPeerClose(peer, peer._writeInProgress); } else { // This value may change, and so we should save it before executing the IRunnable var peerWriteInProgress = peer._writeInProgress; try { peer.EventLoop.Execute((context, state) => // todo: allocation { var p = (LocalChannel)context; var wIP = (bool)state; DoPeerClose(p, wIP); }, peer, peerWriteInProgress); } catch (Exception ex) { // The peer close may attempt to drain this._inboundBuffers. If that fails make sure it is drained. ReleaseInboundBuffers(); throw; } } _peer = null; } }