private IStream createStream( SynStreamFrame frame, StreamFrameListener listener, boolean local, Promise<Stream> promise) { IStream associatedStream = streams.get(frame.getAssociatedStreamId()); IStream stream = new StandardStream( frame.getStreamId(), frame.getPriority(), this, associatedStream, promise); flowControlStrategy.onNewStream(this, stream); stream.updateCloseState(frame.isClose(), local); stream.setStreamFrameListener(listener); if (stream.isUnidirectional()) { // Unidirectional streams are implicitly half closed stream.updateCloseState(true, !local); if (!stream.isClosed()) stream.getAssociatedStream().associate(stream); } int streamId = stream.getId(); if (local) { while (true) { int oldStreamCountValue = localStreamCount.get(); int maxConcurrentStreams = maxConcurrentLocalStreams; if (maxConcurrentStreams > -1 && oldStreamCountValue >= maxConcurrentStreams) { String message = String.format("Max concurrent local streams (%d) exceeded.", maxConcurrentStreams); LOG.debug(message); promise.failed(new SPDYException(message)); return null; } if (localStreamCount.compareAndSet(oldStreamCountValue, oldStreamCountValue + 1)) break; } } if (streams.putIfAbsent(streamId, stream) != null) { String message = "Duplicate stream id " + streamId; IllegalStateException duplicateIdException = new IllegalStateException(message); promise.failed(duplicateIdException); if (local) { localStreamCount.decrementAndGet(); throw duplicateIdException; } RstInfo rstInfo = new RstInfo(streamId, StreamStatus.PROTOCOL_ERROR); LOG.debug("Duplicate stream, {}", rstInfo); rst(rstInfo, new Callback.Adapter()); // We don't care (too much) if the reset fails. return null; } else { LOG.debug("Created {}", stream); notifyStreamCreated(stream); return stream; } }
private void processData(final IStream stream, DataFrame frame, ByteBuffer data) { ByteBufferDataInfo dataInfo = new ByteBufferDataInfo(data, frame.isClose()) { @Override public void consume(int delta) { super.consume(delta); flowControlStrategy.onDataConsumed(StandardSession.this, stream, this, delta); } }; flowControlStrategy.onDataReceived(this, stream, dataInfo); stream.process(dataInfo); if (stream.isClosed()) removeStream(stream); }
@Override public void complete() { bufferPool.release(buffer); super.complete(); if (frame.getType() == ControlFrameType.GO_AWAY) { // After sending a GO_AWAY we need to hard close the connection. // Recipients will know the last good stream id and act accordingly. close(); } IStream stream = getStream(); if (stream != null && stream.isClosed()) removeStream(stream); }
private void processSyn(SessionFrameListener listener, IStream stream, SynStreamFrame frame) { stream.process(frame); // Update the last stream id before calling the application (which may send a GO_AWAY) updateLastStreamId(stream); StreamFrameListener streamListener; if (stream.isUnidirectional()) { PushInfo pushInfo = new PushInfo(frame.getHeaders(), frame.isClose()); streamListener = notifyOnPush(stream.getAssociatedStream().getStreamFrameListener(), stream, pushInfo); } else { SynInfo synInfo = new SynInfo(frame.getHeaders(), frame.isClose(), frame.getPriority()); streamListener = notifyOnSyn(listener, stream, synInfo); } stream.setStreamFrameListener(streamListener); flush(); // The onSyn() listener may have sent a frame that closed the stream if (stream.isClosed()) removeStream(stream); }
@Override public void complete() { 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. prepend(this); flush(); } else { super.complete(); stream.updateCloseState(dataInfo.isClose(), true); if (stream.isClosed()) removeStream(stream); } }
private void processHeaders(IStream stream, HeadersFrame frame) { stream.process(frame); if (stream.isClosed()) removeStream(stream); }
private void processReply(IStream stream, SynReplyFrame frame) { stream.process(frame); if (stream.isClosed()) removeStream(stream); }