public static LocalAddress Register(IChannel channel, LocalAddress oldLocalAddress, EndPoint localAddress) { if (oldLocalAddress != null) { throw new HeliosException("already bound"); } if (!(localAddress is LocalAddress)) { throw new HeliosException($"Unsupported address type {localAddress.GetType()}"); } var addr = (LocalAddress)localAddress; if (LocalAddress.Any.Equals(addr)) { addr = new LocalAddress(channel); } if (BoundChannels.ContainsKey(addr)) { throw new HeliosException($"address {addr} is already in use "); } var boundChannel = BoundChannels.GetOrAdd(addr, channel); return(addr); }
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); }
protected override void DoClose() { if (_state <= 1) { // Update all internal state before the CloseTask is notified if (_localAddress != null) { LocalChannelRegistry.Unregister(_localAddress); _localAddress = null; } _state = 2; } }
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); }
public static LocalAddress Register(IChannel channel, LocalAddress oldLocalAddress, EndPoint localAddress) { if (oldLocalAddress != null) throw new HeliosException("already bound"); if (!(localAddress is LocalAddress)) { throw new HeliosException($"Unsupported address type {localAddress.GetType()}"); } var addr = (LocalAddress) localAddress; if (LocalAddress.Any.Equals(addr)) { addr = new LocalAddress(channel); } if (BoundChannels.ContainsKey(addr)) throw new HeliosException($"address {addr} is already in use "); var boundChannel = BoundChannels.GetOrAdd(addr, channel); return addr; }
protected bool Equals(LocalAddress other) { return(string.Equals(Id, other.Id)); }
public static void Unregister(LocalAddress localAddress) { IChannel channel; BoundChannels.TryRemove(localAddress, out channel); }
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; }
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; } }
protected override void DoBind(EndPoint localAddress) { _localAddress = LocalChannelRegistry.Register(this, _localAddress, localAddress); _state = State.Bound; }
protected override void DoBind(EndPoint localAddress) { _localAddress = LocalChannelRegistry.Register(this, _localAddress, localAddress); _state = 1; }
protected bool Equals(LocalAddress other) { return string.Equals(Id, other.Id); }
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; } }