@Override public int generate(ByteBufferPool.Lease lease, Frame frame) { PushPromiseFrame pushPromiseFrame = (PushPromiseFrame)frame; return generatePushPromise(lease, pushPromiseFrame.getStreamId(), pushPromiseFrame.getPromisedStreamId(), pushPromiseFrame.getMetaData()); }
private void onPushPromise(int streamId, MetaData metaData) { PushPromiseFrame frame = new PushPromiseFrame(getStreamId(), streamId, metaData); notifyPushPromise(frame); }
@Override public void push(IStream stream, Promise<Stream> promise, PushPromiseFrame frame, Stream.Listener listener) { try { // Synchronization is necessary to atomically create // the stream id and enqueue the frame to be sent. boolean queued; synchronized (this) { int streamId = localStreamIds.getAndAdd(2); frame = new PushPromiseFrame(frame.getStreamId(), streamId, frame.getMetaData()); IStream pushStream = createLocalStream(streamId); pushStream.setListener(listener); ControlEntry entry = new ControlEntry(frame, pushStream, new PromiseCallback<>(promise, pushStream)); queued = flusher.append(entry); } // Iterate outside the synchronized block. if (queued) flusher.iterate(); } catch (Throwable x) { promise.failed(x); } }
@Override public void onPushPromise(PushPromiseFrame frame) { if (LOG.isDebugEnabled()) LOG.debug("Received {}", frame); int streamId = frame.getStreamId(); int pushStreamId = frame.getPromisedStreamId(); IStream stream = getStream(streamId); if (stream == null) { if (LOG.isDebugEnabled()) LOG.debug("Ignoring {}, stream #{} not found", frame, streamId); } else { IStream pushStream = createRemoteStream(pushStreamId); if (pushStream != null) { pushStream.process(frame, Callback.NOOP); Stream.Listener listener = notifyPush(stream, pushStream, frame); pushStream.setListener(listener); } } }
@Override public Stream.Listener onPush(Stream stream, PushPromiseFrame frame) { HttpExchange exchange = getHttpExchange(); if (exchange == null) return null; HttpRequest request = exchange.getRequest(); MetaData.Request metaData = (MetaData.Request)frame.getMetaData(); HttpRequest pushRequest = (HttpRequest)getHttpDestination().getHttpClient().newRequest(metaData.getURIString()); // TODO: copy PUSH_PROMISE headers into pushRequest. BiFunction<Request, Request, Response.CompleteListener> pushListener = request.getPushListener(); if (pushListener != null) { Response.CompleteListener listener = pushListener.apply(request, pushRequest); if (listener != null) { HttpChannelOverHTTP2 pushChannel = getHttpChannel().getHttpConnection().acquireHttpChannel(); List<Response.ResponseListener> listeners = Collections.singletonList(listener); HttpExchange pushExchange = new HttpExchange(getHttpDestination(), pushRequest, listeners); pushChannel.associate(pushExchange); pushChannel.setStream(stream); // TODO: idle timeout ? pushExchange.requestComplete(null); pushExchange.terminateRequest(); return pushChannel.getStreamListener(); } } stream.reset(new ResetFrame(stream.getId(), ErrorCode.REFUSED_STREAM_ERROR.code), Callback.NOOP); return null; }
@Override public void push(IStream stream, Promise<Stream> promise, PushPromiseFrame frame, Stream.Listener listener) { try { // Synchronization is necessary to atomically create // the stream id and enqueue the frame to be sent. boolean queued; synchronized (this) { int streamId = localStreamIds.getAndAdd(2); frame = new PushPromiseFrame(frame.getStreamId(), streamId, frame.getMetaData()); IStream pushStream = createLocalStream(streamId); pushStream.setListener(listener); ControlEntry entry = new ControlEntry(frame, pushStream, new StreamPromiseCallback(promise, pushStream)); queued = flusher.append(entry); } // Iterate outside the synchronized block. if (queued) flusher.iterate(); } catch (Throwable x) { promise.failed(x); } }
@Override public int generate(ByteBufferPool.Lease lease, Frame frame) { PushPromiseFrame pushPromiseFrame = (PushPromiseFrame)frame; return generatePushPromise(lease, pushPromiseFrame.getStreamId(), pushPromiseFrame.getPromisedStreamId(), pushPromiseFrame.getMetaData()); }
private void onPushPromise(int streamId, MetaData metaData) { PushPromiseFrame frame = new PushPromiseFrame(getStreamId(), streamId, metaData); notifyPushPromise(frame); }
@Override public void push(final MetaData.Request request) { if (!stream.getSession().isPushEnabled()) { if (LOG.isDebugEnabled()) LOG.debug("HTTP/2 Push disabled for {}", request); return; } if (LOG.isDebugEnabled()) LOG.debug("HTTP/2 Push {}", request); stream.push(new PushPromiseFrame(stream.getId(), 0, request), new Promise<Stream>() { @Override public void succeeded(Stream pushStream) { connection.push(connector, (IStream)pushStream, request); } @Override public void failed(Throwable x) { if (LOG.isDebugEnabled()) LOG.debug("Could not push " + request, x); } }, new Stream.Listener.Adapter()); // TODO: handle reset from the client ? }