1 // 2 // ======================================================================== 3 // Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // All rights reserved. This program and the accompanying materials 6 // are made available under the terms of the Eclipse Public License v1.0 7 // and Apache License v2.0 which accompanies this distribution. 8 // 9 // The Eclipse Public License is available at 10 // http://www.eclipse.org/legal/epl-v10.html 11 // 12 // The Apache License v2.0 is available at 13 // http://www.opensource.org/licenses/apache2.0.php 14 // 15 // You may elect to redistribute this code under either of these licenses. 16 // ======================================================================== 17 // 18 19 package org.eclipse.jetty.spdy.api; 20 21 import java.nio.channels.WritePendingException; 22 import java.util.Set; 23 import java.util.concurrent.Future; 24 import java.util.concurrent.TimeUnit; 25 26 /** 27 * <p>A {@link Stream} represents a bidirectional exchange of data on top of a {@link Session}.</p> 28 * <p>Differently from socket streams, where the input and output streams are permanently associated 29 * with the socket (and hence with the connection that the socket represents), there can be multiple 30 * SPDY streams for a SPDY session.</p> 31 * <p>SPDY streams may terminate without this implying that the SPDY session is terminated.</p> 32 * <p>If SPDY is used to transport the HTTP protocol, then a SPDY stream maps to a HTTP request/response 33 * cycle, and after the request/response cycle is completed, the stream is closed, and other streams 34 * may be opened. Differently from HTTP, though, multiple SPDY streams may be opened concurrently 35 * on the same SPDY session.</p> 36 * <p>Like {@link Session}, {@link Stream} is the active part and by calling its API applications 37 * can generate events on the stream; conversely, {@link StreamFrameListener} is the passive part, and its 38 * callbacks are invoked when events happen on the stream.</p> 39 * <p>A {@link Stream} can send multiple data frames one after the other but implementations use a 40 * flow control mechanism that only sends the data frames if the other end has signalled that it can 41 * accept the frame.</p> 42 * <p>Data frames should be sent sequentially only when the previous frame has been completely sent. 43 * The reason for this requirement is to avoid potentially confusing code such as:</p> 44 * <pre> 45 * // WRONG CODE, DO NOT USE IT 46 * final Stream stream = ...; 47 * stream.data(StringDataInfo("chunk1", false), 5, TimeUnit.SECONDS, new Handler<Void>() { ... }); 48 * stream.data(StringDataInfo("chunk2", true), 1, TimeUnit.SECONDS, new Handler<Void>() { ... }); 49 * </pre> 50 * <p>where the second call to {@link #data(DataInfo, long, TimeUnit, Handler)} has a timeout smaller 51 * than the previous call.</p> 52 * <p>The behavior of such style of invocations is unspecified (it may even throw an exception - similar 53 * to {@link WritePendingException}).</p> 54 * <p>The correct sending of data frames is the following:</p> 55 * <pre> 56 * final Stream stream = ...; 57 * ... 58 * // Blocking version 59 * stream.data(new StringDataInfo("chunk1", false)).get(1, TimeUnit.SECONDS); 60 * stream.data(new StringDataInfo("chunk2", true)).get(1, TimeUnit.SECONDS); 61 * 62 * // Asynchronous version 63 * stream.data(new StringDataInfo("chunk1", false), 1, TimeUnit.SECONDS, new Handler.Adapter<Void>() 64 * { 65 * public void completed(Void context) 66 * { 67 * stream.data(new StringDataInfo("chunk2", true)); 68 * } 69 * }); 70 * </pre> 71 * 72 * @see StreamFrameListener 73 */ 74 public interface Stream 75 { 76 /** 77 * @return the id of this stream 78 */ 79 public int getId(); 80 81 /** 82 * @return the priority of this stream 83 */ 84 public byte getPriority(); 85 86 /** 87 * @return the session this stream is associated to 88 */ 89 public Session getSession(); 90 91 /** 92 * <p>Initiate a unidirectional spdy pushstream associated to this stream asynchronously<p> 93 * <p>Callers may use the returned future to get the pushstream once it got created</p> 94 * 95 * @param synInfo the metadata to send on stream creation 96 * @return a future containing the stream once it got established 97 * @see #syn(SynInfo, long, TimeUnit, Handler) 98 */ 99 public Future<Stream> syn(SynInfo synInfo); 100 101 /** 102 * <p>Initiate a unidirectional spdy pushstream associated to this stream asynchronously<p> 103 * <p>Callers may pass a non-null completion handler to be notified of when the 104 * pushstream has been established.</p> 105 * 106 * @param synInfo the metadata to send on stream creation 107 * @param timeout the operation's timeout 108 * @param unit the timeout's unit 109 * @param handler the completion handler that gets notified once the pushstream is established 110 * @see #syn(SynInfo) 111 */ 112 public void syn(SynInfo synInfo, long timeout, TimeUnit unit, Handler<Stream> handler); 113 114 /** 115 * <p>Sends asynchronously a SYN_REPLY frame in response to a SYN_STREAM frame.</p> 116 * <p>Callers may use the returned future to wait for the reply to be actually sent.</p> 117 * 118 * @param replyInfo the metadata to send 119 * @return a future to wait for the reply to be sent 120 * @see #reply(ReplyInfo, long, TimeUnit, Handler) 121 * @see SessionFrameListener#onSyn(Stream, SynInfo) 122 */ 123 public Future<Void> reply(ReplyInfo replyInfo); 124 125 /** 126 * <p>Sends asynchronously a SYN_REPLY frame in response to a SYN_STREAM frame.</p> 127 * <p>Callers may pass a non-null completion handler to be notified of when the 128 * reply has been actually sent.</p> 129 * 130 * @param replyInfo the metadata to send 131 * @param timeout the operation's timeout 132 * @param unit the timeout's unit 133 * @param handler the completion handler that gets notified of reply sent 134 * @see #reply(ReplyInfo) 135 */ 136 public void reply(ReplyInfo replyInfo, long timeout, TimeUnit unit, Handler<Void> handler); 137 138 /** 139 * <p>Sends asynchronously a DATA frame on this stream.</p> 140 * <p>DATA frames should always be sent after a SYN_REPLY frame.</p> 141 * <p>Callers may use the returned future to wait for the data to be actually sent.</p> 142 * 143 * @param dataInfo the metadata to send 144 * @return a future to wait for the data to be sent 145 * @see #data(DataInfo, long, TimeUnit, Handler) 146 * @see #reply(ReplyInfo) 147 */ 148 public Future<Void> data(DataInfo dataInfo); 149 150 /** 151 * <p>Sends asynchronously a DATA frame on this stream.</p> 152 * <p>DATA frames should always be sent after a SYN_REPLY frame.</p> 153 * <p>Callers may pass a non-null completion handler to be notified of when the 154 * data has been actually sent.</p> 155 * 156 * @param dataInfo the metadata to send 157 * @param timeout the operation's timeout 158 * @param unit the timeout's unit 159 * @param handler the completion handler that gets notified of data sent 160 * @see #data(DataInfo) 161 */ 162 public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Handler<Void> handler); 163 164 /** 165 * <p>Sends asynchronously a HEADER frame on this stream.</p> 166 * <p>HEADERS frames should always be sent after a SYN_REPLY frame.</p> 167 * <p>Callers may use the returned future to wait for the headers to be actually sent.</p> 168 * 169 * @param headersInfo the metadata to send 170 * @return a future to wait for the headers to be sent 171 * @see #headers(HeadersInfo, long, TimeUnit, Handler) 172 * @see #reply(ReplyInfo) 173 */ 174 public Future<Void> headers(HeadersInfo headersInfo); 175 176 /** 177 * <p>Sends asynchronously a HEADER frame on this stream.</p> 178 * <p>HEADERS frames should always be sent after a SYN_REPLY frame.</p> 179 * <p>Callers may pass a non-null completion handler to be notified of when the 180 * headers have been actually sent.</p> 181 * 182 * @param headersInfo the metadata to send 183 * @param timeout the operation's timeout 184 * @param unit the timeout's unit 185 * @param handler the completion handler that gets notified of headers sent 186 * @see #headers(HeadersInfo) 187 */ 188 public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Handler<Void> handler); 189 190 /** 191 * @return whether this stream is unidirectional or not 192 */ 193 public boolean isUnidirectional(); 194 195 /** 196 * @return whether this stream has been reset 197 */ 198 public boolean isReset(); 199 200 /** 201 * @return whether this stream has been closed by both parties 202 * @see #isHalfClosed() 203 */ 204 public boolean isClosed(); 205 206 /** 207 * @return whether this stream has been closed by one party only 208 * @see #isClosed() 209 */ 210 public boolean isHalfClosed(); 211 212 /** 213 * @param key the attribute key 214 * @return an arbitrary object associated with the given key to this stream 215 * @see #setAttribute(String, Object) 216 */ 217 public Object getAttribute(String key); 218 219 /** 220 * @param key the attribute key 221 * @param value an arbitrary object to associate with the given key to this stream 222 * @see #getAttribute(String) 223 * @see #removeAttribute(String) 224 */ 225 public void setAttribute(String key, Object value); 226 227 /** 228 * @param key the attribute key 229 * @return the arbitrary object associated with the given key to this stream 230 * @see #setAttribute(String, Object) 231 */ 232 public Object removeAttribute(String key); 233 234 /** 235 * @return the associated parent stream or null if this is not an associated stream 236 */ 237 public Stream getAssociatedStream(); 238 239 /** 240 * @return associated child streams or an empty set if no associated streams exist 241 */ 242 public Set<Stream> getPushedStreams(); 243 244 }