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