View Javadoc

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