@Override public void syn(SynInfo synInfo, StreamFrameListener listener, Promise<Stream> promise) { // Synchronization is necessary. // SPEC v3, 2.3.1 requires that the stream creation be monotonically crescent // so we cannot allow thread1 to create stream1 and thread2 create stream3 and // have stream3 hit the network before stream1, not only to comply with the spec // but also because the compression context for the headers would be wrong, as the // frame with a compression history will come before the first compressed frame. int associatedStreamId = 0; if (synInfo instanceof PushSynInfo) associatedStreamId = ((PushSynInfo) synInfo).getAssociatedStreamId(); synchronized (this) { int streamId = streamIds.getAndAdd(2); // TODO: for SPDYv3 we need to support the "slot" argument SynStreamFrame synStream = new SynStreamFrame( version, synInfo.getFlags(), streamId, associatedStreamId, synInfo.getPriority(), (short) 0, synInfo.getHeaders()); IStream stream = createStream(synStream, listener, true, promise); if (stream == null) return; generateAndEnqueueControlFrame( stream, synStream, synInfo.getTimeout(), synInfo.getUnit(), stream); } flush(); }
@Override public void data( IStream stream, DataInfo dataInfo, long timeout, TimeUnit unit, Callback callback) { LOG.debug("Queuing {} on {}", dataInfo, stream); DataFrameBytes frameBytes = new DataFrameBytes(stream, callback, dataInfo); if (timeout > 0) frameBytes.task = scheduler.schedule(frameBytes, timeout, unit); append(frameBytes); flush(); }
private void onPing(PingFrame frame) { int pingId = frame.getPingId(); if (pingId % 2 == pingIds.get() % 2) { PingResultInfo pingResultInfo = new PingResultInfo(frame.getPingId()); notifyOnPing(listener, pingResultInfo); flush(); } else { control(null, frame, 0, TimeUnit.MILLISECONDS, new Callback.Adapter()); } }
private void onGoAway(GoAwayFrame frame) { if (goAwayReceived.compareAndSet(false, true)) { // TODO: Find a better name for GoAwayResultInfo GoAwayResultInfo goAwayResultInfo = new GoAwayResultInfo(frame.getLastStreamId(), SessionStatus.from(frame.getStatusCode())); notifyOnGoAway(listener, goAwayResultInfo); flush(); // SPDY does not require to send back a response to a GO_AWAY. // We notified the application of the last good stream id and // tried our best to flush remaining data. } }
private void onRst(RstStreamFrame frame) { IStream stream = streams.get(frame.getStreamId()); if (stream != null) stream.process(frame); RstInfo rstInfo = new RstInfo( frame.getStreamId(), StreamStatus.from(frame.getVersion(), frame.getStatusCode())); notifyOnRst(listener, rstInfo); flush(); if (stream != null) removeStream(stream); }
private void onSettings(SettingsFrame frame) { Settings.Setting windowSizeSetting = frame.getSettings().get(Settings.ID.INITIAL_WINDOW_SIZE); if (windowSizeSetting != null) { int windowSize = windowSizeSetting.value(); setWindowSize(windowSize); LOG.debug("Updated session window size to {}", windowSize); } Settings.Setting maxConcurrentStreamsSetting = frame.getSettings().get(Settings.ID.MAX_CONCURRENT_STREAMS); if (maxConcurrentStreamsSetting != null) { int maxConcurrentStreamsValue = maxConcurrentStreamsSetting.value(); maxConcurrentLocalStreams = maxConcurrentStreamsValue; LOG.debug("Updated session maxConcurrentLocalStreams to {}", maxConcurrentStreamsValue); } SettingsInfo settingsInfo = new SettingsInfo(frame.getSettings(), frame.isClearPersisted()); notifyOnSettings(listener, settingsInfo); flush(); }
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 shutdown() { FrameBytes frameBytes = new CloseFrameBytes(); append(frameBytes); flush(); }
@Override public void control( IStream stream, ControlFrame frame, long timeout, TimeUnit unit, Callback callback) { generateAndEnqueueControlFrame(stream, frame, timeout, unit, callback); flush(); }
private void onCredential(CredentialFrame frame) { LOG.warn("{} frame not yet supported", frame.getType()); flush(); }
private void onWindowUpdate(WindowUpdateFrame frame) { int streamId = frame.getStreamId(); IStream stream = streams.get(streamId); flowControlStrategy.onWindowUpdate(this, stream, frame.getWindowDelta()); flush(); }