private void Receive(Tcp tcp, IMasterClock clock, Action <PooledArraySegment <byte> > onNext, Action onCompleted, Action <Exception> onError) { tcp.OnRead((handle, buffer) => { // onAccept using (buffer) { if (buffer.Count == 0 || !isAlive) { return; } LastReceive = clock.Now; plb.Receive(buffer, buffer.Count, (src, dst, count) => src.ReadBytes(dst, count), onNext, onError); } }, (handle, ex) => { // onError onError(ex); }, handle => { // onCompleted isAlive = false; onCompleted(); // release handles sendQueueDrainer.UserToken = null; sendQueueDrainer.Dispose(); // empty queues while (sendQueue.TryDequeue(out var fragment)) { fragment.Dispose(); } plb.Dispose(); handle.CloseHandle(); });
private void SetupConnection(Loop loop, Tcp tcp) { Contract.RequiresNonNull(tcp, nameof(tcp)); // initialize send queue sendQueue = new ConcurrentQueue <PooledArraySegment <byte> >(); sendQueueDrainer = loop.CreateAsync(DrainSendQueue); sendQueueDrainer.UserToken = tcp; Received = Observable.Create <PooledArraySegment <byte> >(observer => { var plb = new PooledLineBuffer(logger, MaxInboundRequestLength); tcp.OnRead((handle, buffer) => { // onAccept using (buffer) { if (buffer.Count == 0 || !isAlive) { return; } plb.Receive(buffer, buffer.Count, (src, dst, count) => src.ReadBytes(dst, count), observer.OnNext, observer.OnError); } }, (handle, ex) => { // onError observer.OnError(ex); }, handle => { // onCompleted isAlive = false; observer.OnCompleted(); // release handles sendQueueDrainer.UserToken = null; sendQueueDrainer.Dispose(); // empty queues while (sendQueue.TryDequeue(out var fragment)) { fragment.Dispose(); } plb.Dispose(); handle.CloseHandle(); }); return(Disposable.Create(() => { if (tcp.IsValid) { logger.Debug(() => $"[{ConnectionId}] Last subscriber disconnected from receiver stream"); isAlive = false; tcp.Shutdown(); } })); })