@Override public void succeeded() { super.succeeded(); close(); } }
private void goAway(SessionStatus sessionStatus, long timeout, TimeUnit unit, Callback callback) { if (goAwaySent.compareAndSet(false, true)) { if (!goAwayReceived.get()) { GoAwayFrame frame = new GoAwayFrame(version, lastStreamId.get(), sessionStatus.getCode()); control(null, frame, timeout, unit, callback); return; } } complete(callback); }
private void onSyn(final SynStreamFrame frame) { IStream stream = createStream(frame, null, false, new Promise.Adapter<Stream>() { @Override public void failed(Throwable x) { LOG.debug("Received: {} but creating new Stream failed: {}", frame, x.getMessage()); } }); if (stream != null) processSyn(listener, stream, frame); }
private void onPing(PingFrame frame) { int pingId = frame.getPingId(); if (pingId % 2 == pingIds.get() % 2) { PingResultInfo pingResultInfo = new PingResultInfo(frame.getPingId()); notifyOnPing(listener, pingResultInfo); } else { control(null, frame, 0, TimeUnit.MILLISECONDS, Callback.Adapter.INSTANCE); } }
@Override public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException { SPDYClient client = (SPDYClient)context.get(SPDY_CLIENT_CONTEXT_KEY); SPDYClient.Factory factory = client.getFactory(); ByteBufferPool byteBufferPool = factory.getByteBufferPool(); CompressionFactory compressionFactory = new StandardCompressionFactory(); Parser parser = new Parser(compressionFactory.newDecompressor()); Generator generator = new Generator(byteBufferPool, compressionFactory.newCompressor()); SPDYConnection connection = new ClientSPDYConnection(endPoint, byteBufferPool, parser, factory, client.isDispatchIO()); FlowControlStrategy flowControlStrategy = client.newFlowControlStrategy(); SessionFrameListener listener = (SessionFrameListener)context.get(SPDY_SESSION_LISTENER_CONTEXT_KEY); StandardSession session = new StandardSession(client.getVersion(), byteBufferPool, factory.getScheduler(), connection, endPoint, connection, 1, listener, generator, flowControlStrategy); session.setWindowSize(client.getInitialWindowSize()); parser.addListener(session); connection.setSession(session); @SuppressWarnings("unchecked") Promise<Session> promise = (Promise<Session>)context.get(SPDY_SESSION_PROMISE_CONTEXT_KEY); promise.succeeded(session); return connection; }
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); if (LOG.isDebugEnabled()) 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; if (LOG.isDebugEnabled()) LOG.debug("Updated session maxConcurrentLocalStreams to {}", maxConcurrentStreamsValue); } SettingsInfo settingsInfo = new SettingsInfo(frame.getSettings(), frame.isClearPersisted()); notifyOnSettings(listener, settingsInfo); }
@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 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(frameBytes, throwable); notifyCallbackFailed(callback, x);
@Override public void ping(PingInfo pingInfo, Promise<PingResultInfo> promise) { int pingId = pingIds.getAndAdd(2); PingInfoCallback pingInfoCallback = new PingInfoCallback(pingId, promise); PingFrame frame = new PingFrame(version, pingId); control(null, frame, pingInfo.getTimeout(), pingInfo.getUnit(), pingInfoCallback); }
@Override public void shutdown() { CloseFrameBytes frameBytes = new CloseFrameBytes(); flush(frameBytes, flusher.append(frameBytes)); }
@Override public void control(IStream stream, ControlFrame frame, long timeout, TimeUnit unit, Callback callback) { generateAndEnqueueControlFrame(stream, frame, timeout, unit, callback); }
@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 Connection newConnection(Connector connector, EndPoint endPoint) { CompressionFactory compressionFactory = new StandardCompressionFactory(); Parser parser = new Parser(compressionFactory.newDecompressor()); Generator generator = new Generator(connector.getByteBufferPool(), compressionFactory.newCompressor()); ServerSessionFrameListener listener = provideServerSessionFrameListener(connector, endPoint); SPDYConnection connection = new ServerSPDYConnection(connector, endPoint, parser, listener, isDispatchIO(), getInputBufferSize()); FlowControlStrategy flowControlStrategy = newFlowControlStrategy(version); StandardSession session = new StandardSession(getVersion(), connector.getByteBufferPool(), connector.getScheduler(), connection, endPoint, connection, 2, listener, generator, flowControlStrategy); session.setWindowSize(getInitialWindowSize()); parser.addListener(session); connection.setSession(session); sessionOpened(session); return configure(connection, connector, endPoint); }
@Override public void settings(SettingsInfo settingsInfo, Callback callback) { SettingsFrame frame = new SettingsFrame(version, settingsInfo.getFlags(), settingsInfo.getSettings()); control(null, frame, settingsInfo.getTimeout(), settingsInfo.getUnit(), callback); }
@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)); }
@Override public void run() { close(); failed(new InterruptedByTimeoutException()); }
@Override public void succeeded() { bufferPool.release(buffer); super.succeeded(); 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); }