View Javadoc

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