support.cpp revision 1156dc913a5ba7b2bc86489468d4914430f03d14
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "ChromiumHTTPDataSourceSupport" 19#include <utils/Log.h> 20 21#include <media/stagefright/foundation/AString.h> 22 23#include "support.h" 24 25#include "android/net/android_network_library_impl.h" 26#include "base/thread.h" 27#include "net/base/host_resolver.h" 28#include "net/base/ssl_config_service.h" 29#include "net/http/http_cache.h" 30 31#include "include/ChromiumHTTPDataSource.h" 32 33#include <cutils/properties.h> 34#include <media/stagefright/MediaErrors.h> 35 36namespace android { 37 38static Mutex gNetworkThreadLock; 39static base::Thread *gNetworkThread = NULL; 40static scoped_refptr<URLRequestContext> gReqContext; 41 42static void InitializeNetworkThreadIfNecessary() { 43 Mutex::Autolock autoLock(gNetworkThreadLock); 44 if (gNetworkThread == NULL) { 45 gNetworkThread = new base::Thread("network"); 46 base::Thread::Options options; 47 options.message_loop_type = MessageLoop::TYPE_IO; 48 CHECK(gNetworkThread->StartWithOptions(options)); 49 50 gReqContext = new SfRequestContext; 51 52 net::AndroidNetworkLibrary::RegisterSharedInstance( 53 new SfNetworkLibrary); 54 } 55} 56 57static void MY_LOGI(const char *s) { 58 LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s); 59} 60 61static void MY_LOGV(const char *s) { 62#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0 63 LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s); 64#endif 65} 66 67SfNetLog::SfNetLog() 68 : mNextID(1) { 69} 70 71void SfNetLog::AddEntry( 72 EventType type, 73 const base::TimeTicks &time, 74 const Source &source, 75 EventPhase phase, 76 EventParameters *params) { 77#if 0 78 MY_LOGI(StringPrintf( 79 "AddEntry time=%s type=%s source=%s phase=%s\n", 80 TickCountToString(time).c_str(), 81 EventTypeToString(type), 82 SourceTypeToString(source.type), 83 EventPhaseToString(phase)).c_str()); 84#endif 85} 86 87uint32 SfNetLog::NextID() { 88 return mNextID++; 89} 90 91net::NetLog::LogLevel SfNetLog::GetLogLevel() const { 92 return LOG_ALL; 93} 94 95//////////////////////////////////////////////////////////////////////////////// 96 97SfRequestContext::SfRequestContext() { 98 AString ua; 99 ua.append("stagefright/1.2 (Linux;Android "); 100 101#if (PROPERTY_VALUE_MAX < 8) 102#error "PROPERTY_VALUE_MAX must be at least 8" 103#endif 104 105 char value[PROPERTY_VALUE_MAX]; 106 property_get("ro.build.version.release", value, "Unknown"); 107 ua.append(value); 108 ua.append(")"); 109 110 mUserAgent = ua.c_str(); 111 112 net_log_ = new SfNetLog; 113 114 host_resolver_ = 115 net::CreateSystemHostResolver( 116 net::HostResolver::kDefaultParallelism, 117 NULL /* resolver_proc */, 118 net_log_); 119 120 ssl_config_service_ = 121 net::SSLConfigService::CreateSystemSSLConfigService(); 122 123 proxy_service_ = net::ProxyService::CreateDirect(); 124 125 http_transaction_factory_ = new net::HttpCache( 126 host_resolver_, 127 dnsrr_resolver_, 128 dns_cert_checker_.get(), 129 proxy_service_.get(), 130 ssl_config_service_.get(), 131 NULL, // http_auth_handler_factory 132 network_delegate_, 133 net_log_, 134 NULL); // backend_factory 135} 136 137const std::string &SfRequestContext::GetUserAgent(const GURL &url) const { 138 return mUserAgent; 139} 140 141//////////////////////////////////////////////////////////////////////////////// 142 143SfNetworkLibrary::SfNetworkLibrary() {} 144 145SfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain( 146 const std::vector<std::string>& cert_chain, 147 const std::string& hostname, 148 const std::string& auth_type) { 149 return VERIFY_OK; 150} 151 152//////////////////////////////////////////////////////////////////////////////// 153 154SfDelegate::SfDelegate() 155 : mOwner(NULL), 156 mURLRequest(NULL), 157 mReadBuffer(new net::IOBufferWithSize(8192)), 158 mNumBytesRead(0), 159 mNumBytesTotal(0), 160 mDataDestination(NULL), 161 mAtEOS(false) { 162 InitializeNetworkThreadIfNecessary(); 163} 164 165SfDelegate::~SfDelegate() { 166 CHECK(mURLRequest == NULL); 167} 168 169void SfDelegate::setOwner(ChromiumHTTPDataSource *owner) { 170 mOwner = owner; 171} 172 173void SfDelegate::OnReceivedRedirect( 174 URLRequest *request, const GURL &new_url, bool *defer_redirect) { 175 MY_LOGI("OnReceivedRedirect"); 176} 177 178void SfDelegate::OnAuthRequired( 179 URLRequest *request, net::AuthChallengeInfo *auth_info) { 180 MY_LOGI("OnAuthRequired"); 181 182 inherited::OnAuthRequired(request, auth_info); 183} 184 185void SfDelegate::OnCertificateRequested( 186 URLRequest *request, net::SSLCertRequestInfo *cert_request_info) { 187 MY_LOGI("OnCertificateRequested"); 188 189 inherited::OnCertificateRequested(request, cert_request_info); 190} 191 192void SfDelegate::OnSSLCertificateError( 193 URLRequest *request, int cert_error, net::X509Certificate *cert) { 194 fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error); 195 196 inherited::OnSSLCertificateError(request, cert_error, cert); 197} 198 199void SfDelegate::OnGetCookies(URLRequest *request, bool blocked_by_policy) { 200 MY_LOGI("OnGetCookies"); 201} 202 203void SfDelegate::OnSetCookie( 204 URLRequest *request, 205 const std::string &cookie_line, 206 const net::CookieOptions &options, 207 bool blocked_by_policy) { 208 MY_LOGI("OnSetCookie"); 209} 210 211void SfDelegate::OnResponseStarted(URLRequest *request) { 212 if (request->status().status() != URLRequestStatus::SUCCESS) { 213 MY_LOGI(StringPrintf( 214 "Request failed with status %d and os_error %d", 215 request->status().status(), 216 request->status().os_error()).c_str()); 217 218 delete mURLRequest; 219 mURLRequest = NULL; 220 221 mOwner->onConnectionFailed(ERROR_IO); 222 return; 223 } else if (mRangeRequested && request->GetResponseCode() != 206) { 224 MY_LOGI(StringPrintf( 225 "We requested a content range, but server didn't " 226 "support that. (responded with %d)", 227 request->GetResponseCode()).c_str()); 228 229 delete mURLRequest; 230 mURLRequest = NULL; 231 232 mOwner->onConnectionFailed(-EPIPE); 233 return; 234 } else if ((request->GetResponseCode() / 100) != 2) { 235 MY_LOGI(StringPrintf( 236 "Server responded with http status %d", 237 request->GetResponseCode()).c_str()); 238 239 delete mURLRequest; 240 mURLRequest = NULL; 241 242 mOwner->onConnectionFailed(ERROR_IO); 243 return; 244 } 245 246 MY_LOGV("OnResponseStarted"); 247 248 std::string headers; 249 request->GetAllResponseHeaders(&headers); 250 251 MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str()); 252 253 mOwner->onConnectionEstablished(request->GetExpectedContentSize()); 254} 255 256void SfDelegate::OnReadCompleted(URLRequest *request, int bytes_read) { 257 if (bytes_read == -1) { 258 MY_LOGI(StringPrintf( 259 "OnReadCompleted, read failed, status %d", 260 request->status().status()).c_str()); 261 262 mOwner->onReadCompleted(ERROR_IO); 263 return; 264 } 265 266 MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str()); 267 268 if (bytes_read < 0) { 269 MY_LOGI(StringPrintf( 270 "Read failed w/ status %d\n", 271 request->status().status()).c_str()); 272 273 mOwner->onReadCompleted(ERROR_IO); 274 return; 275 } else if (bytes_read == 0) { 276 mAtEOS = true; 277 mOwner->onReadCompleted(mNumBytesRead); 278 return; 279 } 280 281 CHECK_GT(bytes_read, 0); 282 CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal); 283 284 memcpy((uint8_t *)mDataDestination + mNumBytesRead, 285 mReadBuffer->data(), 286 bytes_read); 287 288 mNumBytesRead += bytes_read; 289 290 readMore(request); 291} 292 293void SfDelegate::readMore(URLRequest *request) { 294 while (mNumBytesRead < mNumBytesTotal) { 295 size_t copy = mNumBytesTotal - mNumBytesRead; 296 if (copy > mReadBuffer->size()) { 297 copy = mReadBuffer->size(); 298 } 299 300 int n; 301 if (request->Read(mReadBuffer, copy, &n)) { 302 MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str()); 303 304 CHECK_LE((size_t)n, copy); 305 306 memcpy((uint8_t *)mDataDestination + mNumBytesRead, 307 mReadBuffer->data(), 308 n); 309 310 mNumBytesRead += n; 311 312 if (n == 0) { 313 mAtEOS = true; 314 break; 315 } 316 } else { 317 MY_LOGV("readMore pending read"); 318 319 if (request->status().status() != URLRequestStatus::IO_PENDING) { 320 MY_LOGI(StringPrintf( 321 "Direct read failed w/ status %d\n", 322 request->status().status()).c_str()); 323 324 mOwner->onReadCompleted(ERROR_IO); 325 return; 326 } 327 328 return; 329 } 330 } 331 332 mOwner->onReadCompleted(mNumBytesRead); 333} 334 335void SfDelegate::initiateConnection( 336 const char *uri, 337 const KeyedVector<String8, String8> *headers, 338 off64_t offset) { 339 GURL url(uri); 340 341 MessageLoop *loop = gNetworkThread->message_loop(); 342 loop->PostTask( 343 FROM_HERE, 344 NewRunnableFunction( 345 &SfDelegate::OnInitiateConnectionWrapper, 346 this, 347 url, 348 headers, 349 offset)); 350 351} 352 353// static 354void SfDelegate::OnInitiateConnectionWrapper( 355 SfDelegate *me, GURL url, 356 const KeyedVector<String8, String8> *headers, 357 off64_t offset) { 358 me->onInitiateConnection(url, headers, offset); 359} 360 361void SfDelegate::onInitiateConnection( 362 const GURL &url, 363 const KeyedVector<String8, String8> *extra, 364 off64_t offset) { 365 CHECK(mURLRequest == NULL); 366 367 mURLRequest = new URLRequest(url, this); 368 mAtEOS = false; 369 370 mRangeRequested = false; 371 372 if (offset != 0 || extra != NULL) { 373 net::HttpRequestHeaders headers = 374 mURLRequest->extra_request_headers(); 375 376 if (offset != 0) { 377 headers.AddHeaderFromString( 378 StringPrintf("Range: bytes=%lld-", offset).c_str()); 379 380 mRangeRequested = true; 381 } 382 383 if (extra != NULL) { 384 for (size_t i = 0; i < extra->size(); ++i) { 385 AString s; 386 s.append(extra->keyAt(i).string()); 387 s.append(": "); 388 s.append(extra->valueAt(i).string()); 389 390 headers.AddHeaderFromString(s.c_str()); 391 } 392 } 393 394 mURLRequest->SetExtraRequestHeaders(headers); 395 } 396 397 mURLRequest->set_context(gReqContext); 398 399 mURLRequest->Start(); 400} 401 402void SfDelegate::initiateDisconnect() { 403 MessageLoop *loop = gNetworkThread->message_loop(); 404 loop->PostTask( 405 FROM_HERE, 406 NewRunnableFunction( 407 &SfDelegate::OnInitiateDisconnectWrapper, this)); 408} 409 410// static 411void SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) { 412 me->onInitiateDisconnect(); 413} 414 415void SfDelegate::onInitiateDisconnect() { 416 mURLRequest->Cancel(); 417 418 delete mURLRequest; 419 mURLRequest = NULL; 420 421 mOwner->onDisconnectComplete(); 422} 423 424void SfDelegate::initiateRead(void *data, size_t size) { 425 MessageLoop *loop = gNetworkThread->message_loop(); 426 loop->PostTask( 427 FROM_HERE, 428 NewRunnableFunction( 429 &SfDelegate::OnInitiateReadWrapper, this, data, size)); 430} 431 432// static 433void SfDelegate::OnInitiateReadWrapper( 434 SfDelegate *me, void *data, size_t size) { 435 me->onInitiateRead(data, size); 436} 437 438void SfDelegate::onInitiateRead(void *data, size_t size) { 439 CHECK(mURLRequest != NULL); 440 441 mNumBytesRead = 0; 442 mNumBytesTotal = size; 443 mDataDestination = data; 444 445 if (mAtEOS) { 446 mOwner->onReadCompleted(0); 447 return; 448 } 449 450 readMore(mURLRequest); 451} 452 453} // namespace android 454 455