• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.net;
6 
7 import android.annotation.SuppressLint;
8 import androidx.annotation.NonNull;
9 
10 import java.nio.ByteBuffer;
11 import java.util.concurrent.Executor;
12 
13 /**
14  * Class for bidirectional sending and receiving of data over HTTP/2 or QUIC connections. Created by
15  * {@link Builder}.
16  *
17  * <p>Note: There are ordering restrictions on methods of {@link BidirectionalStream}; please see
18  * individual methods for description of restrictions.
19  *
20  * {@hide crbug/1394772: needs review before we expose to aosp}
21  */
22 public abstract class BidirectionalStream {
23     /**
24      * Builder for {@link BidirectionalStream}s. Allows configuring stream before constructing it
25      * via
26      * {@link Builder#build}. Created by {@link CronetEngine#newBidirectionalStreamBuilder}.
27      */
28     public abstract static class Builder {
29         /**
30          * Sets the HTTP method for the request. Returns builder to facilitate chaining.
31          *
32          * @param method the method to use for request. Default is 'POST'
33          * @return the builder to facilitate chaining
34          */
setHttpMethod(String method)35         public abstract Builder setHttpMethod(String method);
36 
37         /**
38          * Adds a request header. Returns builder to facilitate chaining.
39          *
40          * @param header the header name
41          * @param value the header value
42          * @return the builder to facilitate chaining
43          */
addHeader(String header, String value)44         public abstract Builder addHeader(String header, String value);
45 
46         /** Lowest stream priority. Passed to {@link #setPriority}. */
47         public static final int STREAM_PRIORITY_IDLE = 0;
48 
49         /** Very low stream priority. Passed to {@link #setPriority}. */
50         public static final int STREAM_PRIORITY_LOWEST = 1;
51 
52         /** Low stream priority. Passed to {@link #setPriority}. */
53         public static final int STREAM_PRIORITY_LOW = 2;
54 
55         /**
56          * Medium stream priority. Passed to {@link #setPriority}. This is the default priority
57          * given to the stream.
58          */
59         public static final int STREAM_PRIORITY_MEDIUM = 3;
60 
61         /** Highest stream priority. Passed to {@link #setPriority}. */
62         public static final int STREAM_PRIORITY_HIGHEST = 4;
63 
64         /**
65          * Sets priority of the stream which should be one of the {@link #STREAM_PRIORITY_IDLE
66          * STREAM_PRIORITY_*} values. The stream is given {@link #STREAM_PRIORITY_MEDIUM} priority
67          * if this method is not called.
68          *
69          * @param priority priority of the stream which should be one of the {@link
70          * #STREAM_PRIORITY_IDLE STREAM_PRIORITY_*} values.
71          * @return the builder to facilitate chaining.
72          */
setPriority(int priority)73         public abstract Builder setPriority(int priority);
74 
75         /**
76          * Delays sending request headers until {@link BidirectionalStream#flush()} is called. This
77          * flag is currently only respected when QUIC is negotiated. When true, QUIC will send
78          * request header frame along with data frame(s) as a single packet when possible.
79          *
80          * @param delayRequestHeadersUntilFirstFlush if true, sending request headers will be
81          *         delayed
82          * until flush() is called.
83          * @return the builder to facilitate chaining.
84          */
delayRequestHeadersUntilFirstFlush( boolean delayRequestHeadersUntilFirstFlush)85         public abstract Builder delayRequestHeadersUntilFirstFlush(
86                 boolean delayRequestHeadersUntilFirstFlush);
87 
88         /**
89          * Associates the annotation object with this request. May add more than one. Passed through
90          * to a {@link RequestFinishedInfo.Listener}, see {@link
91          * RequestFinishedInfo#getAnnotations}.
92          *
93          * @param annotation an object to pass on to the {@link RequestFinishedInfo.Listener} with a
94          * {@link RequestFinishedInfo}.
95          * @return the builder to facilitate chaining.
96          */
addRequestAnnotation(Object annotation)97         public Builder addRequestAnnotation(Object annotation) {
98             return this;
99         }
100 
101         /**
102          * Sets {@link android.net.TrafficStats} tag to use when accounting socket traffic caused by
103          * this request. See {@link android.net.TrafficStats} for more information. If no tag is set
104          * (e.g. this method isn't called), then Android accounts for the socket traffic caused by
105          * this request as if the tag value were set to 0. <p> <b>NOTE:</b>Setting a tag disallows
106          * sharing of sockets with requests with other tags, which may adversely effect performance
107          * by prohibiting connection sharing. In other words use of multiplexed sockets (e.g. HTTP/2
108          * and QUIC) will only be allowed if all requests have the same socket tag.
109          *
110          * @param tag the tag value used to when accounting for socket traffic caused by this
111          *         request.
112          * Tags between 0xFFFFFF00 and 0xFFFFFFFF are reserved and used internally by system
113          * services like {@link android.app.DownloadManager} when performing traffic on behalf of an
114          * application.
115          * @return the builder to facilitate chaining.
116          */
setTrafficStatsTag(int tag)117         public Builder setTrafficStatsTag(int tag) {
118             return this;
119         }
120 
121         /**
122          * Sets specific UID to use when accounting socket traffic caused by this request. See
123          * {@link android.net.TrafficStats} for more information. Designed for use when performing
124          * an operation on behalf of another application. Caller must hold {@code
125          * MODIFY_NETWORK_ACCOUNTING} permission. By default traffic is attributed to UID of caller.
126          *
127          * <p><b>NOTE:</b>Setting a UID disallows sharing of sockets with requests with other UIDs,
128          * which may adversely effect performance by prohibiting connection sharing. In other words
129          * use of multiplexed sockets (e.g. HTTP/2 and QUIC) will only be allowed if all requests
130          * have the same UID set.
131          *
132          * @param uid the UID to attribute socket traffic caused by this request.
133          * @return the builder to facilitate chaining.
134          */
setTrafficStatsUid(int uid)135         public Builder setTrafficStatsUid(int uid) {
136             return this;
137         }
138 
139         /**
140          * Binds the request to the specified network handle. Cronet will send this request only
141          * using the network associated to this handle. If this network disconnects the request will
142          * fail, the exact error will depend on the stage of request processing when the network
143          * disconnects. Network handles can be obtained through {@code Network#getNetworkHandle}.
144          * Only available starting from Android Marshmallow.
145          *
146          * @param networkHandle the network handle to bind the request to. Specify {@link
147          * CronetEngine#UNBIND_NETWORK_HANDLE} to unbind.
148          * @return the builder to facilitate chaining.
149          */
bindToNetwork(long networkHandle)150         public Builder bindToNetwork(long networkHandle) {
151             return this;
152         }
153 
154         /**
155          * Creates a {@link BidirectionalStream} using configuration from this {@link Builder}. The
156          * returned {@code BidirectionalStream} can then be started by calling {@link
157          * BidirectionalStream#start}.
158          *
159          * @return constructed {@link BidirectionalStream} using configuration from this {@link
160          *         Builder}
161          */
162         @SuppressLint("WrongConstant") // TODO(jbudorick): Remove this after rolling to the N SDK.
build()163         public abstract BidirectionalStream build();
164     }
165 
166     /** Callback class used to receive callbacks from a {@link BidirectionalStream}. */
167     public abstract static class Callback {
168         /**
169          * Invoked when the stream is ready for reading and writing. Consumer may call {@link
170          * BidirectionalStream#read read()} to start reading data. Consumer may call {@link
171          * BidirectionalStream#write write()} to start writing data.
172          *
173          * @param stream the stream that is ready.
174          */
onStreamReady(BidirectionalStream stream)175         public abstract void onStreamReady(BidirectionalStream stream);
176 
177         /**
178          * Invoked when initial response headers are received. Headers are available from {@code
179          * info.}{@link UrlResponseInfo#getAllHeaders getAllHeaders()}. Consumer may call {@link
180          * BidirectionalStream#read read()} to start reading. Consumer may call {@link
181          * BidirectionalStream#write write()} to start writing or close the stream.
182          *
183          * @param stream the stream on which response headers were received.
184          * @param info the response information.
185          */
onResponseHeadersReceived( BidirectionalStream stream, UrlResponseInfo info)186         public abstract void onResponseHeadersReceived(
187                 BidirectionalStream stream, UrlResponseInfo info);
188 
189         /**
190          * Invoked when data is read into the buffer passed to {@link BidirectionalStream#read
191          * read()}. Only part of the buffer may be populated. To continue reading, call {@link
192          * BidirectionalStream#read read()}. It may be invoked after {@code
193          * onResponseTrailersReceived()}, if there was pending read data before trailers were
194          * received.
195          *
196          * @param stream the stream on which the read completed
197          * @param info the response information
198          * @param buffer the buffer that was passed to {@link BidirectionalStream#read read()}, now
199          * containing the received data. The buffer's limit is not changed. The buffer's position is
200          * set to the end of the received data. If position is not updated, it means the remote side
201          * has signaled that it will send no more data.
202          * @param endOfStream if true, this is the last read data, remote will not send more data,
203          *         and
204          * the read side is closed.
205          */
onReadCompleted( BidirectionalStream stream, UrlResponseInfo info, ByteBuffer buffer, boolean endOfStream)206         public abstract void onReadCompleted(
207                 BidirectionalStream stream,
208                 UrlResponseInfo info,
209                 ByteBuffer buffer,
210                 boolean endOfStream);
211 
212         /**
213          * Invoked when the entire ByteBuffer passed to {@link BidirectionalStream#write write()} is
214          * sent. The buffer's position is updated to be the same as the buffer's limit. The buffer's
215          * limit is not changed. To continue writing, call {@link BidirectionalStream#write
216          * write()}.
217          *
218          * @param stream the stream on which the write completed
219          * @param info the response information
220          * @param buffer the buffer that was passed to {@link BidirectionalStream#write write()}.
221          *         The
222          * buffer's position is set to the buffer's limit. The buffer's limit is not changed.
223          * @param endOfStream the endOfStream flag that was passed to the corresponding {@link
224          * BidirectionalStream#write write()}. If true, the write side is closed.
225          */
onWriteCompleted( BidirectionalStream stream, UrlResponseInfo info, ByteBuffer buffer, boolean endOfStream)226         public abstract void onWriteCompleted(
227                 BidirectionalStream stream,
228                 UrlResponseInfo info,
229                 ByteBuffer buffer,
230                 boolean endOfStream);
231 
232         /**
233          * Invoked when trailers are received before closing the stream. Only invoked when server
234          * sends trailers, which it may not. May be invoked while there is read data remaining in
235          * local buffer.
236          *
237          * Default implementation takes no action.
238          *
239          * @param stream the stream on which response trailers were received
240          * @param info the response information
241          * @param trailers the trailers received
242          */
onResponseTrailersReceived( BidirectionalStream stream, UrlResponseInfo info, UrlResponseInfo.HeaderBlock trailers)243         public void onResponseTrailersReceived(
244                 BidirectionalStream stream,
245                 UrlResponseInfo info,
246                 UrlResponseInfo.HeaderBlock trailers) {}
247 
248         /**
249          * Invoked when there is no data to be read or written and the stream is closed successfully
250          * remotely and locally. Once invoked, no further {@link BidirectionalStream.Callback}
251          * methods will be invoked.
252          *
253          * @param stream the stream which is closed successfully
254          * @param info the response information
255          */
onSucceeded(BidirectionalStream stream, UrlResponseInfo info)256         public abstract void onSucceeded(BidirectionalStream stream, UrlResponseInfo info);
257 
258         /**
259          * Invoked if the stream failed for any reason after {@link BidirectionalStream#start}.
260          * <a href="https://tools.ietf.org/html/rfc7540#section-7">HTTP/2 error codes</a> are
261          * mapped to {@link NetworkException#getCronetInternalErrorCode} codes. Once invoked, no
262          * further {@link BidirectionalStream.Callback} methods will be invoked.
263          *
264          * @param stream the stream which has failed
265          * @param info the response information. May be {@code null} if no response was received.
266          * @param error information about the failure
267          */
onFailed( BidirectionalStream stream, UrlResponseInfo info, CronetException error)268         public abstract void onFailed(
269                 BidirectionalStream stream, UrlResponseInfo info, CronetException error);
270 
271         /**
272          * Invoked if the stream was canceled via {@link BidirectionalStream#cancel}. Once invoked,
273          * no further {@link BidirectionalStream.Callback} methods will be invoked. Default
274          * implementation takes no action.
275          *
276          * @param stream the stream that was canceled
277          * @param info the response information. May be {@code null} if no response was received.
278          */
onCanceled(BidirectionalStream stream, UrlResponseInfo info)279         public void onCanceled(BidirectionalStream stream, UrlResponseInfo info) {}
280     }
281 
282     /**
283      * See {@link BidirectionalStream.Builder#setHttpMethod(String)}.
284      */
285     @NonNull
getHttpMethod()286     public abstract String getHttpMethod();
287 
288     /**
289      * See {@link BidirectionalStream.Builder#setTrafficStatsTag(int)}
290      */
hasTrafficStatsTag()291     public abstract boolean hasTrafficStatsTag();
292 
293     /**
294      * See {@link BidirectionalStream.Builder#setTrafficStatsTag(int)}
295      */
getTrafficStatsTag()296     public abstract int getTrafficStatsTag();
297 
298     /**
299      * See {@link BidirectionalStream.Builder#setTrafficStatsUid(int)}
300      */
hasTrafficStatsUid()301     public abstract boolean hasTrafficStatsUid();
302 
303     /**
304      * See {@link BidirectionalStream.Builder#setTrafficStatsUid(int)}
305      */
getTrafficStatsUid()306     public abstract int getTrafficStatsUid();
307 
308     /**
309      * See {@link Builder#addHeader(String, String)}
310      */
311     @NonNull
getHeaders()312     public abstract UrlResponseInfo.HeaderBlock getHeaders();
313 
314     /**
315      * See {@link Builder#setPriority(int)}
316      */
getPriority()317     public abstract int getPriority();
318 
319     /**
320      * See {@link Builder#setDelayRequestHeadersUntilFirstFlushEnabled(boolean)}
321      */
isDelayRequestHeadersUntilFirstFlushEnabled()322     public abstract boolean isDelayRequestHeadersUntilFirstFlushEnabled();
323 
324     /**
325      * Starts the stream, all callbacks go to the {@code callback} argument passed to {@link
326      * BidirectionalStream.Builder}'s constructor. Should only be called once.
327      */
start()328     public abstract void start();
329 
330     /**
331      * Reads data from the stream into the provided buffer. Can only be called at most once in
332      * response to each invocation of the {@link Callback#onStreamReady onStreamReady()}/ {@link
333      * Callback#onResponseHeadersReceived onResponseHeadersReceived()} and {@link
334      * Callback#onReadCompleted onReadCompleted()} methods of the {@link Callback}. Each call will
335      * result in an invocation of one of the {@link Callback Callback}'s {@link
336      * Callback#onReadCompleted onReadCompleted()} method if data is read, or its {@link
337      * Callback#onFailed onFailed()} method if there's an error.
338      *
339      * An attempt to read data into {@code buffer} starting at {@code buffer.position()} is begun.
340      * At most {@code buffer.remaining()} bytes are read. {@code buffer.position()} is updated upon
341      * invocation of {@link Callback#onReadCompleted onReadCompleted()} to indicate how much data
342      * was read.
343      *
344      * @param buffer the {@link ByteBuffer} to read data into. Must be a direct ByteBuffer. The
345      * embedder must not read or modify buffer's position, limit, or data between its position and
346      * limit until {@link Callback#onReadCompleted onReadCompleted()}, {@link Callback#onCanceled
347      * onCanceled()}, or {@link Callback#onFailed onFailed()} are invoked.
348      */
read(ByteBuffer buffer)349     public abstract void read(ByteBuffer buffer);
350 
351     /**
352      * Attempts to write data from the provided buffer into the stream. If auto flush is disabled,
353      * data will be sent only after {@link #flush flush()} is called. Each call will result in an
354      * invocation of one of the {@link Callback Callback}'s {@link Callback#onWriteCompleted
355      * onWriteCompleted()} method if data is sent, or its {@link Callback#onFailed onFailed()}
356      * method if there's an error.
357      *
358      * An attempt to write data from {@code buffer} starting at {@code buffer.position()} is begun.
359      * {@code buffer.remaining()} bytes will be written. {@link Callback#onWriteCompleted
360      * onWriteCompleted()} will be invoked only when the full ByteBuffer is written.
361      *
362      * @param buffer the {@link ByteBuffer} to write data from. Must be a direct ByteBuffer. The
363      * embedder must not read or modify buffer's position, limit, or data between its position and
364      * limit until {@link Callback#onWriteCompleted onWriteCompleted()}, {@link Callback#onCanceled
365      * onCanceled()}, or {@link Callback#onFailed onFailed()} are invoked. Can be empty when {@code
366      * endOfStream} is {@code true}.
367      * @param endOfStream if {@code true}, then {@code buffer} is the last buffer to be written, and
368      * once written, stream is closed from the client side, resulting in half-closed stream or a
369      * fully closed stream if the remote side has already closed.
370      */
write(ByteBuffer buffer, boolean endOfStream)371     public abstract void write(ByteBuffer buffer, boolean endOfStream);
372 
373     /**
374      * Flushes pending writes. This method should not be invoked before {@link
375      * Callback#onStreamReady onStreamReady()}. For previously delayed {@link #write write()}s, a
376      * corresponding {@link Callback#onWriteCompleted onWriteCompleted()} will be invoked when the
377      * buffer is sent.
378      */
flush()379     public abstract void flush();
380 
381     /**
382      * Cancels the stream. Can be called at any time after {@link #start}. {@link
383      * Callback#onCanceled onCanceled()} will be invoked when cancelation is complete and no further
384      * callback methods will be invoked. If the stream has completed or has not started, calling
385      * {@code cancel()} has no effect and {@code onCanceled()} will not be invoked. If the {@link
386      * Executor} passed in during
387      * {@code BidirectionalStream} construction runs tasks on a single thread, and {@code cancel()}
388      * is called on that thread, no listener methods (besides {@code onCanceled()}) will be invoked
389      * after
390      * {@code cancel()} is called. Otherwise, at most one callback method may be invoked after
391      * {@code cancel()} has completed.
392      */
cancel()393     public abstract void cancel();
394 
395     /**
396      * Returns {@code true} if the stream was successfully started and is now done (succeeded,
397      * canceled, or failed).
398      *
399      * @return {@code true} if the stream was successfully started and is now done (completed,
400      * canceled, or failed), otherwise returns {@code false} to indicate stream is not yet started
401      * or is in progress.
402      */
isDone()403     public abstract boolean isDone();
404 }
405