public StandardSession(short version, ByteBufferPool bufferPool, Scheduler scheduler, Controller controller, EndPoint endPoint, IdleListener idleListener, int initialStreamId, SessionFrameListener listener, Generator generator, FlowControlStrategy flowControlStrategy) { // TODO this should probably be an aggregate lifecycle this.version = version; this.bufferPool = bufferPool; this.scheduler = scheduler; this.controller = controller; this.endPoint = endPoint; this.idleListener = idleListener; this.streamIds = new AtomicInteger(initialStreamId); this.pingIds = new AtomicInteger(initialStreamId); this.listener = listener; this.generator = generator; this.flowControlStrategy = flowControlStrategy; this.flusher = new Flusher(controller); }
@Override public void shutdown() { CloseFrameBytes frameBytes = new CloseFrameBytes(); flush(frameBytes, flusher.append(frameBytes)); }
private void flush(FrameBytes frameBytes, Throwable throwable) { if (throwable != null) frameBytes.failed(throwable); else flusher.flush(); }
@Override public String toString() { return String.format("%s@%x{v%d,queueSize=%d,windowSize=%d,streams=%d}", getClass().getSimpleName(), hashCode(), version, flusher.getQueueSize(), getWindowSize(), streams.size()); }
@Override public void rst(RstInfo rstInfo, Callback callback) { // SPEC v3, 2.2.2 if (goAwaySent.get()) { complete(callback); } else { int streamId = rstInfo.getStreamId(); IStream stream = streams.get(streamId); RstStreamFrame frame = new RstStreamFrame(version, streamId, rstInfo.getStreamStatus().getCode(version)); control(stream, frame, rstInfo.getTimeout(), rstInfo.getUnit(), callback); if (stream != null) { stream.process(frame); flusher.removeFrameBytesFromQueue(stream); removeStream(stream); } } }
@Override public void succeeded() { bufferPool.release(buffer); IStream stream = getStream(); dataInfo.consume(size); flowControlStrategy.updateWindow(StandardSession.this, stream, -size); if (dataInfo.available() > 0) { // We have written a frame out of this DataInfo, but there is more to write. // We need to keep the correct ordering of frames, to avoid that another // DataInfo for the same stream is written before this one is finished. flush(this, flusher.prepend(this)); } else { super.succeeded(); stream.updateCloseState(dataInfo.isClose(), true); if (stream.isClosed()) removeStream(stream); } }
private void onWindowUpdate(WindowUpdateFrame frame) { int streamId = frame.getStreamId(); IStream stream = streams.get(streamId); flowControlStrategy.onWindowUpdate(this, stream, frame.getWindowDelta()); flusher.flush(); }
@Override public void data(IStream stream, DataInfo dataInfo, long timeout, TimeUnit unit, Callback callback) { if (LOG.isDebugEnabled()) LOG.debug("Queuing {} on {}", dataInfo, stream); DataFrameBytes frameBytes = new DataFrameBytes(stream, callback, dataInfo); if (timeout > 0) frameBytes.task = scheduler.schedule(frameBytes, timeout, unit); flush(frameBytes, flusher.append(frameBytes)); }