com.fireflysource.net.http.common.v2.stream.Stream Maven / Gradle / Ivy
package com.fireflysource.net.http.common.v2.stream;
import com.fireflysource.common.sys.Result;
import com.fireflysource.net.http.common.v2.frame.DataFrame;
import com.fireflysource.net.http.common.v2.frame.HeadersFrame;
import com.fireflysource.net.http.common.v2.frame.PushPromiseFrame;
import com.fireflysource.net.http.common.v2.frame.ResetFrame;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
/**
* A {@link Stream} represents a bidirectional exchange of data on top of a {@link Http2Connection}.
* Differently from socket streams, where the input and output streams permanently associated
* with the socket (and hence with the connection that the socket represents), there can be multiple
* HTTP/2 streams present concurrent for an HTTP/2 session.
* A {@link Stream} maps to an HTTP request/response cycle, and after the request/response cycle completed,
* the stream closed and removed from the session.
* Like {@link Http2Connection}, {@link Stream} is the active part and by calling its API applications
* can generate events on the stream; conversely, {@link Stream.Listener} is the passive part, and
* its results invoked when events happen on the stream.
*
* @see Stream.Listener
*/
public interface Stream {
/**
* @return the stream's unique id
*/
int getId();
/**
* @return the HTTP 2 connection this stream associated to.
*/
Http2Connection getHttp2Connection();
/**
* Sends the given HEADERS {@code frame} representing an HTTP response.
*
* @param frame The HEADERS frame to send.
* @param result The result that gets notified when the frame has been sent.
*/
void headers(HeadersFrame frame, Consumer> result);
/**
* Sends the given HEADERS {@code frame} representing an HTTP response.
*
* @param frame The HEADERS frame to send.
* @return The result that gets notified when the frame has been sent.
*/
default CompletableFuture headers(HeadersFrame frame) {
CompletableFuture future = new CompletableFuture<>();
headers(frame, Result.futureToConsumer(future));
return future;
}
/**
* Sends the given PUSH_PROMISE {@code frame}.
*
* @param frame The PUSH_PROMISE frame to send.
* @param promise The promise that gets notified of the pushed stream creation.
* @param listener The listener that gets notified of stream events.
*/
void push(PushPromiseFrame frame, Consumer> promise, Listener listener);
/**
* Sends the given PUSH_PROMISE {@code frame}.
*
* @param frame The PUSH_PROMISE frame to send.
* @param listener The listener that gets notified of stream events.
* @return The future which gets notified of the pushed stream creation.
*/
default CompletableFuture push(PushPromiseFrame frame, Listener listener) {
CompletableFuture future = new CompletableFuture<>();
push(frame, Result.futureToConsumer(future), listener);
return future;
}
/**
* Sends the given DATA {@code frame}.
*
* @param frame The DATA frame to send.
* @param result The result that gets notified when the frame has been sent.
*/
void data(DataFrame frame, Consumer> result);
/**
* Sends the given DATA {@code frame}.
*
* @param frame The DATA frame to send.
* @return The result that gets notified when the frame has been sent.
*/
default CompletableFuture data(DataFrame frame) {
CompletableFuture future = new CompletableFuture<>();
data(frame, Result.futureToConsumer(future));
return future;
}
/**
* Sends the given RST_STREAM {@code frame}.
*
* @param frame The RST_FRAME to send.
* @param result The result that gets notified when the frame has been sent.
*/
void reset(ResetFrame frame, Consumer> result);
/**
* @param key the attribute key.
* @return An object associated with the given key to this stream.
* or null if no object can be found for the given key.
* @see #setAttribute(String, Object)
*/
Object getAttribute(String key);
/**
* @param key The attribute key.
* @param value An arbitrary object to associate with the given key to this stream.
* @see #getAttribute(String)
* @see #removeAttribute(String)
*/
void setAttribute(String key, Object value);
/**
* @param key The attribute key.
* @return The object associated with the given key to this stream.
* @see #setAttribute(String, Object)
*/
Object removeAttribute(String key);
/**
* @return If true this stream has been reset.
*/
boolean isReset();
/**
* @return If true this stream closed, both locally and remotely.
*/
boolean isClosed();
/**
* @return The stream idle timeout.
* @see #setIdleTimeout(long)
*/
long getIdleTimeout();
/**
* @param idleTimeout The stream idle timeout.
* @see #getIdleTimeout()
* @see Stream.Listener#onIdleTimeout(Stream, Throwable)
*/
void setIdleTimeout(long idleTimeout);
/**
* A {@link Stream.Listener} is the passive counterpart of a {@link Stream} and receives
* events happening on an HTTP/2 stream.
*
* @see Stream
*/
interface Listener {
/**
* Callback method invoked when a HEADERS frame representing the HTTP response has been received.
*
* @param stream The stream.
* @param frame The HEADERS frame received.
*/
void onHeaders(Stream stream, HeadersFrame frame);
/**
* Callback method invoked when a PUSH_PROMISE frame has been received.
*
* @param stream The stream.
* @param frame The PUSH_PROMISE frame received.
* @return A Stream.Listener that will be notified of pushed stream events.
*/
Listener onPush(Stream stream, PushPromiseFrame frame);
/**
* Callback method invoked when a DATA frame has been received.
*
* @param stream The stream.
* @param frame The DATA frame received.
* @param result The result to complete when the bytes of the DATA frame have been consumed.
*/
void onData(Stream stream, DataFrame frame, Consumer> result);
/**
* Callback method invoked when an RST_STREAM frame has been received for this stream.
*
* @param stream The stream.
* @param frame The RST_FRAME received.
* @param result The result to complete when the reset has been handled.
*/
default void onReset(Stream stream, ResetFrame frame, Consumer> result) {
try {
onReset(stream, frame);
result.accept(Result.SUCCESS);
} catch (Throwable x) {
result.accept(Result.createFailedResult(x));
}
}
/**
* Callback method invoked when an RST_STREAM frame has been received for this stream.
*
* @param stream The stream.
* @param frame The RST_FRAME received.
* @see Http2Connection.Listener#onReset(Http2Connection, ResetFrame)
*/
default void onReset(Stream stream, ResetFrame frame) {
}
/**
* Callback method invoked when the stream exceeds its idle timeout.
*
* @param stream The stream.
* @param x The timeout failure.
* @return If true to reset the stream, false to ignore the idle timeout.
* @see #getIdleTimeout()
*/
default boolean onIdleTimeout(Stream stream, Throwable x) {
return true;
}
/**
* Callback method invoked when the stream failed.
*
* @param stream The stream.
* @param error An error code.
* @param reason An error reason, or null.
* @param result The result to complete when the failure has been handled.
*/
default void onFailure(Stream stream, int error, String reason, Consumer> result) {
result.accept(Result.SUCCESS);
}
/**
* Callback method invoked after the stream has been closed.
*
* @param stream The stream.
*/
default void onClosed(Stream stream) {
}
/**
* Callback method invoked after the connection is terminal.
*
* @param stream The stream.
*/
default void onTerminal(Stream stream) {
}
/**
* Empty implementation of {@link Listener}
*/
class Adapter implements Listener {
@Override
public void onHeaders(Stream stream, HeadersFrame frame) {
}
@Override
public Listener onPush(Stream stream, PushPromiseFrame frame) {
return null;
}
@Override
public void onData(Stream stream, DataFrame frame, Consumer> result) {
result.accept(Result.SUCCESS);
}
@Override
public void onReset(Stream stream, ResetFrame frame) {
}
@Override
public boolean onIdleTimeout(Stream stream, Throwable x) {
return true;
}
}
}
}