1 module hunt.http.codec.http.stream.Stream; 2 3 import hunt.http.codec.http.frame.DataFrame; 4 import hunt.http.codec.http.frame.HeadersFrame; 5 import hunt.http.codec.http.frame.PushPromiseFrame; 6 import hunt.http.codec.http.frame.ResetFrame; 7 import hunt.http.codec.http.stream.Session; 8 9 import hunt.util.Common; 10 import hunt.concurrency.Promise; 11 12 13 alias StreamListener = Stream.Listener; 14 15 /** 16 * <p> 17 * A {@link Stream} represents a bidirectional exchange of data on top of a 18 * {@link Session}. 19 * </p> 20 * <p> 21 * Differently from socket streams, where the input and output streams are 22 * permanently associated with the socket (and hence with the connection that 23 * the socket represents), there can be multiple HTTP/2 streams present 24 * concurrent for a HTTP/2 session. 25 * </p> 26 * <p> 27 * A {@link Stream} maps to a HTTP request/response cycle, and after the 28 * request/response cycle is completed, the stream is closed and removed from 29 * the session. 30 * </p> 31 * <p> 32 * Like {@link Session}, {@link Stream} is the active part and by calling its 33 * API applications can generate events on the stream; conversely, 34 * {@link Stream.Listener} is the passive part, and its callbacks are invoked 35 * when events happen on the stream. 36 * </p> 37 * 38 * @see Stream.Listener 39 */ 40 interface Stream { 41 /** 42 * @return the stream unique id 43 */ 44 int getId(); 45 46 /** 47 * @return the session this stream is associated to 48 */ 49 Session getSession(); 50 51 /** 52 * <p>Sends the given HEADERS {@code frame} representing a HTTP response.</p> 53 * 54 * @param frame the HEADERS frame to send 55 * @param callback the callback that gets notified when the frame has been sent 56 */ 57 void headers(HeadersFrame frame, Callback callback); 58 59 /** 60 * <p>Sends the given PUSH_PROMISE {@code frame}.</p> 61 * 62 * @param frame the PUSH_PROMISE frame to send 63 * @param promise the promise that gets notified of the pushed stream creation 64 * @param listener the listener that gets notified of stream events 65 */ 66 void push(PushPromiseFrame frame, Promise!Stream promise, Listener listener); 67 68 /** 69 * <p>Sends the given DATA {@code frame}.</p> 70 * 71 * @param frame the DATA frame to send 72 * @param callback the callback that gets notified when the frame has been sent 73 */ 74 void data(DataFrame frame, Callback callback); 75 76 /** 77 * <p>Sends the given RST_STREAM {@code frame}.</p> 78 * 79 * @param frame the RST_FRAME to send 80 * @param callback the callback that gets notified when the frame has been sent 81 */ 82 void reset(ResetFrame frame, Callback callback); 83 84 /** 85 * @param key the attribute key 86 * @return an arbitrary object associated with the given key to this stream 87 * or null if no object can be found for the given key. 88 * @see #setAttribute(string, Object) 89 */ 90 Object getAttribute(string key); 91 92 /** 93 * @param key the attribute key 94 * @param value an arbitrary object to associate with the given key to this stream 95 * @see #getAttribute(string) 96 * @see #removeAttribute(string) 97 */ 98 void setAttribute(string key, Object value); 99 100 /** 101 * @param key the attribute key 102 * @return the arbitrary object associated with the given key to this stream 103 * @see #setAttribute(string, Object) 104 */ 105 Object removeAttribute(string key); 106 107 /** 108 * @return whether this stream has been reset 109 */ 110 bool isReset(); 111 112 /** 113 * @return whether this stream is closed, both locally and remotely. 114 */ 115 bool isClosed(); 116 117 /** 118 * @return the stream idle timeout 119 * @see #setIdleTimeout(long) 120 */ 121 // long getIdleTimeout(); 122 123 /** 124 * @param idleTimeout the stream idle timeout 125 * @see #getIdleTimeout() 126 * @see Stream.Listener#onIdleTimeout(Stream, Exception) 127 */ 128 // void setIdleTimeout(long idleTimeout); 129 130 string toString(); 131 132 /** 133 * <p>A {@link Stream.Listener} is the passive counterpart of a {@link Stream} and receives 134 * events happening on a HTTP/2 stream.</p> 135 * 136 * @see Stream 137 */ 138 interface Listener { 139 /** 140 * <p>Callback method invoked when a HEADERS frame representing the HTTP response has been received.</p> 141 * 142 * @param stream the stream 143 * @param frame the HEADERS frame received 144 */ 145 void onHeaders(Stream stream, HeadersFrame frame); 146 147 /** 148 * <p>Callback method invoked when a PUSH_PROMISE frame has been received.</p> 149 * 150 * @param stream the stream 151 * @param frame the PUSH_PROMISE frame received 152 * @return a Stream.Listener that will be notified of pushed stream events 153 */ 154 Listener onPush(Stream stream, PushPromiseFrame frame); 155 156 /** 157 * <p>Callback method invoked when a DATA frame has been received.</p> 158 * 159 * @param stream the stream 160 * @param frame the DATA frame received 161 * @param callback the callback to complete when the bytes of the DATA frame have been consumed 162 */ 163 void onData(Stream stream, DataFrame frame, Callback callback); 164 165 void onReset(Stream stream, ResetFrame frame, Callback callback); 166 167 // void onReset(Stream stream, ResetFrame frame, Callback callback) { 168 // try { 169 // onReset(stream, frame); 170 // callback.succeeded(); 171 // } catch (Exception x) { 172 // callback.failed(x); 173 // } 174 // } 175 176 /** 177 * <p>Callback method invoked when a RST_STREAM frame has been received for this stream.</p> 178 * 179 * @param stream the stream 180 * @param frame the RST_FRAME received 181 * @see Session.Listener#onReset(Session, ResetFrame) 182 */ 183 void onReset(Stream stream, ResetFrame frame); 184 185 /** 186 * <p>Callback method invoked when the stream exceeds its idle timeout.</p> 187 * 188 * @param stream the stream 189 * @param x the timeout failure 190 * @see #getIdleTimeout() 191 * @deprecated use {@link #onIdleTimeout(Stream, Exception)} instead 192 */ 193 // deprecated("") 194 // default void onTimeout(Stream stream, Exception x) { 195 // } 196 197 /** 198 * <p>Callback method invoked when the stream exceeds its idle timeout.</p> 199 * 200 * @param stream the stream 201 * @param x the timeout failure 202 * @return true to reset the stream, false to ignore the idle timeout 203 * @see #getIdleTimeout() 204 */ 205 bool onIdleTimeout(Stream stream, Exception x); 206 207 string toString(); 208 209 210 /** 211 * <p>Empty implementation of {@link Listener}</p> 212 */ 213 static class Adapter : Listener { 214 215 void onHeaders(Stream stream, HeadersFrame frame) { 216 } 217 218 219 Listener onPush(Stream stream, PushPromiseFrame frame) { 220 return null; 221 } 222 223 224 void onData(Stream stream, DataFrame frame, Callback callback) { 225 callback.succeeded(); 226 } 227 228 void onReset(Stream stream, ResetFrame frame, Callback callback) { 229 try { 230 onReset(stream, frame); 231 callback.succeeded(); 232 } catch (Exception x) { 233 callback.failed(x); 234 } 235 } 236 237 void onReset(Stream stream, ResetFrame frame) { 238 } 239 240 void onTimeout(Stream stream, Exception x) { 241 } 242 243 244 bool onIdleTimeout(Stream stream, Exception x) { 245 return true; 246 } 247 248 249 override string toString() 250 { 251 return super.toString(); 252 } 253 } 254 } 255 }