View Javadoc

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&lt;Void&gt;() { ... });
48   * stream.data(StringDataInfo("chunk2", true), 1, TimeUnit.SECONDS, new Handler&lt;Void&gt;() { ... });
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&lt;Void&gt;()
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 }