@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); } }
/** * @return the close flag as integer * @see #FLAG_CLOSE */ public byte getFlags() { return isClose() ? FLAG_CLOSE : 0; }
@Override public Stream syn(SynInfo synInfo, StreamFrameListener listener) throws ExecutionException, InterruptedException, TimeoutException { FuturePromise<Stream> result = new FuturePromise<>(); syn(synInfo, listener, result); if (synInfo.getTimeout() > 0) return result.get(synInfo.getTimeout(), synInfo.getUnit()); else return result.get(); }
@Override public StreamFrameListener onSyn(Stream serverStream, SynInfo serverSynInfo) { logger.debug("S -> P pushed {} on {}", serverSynInfo, serverStream); Headers headers = new Headers(serverSynInfo.getHeaders(), false); addResponseProxyHeaders(serverStream, headers); customizeResponseHeaders(serverStream, headers); Stream clientStream = (Stream)serverStream.getAssociatedStream().getAttribute(CLIENT_STREAM_ATTRIBUTE); convert(serverStream.getSession().getVersion(), clientStream.getSession().getVersion(), headers); StreamHandler handler = new StreamHandler(clientStream, serverSynInfo); serverStream.setAttribute(STREAM_HANDLER_ATTRIBUTE, handler); clientStream.syn(new SynInfo(headers, serverSynInfo.isClose()), getTimeout(), TimeUnit.MILLISECONDS, handler); return this; }
@Override public StreamFrameListener onSyn(final Stream stream, SynInfo synInfo) { // Every time we have a SYN, it maps to a HTTP request. // We can have multiple concurrent SYNs on the same connection, // and this is very different from HTTP, where only one request/response // cycle is processed at a time, so we need to fake an http connection // for each SYN in order to run concurrently. logger.debug("Received {} on {}", synInfo, stream); HTTPSPDYAsyncEndPoint asyncEndPoint = new HTTPSPDYAsyncEndPoint(endPoint, stream); ServerHTTPSPDYAsyncConnection connection = new ServerHTTPSPDYAsyncConnection(connector, asyncEndPoint, connector.getServer(), getVersion(), (SPDYAsyncConnection)endPoint.getConnection(), pushStrategy, stream); asyncEndPoint.setConnection(connection); stream.setAttribute(CONNECTION_ATTRIBUTE, connection); Headers headers = synInfo.getHeaders(); connection.beginRequest(headers, synInfo.isClose()); if (headers.isEmpty()) { // If the SYN has no headers, they may come later in a HEADERS frame return this; } else { if (synInfo.isClose()) return null; else return this; } }
private HTTPStream syn(boolean close) { HTTPStream stream = new HTTPStream(1, (byte)0, session, null); StreamFrameListener streamFrameListener = proxyEngineSelector.onSyn(stream, new SynInfo(headers, close)); stream.setStreamFrameListener(streamFrameListener); return stream; }
Headers headers = new Headers(clientSynInfo.getHeaders(), false);
/** * @return the close and unidirectional flags as integer * @see #FLAG_CLOSE * @see #FLAG_UNIDIRECTIONAL */ @Override public byte getFlags() { byte flags = super.getFlags(); flags += FLAG_UNIDIRECTIONAL; return flags; }
public StreamFrameListener proxy(final Stream clientStream, SynInfo clientSynInfo, ProxyEngineSelector.ProxyServerInfo proxyServerInfo) { Fields headers = new Fields(clientSynInfo.getHeaders(), false); short serverVersion = getVersion(proxyServerInfo.getProtocol()); InetSocketAddress address = proxyServerInfo.getAddress(); Session serverSession = produceSession(proxyServerInfo.getHost(), serverVersion, address); if (serverSession == null) { rst(clientStream); return null; } final Session clientSession = clientStream.getSession(); addRequestProxyHeaders(clientStream, headers); customizeRequestHeaders(clientStream, headers); convert(clientSession.getVersion(), serverVersion, headers); SynInfo serverSynInfo = new SynInfo(headers, clientSynInfo.isClose()); StreamFrameListener listener = new ProxyStreamFrameListener(clientStream); StreamPromise promise = new StreamPromise(clientStream, serverSynInfo); clientStream.setAttribute(STREAM_PROMISE_ATTRIBUTE, promise); serverSession.syn(serverSynInfo, listener, promise); return this; }
LOG.debug("Received {} on {}", synInfo, stream); Fields headers = synInfo.getHeaders(); stream.setAttribute(CHANNEL_ATTRIBUTE, channel); channel.requestStart(headers, synInfo.isClose()); if (synInfo.isClose()) return null; else
private HTTPStream syn(boolean close) { HTTPStream stream = new HTTPStream(1, (byte)0, session, null); StreamFrameListener streamFrameListener = proxyEngineSelector.onSyn(stream, new SynInfo(headers, close)); stream.setStreamFrameListener(streamFrameListener); return stream; }
Fields headers = new Fields(clientSynInfo.getHeaders(), false);
public StreamFrameListener proxy(final Stream clientStream, SynInfo clientSynInfo, ProxyEngineSelector.ProxyServerInfo proxyServerInfo) { Headers headers = new Headers(clientSynInfo.getHeaders(), false); short serverVersion = getVersion(proxyServerInfo.getProtocol()); InetSocketAddress address = proxyServerInfo.getAddress(); Session serverSession = produceSession(proxyServerInfo.getHost(), serverVersion, address); if (serverSession == null) { rst(clientStream); return null; } final Session clientSession = clientStream.getSession(); addRequestProxyHeaders(clientStream, headers); customizeRequestHeaders(clientStream, headers); convert(clientSession.getVersion(), serverVersion, headers); SynInfo serverSynInfo = new SynInfo(headers, clientSynInfo.isClose()); StreamFrameListener listener = new ProxyStreamFrameListener(clientStream); StreamHandler handler = new StreamHandler(clientStream, serverSynInfo); clientStream.setAttribute(STREAM_HANDLER_ATTRIBUTE, handler); serverSession.syn(serverSynInfo, listener, timeout, TimeUnit.MILLISECONDS, handler); return this; }
public StreamFrameListener proxy(final Stream clientStream, SynInfo clientSynInfo, ProxyEngineSelector.ProxyServerInfo proxyServerInfo) String method = clientSynInfo.getHeaders().get(HTTPSPDYHeader.METHOD.name(version)).getValue(); String path = clientSynInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version)).getValue(); Fields headers = new Fields(clientSynInfo.getHeaders(), false); addNonSpdyHeadersToRequest(version, headers, request); if (!clientSynInfo.isClose())
protected void reply(Stream stream, ReplyInfo replyInfo) { if (!stream.isUnidirectional()) stream.reply(replyInfo); if (replyInfo.getHeaders().get(HTTPSPDYHeader.STATUS.name(version)).value().startsWith("200") && !stream.isClosed()) { // We have a 200 OK with some content to send Headers.Header scheme = headers.get(HTTPSPDYHeader.SCHEME.name(version)); Headers.Header host = headers.get(HTTPSPDYHeader.HOST.name(version)); Headers.Header uri = headers.get(HTTPSPDYHeader.URI.name(version)); Set<String> pushResources = pushStrategy.apply(stream, headers, replyInfo.getHeaders()); for (String pushResourcePath : pushResources) { final Headers requestHeaders = createRequestHeaders(scheme, host, uri, pushResourcePath); final Headers pushHeaders = createPushHeaders(scheme, host, pushResourcePath); stream.syn(new SynInfo(pushHeaders, false), getMaxIdleTime(), TimeUnit.MILLISECONDS, new Handler.Adapter<Stream>() { @Override public void completed(Stream pushStream) { ServerHTTPSPDYAsyncConnection pushConnection = new ServerHTTPSPDYAsyncConnection(getConnector(), getEndPoint(), getServer(), version, connection, pushStrategy, pushStream); pushConnection.beginRequest(requestHeaders, true); } }); } } }
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); // The onSyn() listener may have sent a frame that closed the stream if (stream.isClosed()) removeStream(stream); }