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