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 }