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