xref: /aosp_15_r20/external/cronet/components/cronet/android/cronet_bidirectional_stream_adapter.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #ifndef COMPONENTS_CRONET_ANDROID_CRONET_BIDIRECTIONAL_STREAM_ADAPTER_H_
6 #define COMPONENTS_CRONET_ANDROID_CRONET_BIDIRECTIONAL_STREAM_ADAPTER_H_
7 
8 #include <jni.h>
9 
10 #include <memory>
11 
12 #include "base/android/jni_android.h"
13 #include "base/android/jni_array.h"
14 #include "base/android/jni_string.h"
15 #include "base/android/scoped_java_ref.h"
16 #include "base/memory/raw_ptr.h"
17 #include "base/memory/ref_counted.h"
18 #include "net/base/network_handle.h"
19 #include "net/http/bidirectional_stream.h"
20 #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h"
21 
22 namespace net {
23 struct BidirectionalStreamRequestInfo;
24 }  // namespace net
25 
26 namespace cronet {
27 
28 class CronetContextAdapter;
29 class IOBufferWithByteBuffer;
30 
31 // Convenient wrapper to hold Java references and data to represent the pending
32 // data to be written.
33 struct PendingWriteData {
34   PendingWriteData(
35       JNIEnv* env,
36       const base::android::JavaRef<jobjectArray>& jwrite_buffer_list,
37       const base::android::JavaRef<jintArray>& jwrite_buffer_pos_list,
38       const base::android::JavaRef<jintArray>& jwrite_buffer_limit_list,
39       jboolean jwrite_end_of_stream);
40 
41   PendingWriteData(const PendingWriteData&) = delete;
42   PendingWriteData& operator=(const PendingWriteData&) = delete;
43 
44   ~PendingWriteData();
45 
46   // Arguments passed in from Java. Retain a global ref so they won't get GC-ed
47   // until the corresponding onWriteCompleted is invoked.
48   base::android::ScopedJavaGlobalRef<jobjectArray> jwrite_buffer_list;
49   base::android::ScopedJavaGlobalRef<jintArray> jwrite_buffer_pos_list;
50   base::android::ScopedJavaGlobalRef<jintArray> jwrite_buffer_limit_list;
51   // A copy of the end of stream flag passed in from Java.
52   jboolean jwrite_end_of_stream;
53   // Every IOBuffer in |write_buffer_list| points to the memory owned by the
54   // corresponding Java ByteBuffer in |jwrite_buffer_list|.
55   std::vector<scoped_refptr<net::IOBuffer>> write_buffer_list;
56   // A list of the length of each IOBuffer in |write_buffer_list|.
57   std::vector<int> write_buffer_len_list;
58 };
59 
60 // An adapter from Java BidirectionalStream object to net::BidirectionalStream.
61 // Created and configured from a Java thread. Start, ReadData, WritevData and
62 // Destroy can be called on any thread (including network thread), and post
63 // calls to corresponding {Start|ReadData|WritevData|Destroy}OnNetworkThread to
64 // the network thread. The object is always deleted on network thread. All
65 // callbacks into the Java BidirectionalStream are done on the network thread.
66 // Java BidirectionalStream is expected to initiate the next step like ReadData
67 // or Destroy. Public methods can be called on any thread.
68 class CronetBidirectionalStreamAdapter
69     : public net::BidirectionalStream::Delegate {
70  public:
71   CronetBidirectionalStreamAdapter(
72       CronetContextAdapter* context,
73       JNIEnv* env,
74       const base::android::JavaParamRef<jobject>& jbidi_stream,
75       bool jsend_request_headers_automatically,
76       bool traffic_stats_tag_set,
77       int32_t traffic_stats_tag,
78       bool traffic_stats_uid_set,
79       int32_t traffic_stats_uid,
80       net::handles::NetworkHandle network);
81 
82   CronetBidirectionalStreamAdapter(const CronetBidirectionalStreamAdapter&) =
83       delete;
84   CronetBidirectionalStreamAdapter& operator=(
85       const CronetBidirectionalStreamAdapter&) = delete;
86 
87   ~CronetBidirectionalStreamAdapter() override;
88 
89   // Validates method and headers, initializes and starts the request. If
90   // |jend_of_stream| is true, then stream is half-closed after sending header
91   // frame and no data is expected to be written.
92   // Returns 0 if request is valid and started successfully,
93   // Returns -1 if |jmethod| is not valid HTTP method name.
94   // Returns position of invalid header value in |jheaders| if header name is
95   // not valid.
96   jint Start(JNIEnv* env,
97              const base::android::JavaParamRef<jobject>& jcaller,
98              const base::android::JavaParamRef<jstring>& jurl,
99              jint jpriority,
100              const base::android::JavaParamRef<jstring>& jmethod,
101              const base::android::JavaParamRef<jobjectArray>& jheaders,
102              jboolean jend_of_stream);
103 
104   // Sends request headers to server.
105   // When |send_request_headers_automatically_| is
106   // false and OnStreamReady() is invoked with request_headers_sent = false,
107   // headers will be combined with next WriteData/WritevData unless this
108   // method is called first, in which case headers will be sent separately
109   // without delay.
110   // (This method cannot be called when |send_request_headers_automatically_| is
111   // true nor when OnStreamReady() is invoked with request_headers_sent = true,
112   // since headers have been sent by the stream when stream is negotiated
113   // successfully.)
114   void SendRequestHeaders(JNIEnv* env,
115                           const base::android::JavaParamRef<jobject>& jcaller);
116 
117   // Reads more data into |jbyte_buffer| starting at |jposition| and not
118   // exceeding |jlimit|. Arguments are preserved to ensure that |jbyte_buffer|
119   // is not modified by the application during read.
120   jboolean ReadData(JNIEnv* env,
121                     const base::android::JavaParamRef<jobject>& jcaller,
122                     const base::android::JavaParamRef<jobject>& jbyte_buffer,
123                     jint jposition,
124                     jint jlimit);
125 
126   // Writes more data from |jbyte_buffers|. For the i_th buffer in
127   // |jbyte_buffers|, bytes to write start from i_th position in |jpositions|
128   // and end at i_th limit in |jlimits|.
129   // Arguments are preserved to ensure that |jbyte_buffer|
130   // is not modified by the application during write. The |jend_of_stream| is
131   // passed to remote to indicate end of stream.
132   jboolean WritevData(
133       JNIEnv* env,
134       const base::android::JavaParamRef<jobject>& jcaller,
135       const base::android::JavaParamRef<jobjectArray>& jbyte_buffers,
136       const base::android::JavaParamRef<jintArray>& jpositions,
137       const base::android::JavaParamRef<jintArray>& jlimits,
138       jboolean jend_of_stream);
139 
140   // Releases all resources for the request and deletes the object itself.
141   // |jsend_on_canceled| indicates if Java onCanceled callback should be
142   // issued to indicate that no more callbacks will be issued.
143   void Destroy(JNIEnv* env,
144                const base::android::JavaParamRef<jobject>& jcaller,
145                jboolean jsend_on_canceled);
146 
147  private:
148   // net::BidirectionalStream::Delegate implementations:
149   void OnStreamReady(bool request_headers_sent) override;
150   void OnHeadersReceived(
151       const spdy::Http2HeaderBlock& response_headers) override;
152   void OnDataRead(int bytes_read) override;
153   void OnDataSent() override;
154   void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) override;
155   void OnFailed(int error) override;
156 
157   void StartOnNetworkThread(
158       std::unique_ptr<net::BidirectionalStreamRequestInfo> request_info);
159   void SendRequestHeadersOnNetworkThread();
160   void ReadDataOnNetworkThread(
161       scoped_refptr<IOBufferWithByteBuffer> read_buffer,
162       int buffer_size);
163   void WritevDataOnNetworkThread(
164       std::unique_ptr<PendingWriteData> pending_write_data);
165   void DestroyOnNetworkThread(bool send_on_canceled);
166   // Gets headers as a Java array.
167   base::android::ScopedJavaLocalRef<jobjectArray> GetHeadersArray(
168       JNIEnv* env,
169       const spdy::Http2HeaderBlock& header_block);
170   // Reports metrics to the Java layer if the stream was ever started. Called on
171   // the network thread immediately before the adapter destroys itself.
172   void MaybeReportMetrics();
173   const raw_ptr<CronetContextAdapter> context_;
174 
175   // Java object that owns this CronetBidirectionalStreamAdapter.
176   base::android::ScopedJavaGlobalRef<jobject> owner_;
177   const bool send_request_headers_automatically_;
178   // Whether |traffic_stats_tag_| should be applied.
179   const bool traffic_stats_tag_set_;
180   // TrafficStats tag to apply to URLRequest.
181   const int32_t traffic_stats_tag_;
182   // Whether |traffic_stats_uid_| should be applied.
183   const bool traffic_stats_uid_set_;
184   // UID to be applied to URLRequest.
185   const int32_t traffic_stats_uid_;
186   // If not equal to net::handles::kInvalidNetworkHandle, the network to be used
187   // to send this request.
188   const net::handles::NetworkHandle network_;
189 
190   scoped_refptr<IOBufferWithByteBuffer> read_buffer_;
191   std::unique_ptr<PendingWriteData> pending_write_data_;
192   std::unique_ptr<net::BidirectionalStream> bidi_stream_;
193 
194   // Whether BidirectionalStream::Delegate::OnFailed callback is invoked.
195   bool stream_failed_;
196 };
197 
198 }  // namespace cronet
199 
200 #endif  // COMPONENTS_CRONET_ANDROID_CRONET_BIDIRECTIONAL_STREAM_ADAPTER_H_
201