| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cronet_bidirectional_stream_adapter.h" | 5 #include "cronet_bidirectional_stream_adapter.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 template <typename JavaArrayType> | 42 template <typename JavaArrayType> |
| 43 size_t SafeGetArrayLength(JNIEnv* env, JavaArrayType jarray) { | 43 size_t SafeGetArrayLength(JNIEnv* env, JavaArrayType jarray) { |
| 44 DCHECK(jarray); | 44 DCHECK(jarray); |
| 45 jsize length = env->GetArrayLength(jarray); | 45 jsize length = env->GetArrayLength(jarray); |
| 46 DCHECK_GE(length, 0) << "Invalid array length: " << length; | 46 DCHECK_GE(length, 0) << "Invalid array length: " << length; |
| 47 return static_cast<size_t>(std::max(0, length)); | 47 return static_cast<size_t>(std::max(0, length)); |
| 48 } | 48 } |
| 49 | 49 |
| 50 } // namespace | 50 } // namespace |
| 51 | 51 |
| 52 PendingWriteData::PendingWriteData(JNIEnv* env, |
| 53 jobjectArray jwrite_buffer_list, |
| 54 jintArray jwrite_buffer_pos_list, |
| 55 jintArray jwrite_buffer_limit_list, |
| 56 jboolean jwrite_end_of_stream) { |
| 57 this->jwrite_buffer_list.Reset(env, jwrite_buffer_list); |
| 58 this->jwrite_buffer_pos_list.Reset(env, jwrite_buffer_pos_list); |
| 59 this->jwrite_buffer_limit_list.Reset(env, jwrite_buffer_limit_list); |
| 60 this->jwrite_end_of_stream = jwrite_end_of_stream; |
| 61 } |
| 62 |
| 63 PendingWriteData::~PendingWriteData() { |
| 64 // Reset global references. |
| 65 jwrite_buffer_list.Reset(); |
| 66 jwrite_buffer_pos_list.Reset(); |
| 67 jwrite_buffer_limit_list.Reset(); |
| 68 } |
| 69 |
| 52 static jlong CreateBidirectionalStream( | 70 static jlong CreateBidirectionalStream( |
| 53 JNIEnv* env, | 71 JNIEnv* env, |
| 54 const base::android::JavaParamRef<jobject>& jbidi_stream, | 72 const base::android::JavaParamRef<jobject>& jbidi_stream, |
| 55 jlong jurl_request_context_adapter, | 73 jlong jurl_request_context_adapter, |
| 56 jboolean jdisable_auto_flush) { | 74 jboolean jdisable_auto_flush) { |
| 57 CronetURLRequestContextAdapter* context_adapter = | 75 CronetURLRequestContextAdapter* context_adapter = |
| 58 reinterpret_cast<CronetURLRequestContextAdapter*>( | 76 reinterpret_cast<CronetURLRequestContextAdapter*>( |
| 59 jurl_request_context_adapter); | 77 jurl_request_context_adapter); |
| 60 DCHECK(context_adapter); | 78 DCHECK(context_adapter); |
| 61 | 79 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 72 } | 90 } |
| 73 | 91 |
| 74 CronetBidirectionalStreamAdapter::CronetBidirectionalStreamAdapter( | 92 CronetBidirectionalStreamAdapter::CronetBidirectionalStreamAdapter( |
| 75 CronetURLRequestContextAdapter* context, | 93 CronetURLRequestContextAdapter* context, |
| 76 JNIEnv* env, | 94 JNIEnv* env, |
| 77 const base::android::JavaParamRef<jobject>& jbidi_stream, | 95 const base::android::JavaParamRef<jobject>& jbidi_stream, |
| 78 bool disable_auto_flush) | 96 bool disable_auto_flush) |
| 79 : context_(context), | 97 : context_(context), |
| 80 owner_(env, jbidi_stream), | 98 owner_(env, jbidi_stream), |
| 81 disable_auto_flush_(disable_auto_flush), | 99 disable_auto_flush_(disable_auto_flush), |
| 82 write_end_of_stream_(false), | |
| 83 stream_failed_(false) {} | 100 stream_failed_(false) {} |
| 84 | 101 |
| 85 CronetBidirectionalStreamAdapter::~CronetBidirectionalStreamAdapter() { | 102 CronetBidirectionalStreamAdapter::~CronetBidirectionalStreamAdapter() { |
| 86 DCHECK(context_->IsOnNetworkThread()); | 103 DCHECK(context_->IsOnNetworkThread()); |
| 87 } | 104 } |
| 88 | 105 |
| 89 jint CronetBidirectionalStreamAdapter::Start( | 106 jint CronetBidirectionalStreamAdapter::Start( |
| 90 JNIEnv* env, | 107 JNIEnv* env, |
| 91 const base::android::JavaParamRef<jobject>& jcaller, | 108 const base::android::JavaParamRef<jobject>& jcaller, |
| 92 const base::android::JavaParamRef<jstring>& jurl, | 109 const base::android::JavaParamRef<jstring>& jurl, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 jboolean jend_of_stream) { | 174 jboolean jend_of_stream) { |
| 158 size_t buffers_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); | 175 size_t buffers_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 159 size_t pos_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); | 176 size_t pos_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 160 size_t limit_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); | 177 size_t limit_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 161 if (buffers_array_size != pos_array_size || | 178 if (buffers_array_size != pos_array_size || |
| 162 buffers_array_size != limit_array_size) { | 179 buffers_array_size != limit_array_size) { |
| 163 DLOG(ERROR) << "Illegal arguments."; | 180 DLOG(ERROR) << "Illegal arguments."; |
| 164 return JNI_FALSE; | 181 return JNI_FALSE; |
| 165 } | 182 } |
| 166 | 183 |
| 167 IOBufferWithByteBufferList buffers; | 184 std::unique_ptr<PendingWriteData> pending_write_data; |
| 185 pending_write_data.reset( |
| 186 new PendingWriteData(env, jbyte_buffers.obj(), jbyte_buffers_pos.obj(), |
| 187 jbyte_buffers_limit.obj(), jend_of_stream)); |
| 168 for (size_t i = 0; i < buffers_array_size; ++i) { | 188 for (size_t i = 0; i < buffers_array_size; ++i) { |
| 169 ScopedJavaLocalRef<jobject> jbuffer( | 189 ScopedJavaLocalRef<jobject> jbuffer( |
| 170 env, env->GetObjectArrayElement(jbyte_buffers, i)); | 190 env, env->GetObjectArrayElement( |
| 191 pending_write_data->jwrite_buffer_list.obj(), i)); |
| 171 void* data = env->GetDirectBufferAddress(jbuffer.obj()); | 192 void* data = env->GetDirectBufferAddress(jbuffer.obj()); |
| 172 if (!data) | 193 if (!data) |
| 173 return JNI_FALSE; | 194 return JNI_FALSE; |
| 174 jint pos; | 195 jint pos; |
| 175 env->GetIntArrayRegion(jbyte_buffers_pos.obj(), i, 1, &pos); | 196 env->GetIntArrayRegion(pending_write_data->jwrite_buffer_pos_list.obj(), i, |
| 197 1, &pos); |
| 176 jint limit; | 198 jint limit; |
| 177 env->GetIntArrayRegion(jbyte_buffers_limit.obj(), i, 1, &limit); | 199 env->GetIntArrayRegion(pending_write_data->jwrite_buffer_limit_list.obj(), |
| 200 i, 1, &limit); |
| 178 DCHECK_LE(pos, limit); | 201 DCHECK_LE(pos, limit); |
| 179 scoped_refptr<IOBufferWithByteBuffer> write_buffer( | 202 scoped_refptr<net::WrappedIOBuffer> write_buffer( |
| 180 new IOBufferWithByteBuffer( | 203 new net::WrappedIOBuffer(static_cast<char*>(data) + pos)); |
| 181 env, base::android::JavaParamRef<jobject>(env, jbuffer.Release()), | 204 pending_write_data->write_buffer_list.push_back(write_buffer); |
| 182 data, pos, limit)); | 205 pending_write_data->write_buffer_len_list.push_back(limit - pos); |
| 183 buffers.push_back(write_buffer); | |
| 184 } | 206 } |
| 207 |
| 185 context_->PostTaskToNetworkThread( | 208 context_->PostTaskToNetworkThread( |
| 186 FROM_HERE, | 209 FROM_HERE, |
| 187 base::Bind(&CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread, | 210 base::Bind(&CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread, |
| 188 base::Unretained(this), buffers, jend_of_stream)); | 211 base::Unretained(this), |
| 189 | 212 base::Passed(std::move(pending_write_data)))); |
| 190 return JNI_TRUE; | 213 return JNI_TRUE; |
| 191 } | 214 } |
| 192 | 215 |
| 193 void CronetBidirectionalStreamAdapter::Destroy( | 216 void CronetBidirectionalStreamAdapter::Destroy( |
| 194 JNIEnv* env, | 217 JNIEnv* env, |
| 195 const base::android::JavaParamRef<jobject>& jcaller, | 218 const base::android::JavaParamRef<jobject>& jcaller, |
| 196 jboolean jsend_on_canceled) { | 219 jboolean jsend_on_canceled) { |
| 197 // Destroy could be called from any thread, including network thread (if | 220 // Destroy could be called from any thread, including network thread (if |
| 198 // posting task to executor throws an exception), but is posted, so |this| | 221 // posting task to executor throws an exception), but is posted, so |this| |
| 199 // is valid until calling task is complete. Destroy() is always called from | 222 // is valid until calling task is complete. Destroy() is always called from |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 env, owner_.obj(), read_buffer_->byte_buffer(), bytes_read, | 270 env, owner_.obj(), read_buffer_->byte_buffer(), bytes_read, |
| 248 read_buffer_->initial_position(), read_buffer_->initial_limit(), | 271 read_buffer_->initial_position(), read_buffer_->initial_limit(), |
| 249 bidi_stream_->GetTotalReceivedBytes()); | 272 bidi_stream_->GetTotalReceivedBytes()); |
| 250 // Free the read buffer. This lets the Java ByteBuffer be freed, if the | 273 // Free the read buffer. This lets the Java ByteBuffer be freed, if the |
| 251 // embedder releases it, too. | 274 // embedder releases it, too. |
| 252 read_buffer_ = nullptr; | 275 read_buffer_ = nullptr; |
| 253 } | 276 } |
| 254 | 277 |
| 255 void CronetBidirectionalStreamAdapter::OnDataSent() { | 278 void CronetBidirectionalStreamAdapter::OnDataSent() { |
| 256 DCHECK(context_->IsOnNetworkThread()); | 279 DCHECK(context_->IsOnNetworkThread()); |
| 257 DCHECK(!write_buffer_list_.empty()); | 280 DCHECK(pending_write_data_); |
| 258 | 281 |
| 259 JNIEnv* env = base::android::AttachCurrentThread(); | 282 JNIEnv* env = base::android::AttachCurrentThread(); |
| 260 base::android::ScopedJavaLocalRef<jclass> byte_buffer_clazz( | |
| 261 env, env->FindClass("java/nio/ByteBuffer")); | |
| 262 size_t size = write_buffer_list_.size(); | |
| 263 jobjectArray jbuffer_array = | |
| 264 env->NewObjectArray(size, byte_buffer_clazz.obj(), NULL); | |
| 265 base::android::CheckException(env); | |
| 266 std::vector<int> initial_positions; | |
| 267 std::vector<int> initial_limits; | |
| 268 for (size_t i = 0; i < size; ++i) { | |
| 269 env->SetObjectArrayElement(jbuffer_array, i, | |
| 270 write_buffer_list_[i]->byte_buffer()); | |
| 271 initial_positions.push_back(write_buffer_list_[i]->initial_position()); | |
| 272 initial_limits.push_back(write_buffer_list_[i]->initial_limit()); | |
| 273 } | |
| 274 ScopedJavaLocalRef<jobjectArray> jbuffers(env, jbuffer_array); | |
| 275 ScopedJavaLocalRef<jintArray> jinitial_positions = | |
| 276 base::android::ToJavaIntArray(env, initial_positions); | |
| 277 ScopedJavaLocalRef<jintArray> jinitial_limits = | |
| 278 base::android::ToJavaIntArray(env, initial_limits); | |
| 279 // Call into Java. | 283 // Call into Java. |
| 280 cronet::Java_CronetBidirectionalStream_onWritevCompleted( | 284 cronet::Java_CronetBidirectionalStream_onWritevCompleted( |
| 281 env, owner_.obj(), jbuffers.obj(), jinitial_positions.obj(), | 285 env, owner_.obj(), pending_write_data_->jwrite_buffer_list.obj(), |
| 282 jinitial_limits.obj(), write_end_of_stream_); | 286 pending_write_data_->jwrite_buffer_pos_list.obj(), |
| 283 // Free the write buffers. This lets the Java ByteBuffer be freed, if the | 287 pending_write_data_->jwrite_buffer_limit_list.obj(), |
| 288 pending_write_data_->jwrite_end_of_stream); |
| 289 // Free the java objects. This lets the Java ByteBuffers be freed, if the |
| 284 // embedder releases it, too. | 290 // embedder releases it, too. |
| 285 write_buffer_list_.clear(); | 291 pending_write_data_.reset(); |
| 286 } | 292 } |
| 287 | 293 |
| 288 void CronetBidirectionalStreamAdapter::OnTrailersReceived( | 294 void CronetBidirectionalStreamAdapter::OnTrailersReceived( |
| 289 const net::SpdyHeaderBlock& response_trailers) { | 295 const net::SpdyHeaderBlock& response_trailers) { |
| 290 DCHECK(context_->IsOnNetworkThread()); | 296 DCHECK(context_->IsOnNetworkThread()); |
| 291 JNIEnv* env = base::android::AttachCurrentThread(); | 297 JNIEnv* env = base::android::AttachCurrentThread(); |
| 292 cronet::Java_CronetBidirectionalStream_onResponseTrailersReceived( | 298 cronet::Java_CronetBidirectionalStream_onResponseTrailersReceived( |
| 293 env, owner_.obj(), GetHeadersArray(env, response_trailers).obj()); | 299 env, owner_.obj(), GetHeadersArray(env, response_trailers).obj()); |
| 294 } | 300 } |
| 295 | 301 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 return; | 339 return; |
| 334 | 340 |
| 335 if (bytes_read < 0) { | 341 if (bytes_read < 0) { |
| 336 OnFailed(bytes_read); | 342 OnFailed(bytes_read); |
| 337 return; | 343 return; |
| 338 } | 344 } |
| 339 OnDataRead(bytes_read); | 345 OnDataRead(bytes_read); |
| 340 } | 346 } |
| 341 | 347 |
| 342 void CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread( | 348 void CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread( |
| 343 const IOBufferWithByteBufferList& write_buffer_list, | 349 std::unique_ptr<PendingWriteData> pending_write_data) { |
| 344 bool end_of_stream) { | |
| 345 DCHECK(context_->IsOnNetworkThread()); | 350 DCHECK(context_->IsOnNetworkThread()); |
| 346 DCHECK(write_buffer_list_.empty()); | 351 DCHECK(pending_write_data); |
| 347 DCHECK(!write_buffer_list.empty()); | 352 DCHECK(!pending_write_data_); |
| 348 DCHECK(!write_end_of_stream_); | |
| 349 | 353 |
| 350 if (stream_failed_) { | 354 if (stream_failed_) { |
| 351 // If stream failed between the time when WritevData is invoked and | 355 // If stream failed between the time when WritevData is invoked and |
| 352 // WritevDataOnNetworkThread is executed, do not call into |bidi_stream_| | 356 // WritevDataOnNetworkThread is executed, do not call into |bidi_stream_| |
| 353 // since the underlying stream might have been destroyed. Do not invoke | 357 // since the underlying stream might have been destroyed. Do not invoke |
| 354 // Java callback either, since onError is posted when |stream_failed_| is | 358 // Java callback either, since onError is posted when |stream_failed_| is |
| 355 // set to true. | 359 // set to true. |
| 356 return; | 360 return; |
| 357 } | 361 } |
| 358 | 362 |
| 359 write_end_of_stream_ = end_of_stream; | 363 pending_write_data_ = std::move(pending_write_data); |
| 360 std::vector<net::IOBuffer*> buffers; | 364 bool end_of_stream = pending_write_data_->jwrite_end_of_stream == JNI_TRUE; |
| 361 std::vector<int> lengths; | 365 if (pending_write_data_->write_buffer_list.size() == 1) { |
| 362 for (const auto& buffer : write_buffer_list) { | 366 bidi_stream_->SendData(pending_write_data_->write_buffer_list[0], |
| 363 write_buffer_list_.push_back(buffer); | 367 pending_write_data_->write_buffer_len_list[0], |
| 364 buffers.push_back(buffer.get()); | 368 end_of_stream); |
| 365 lengths.push_back(buffer->initial_limit() - buffer->initial_position()); | |
| 366 } | |
| 367 if (buffers.size() == 1) { | |
| 368 bidi_stream_->SendData(buffers[0], lengths[0], end_of_stream); | |
| 369 } else { | 369 } else { |
| 370 bidi_stream_->SendvData(buffers, lengths, end_of_stream); | 370 bidi_stream_->SendvData(pending_write_data_->write_buffer_list, |
| 371 pending_write_data_->write_buffer_len_list, |
| 372 end_of_stream); |
| 371 } | 373 } |
| 372 } | 374 } |
| 373 | 375 |
| 374 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread( | 376 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread( |
| 375 bool send_on_canceled) { | 377 bool send_on_canceled) { |
| 376 DCHECK(context_->IsOnNetworkThread()); | 378 DCHECK(context_->IsOnNetworkThread()); |
| 377 if (send_on_canceled) { | 379 if (send_on_canceled) { |
| 378 JNIEnv* env = base::android::AttachCurrentThread(); | 380 JNIEnv* env = base::android::AttachCurrentThread(); |
| 379 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj()); | 381 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj()); |
| 380 } | 382 } |
| 381 delete this; | 383 delete this; |
| 382 } | 384 } |
| 383 | 385 |
| 384 base::android::ScopedJavaLocalRef<jobjectArray> | 386 base::android::ScopedJavaLocalRef<jobjectArray> |
| 385 CronetBidirectionalStreamAdapter::GetHeadersArray( | 387 CronetBidirectionalStreamAdapter::GetHeadersArray( |
| 386 JNIEnv* env, | 388 JNIEnv* env, |
| 387 const net::SpdyHeaderBlock& header_block) { | 389 const net::SpdyHeaderBlock& header_block) { |
| 388 DCHECK(context_->IsOnNetworkThread()); | 390 DCHECK(context_->IsOnNetworkThread()); |
| 389 | 391 |
| 390 std::vector<std::string> headers; | 392 std::vector<std::string> headers; |
| 391 for (const auto& header : header_block) { | 393 for (const auto& header : header_block) { |
| 392 headers.push_back(header.first.as_string()); | 394 headers.push_back(header.first.as_string()); |
| 393 headers.push_back(header.second.as_string()); | 395 headers.push_back(header.second.as_string()); |
| 394 } | 396 } |
| 395 return base::android::ToJavaArrayOfStrings(env, headers); | 397 return base::android::ToJavaArrayOfStrings(env, headers); |
| 396 } | 398 } |
| 397 | 399 |
| 398 } // namespace cronet | 400 } // namespace cronet |
| OLD | NEW |