15abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang/* 25abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * Copyright 2015 The Android Open Source Project 35abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * 45abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 55abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * you may not use this file except in compliance with the License. 65abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * You may obtain a copy of the License at 75abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * 85abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * http://www.apache.org/licenses/LICENSE-2.0 95abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * 105abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * Unless required by applicable law or agreed to in writing, software 115abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * distributed under the License is distributed on an "AS IS" BASIS, 125abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * See the License for the specific language governing permissions and 145abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * limitations under the License. 155abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang */ 165abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 175abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang//#define LOG_NDEBUG 0 185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#define LOG_TAG "HTTPDownloader" 195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <utils/Log.h> 205abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include "HTTPDownloader.h" 225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include "M3UParser.h" 235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <media/IMediaHTTPConnection.h> 255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <media/IMediaHTTPService.h> 265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <media/stagefright/foundation/ABuffer.h> 275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <media/stagefright/foundation/ADebug.h> 285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <media/stagefright/MediaHTTP.h> 295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <media/stagefright/DataSource.h> 305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <media/stagefright/FileSource.h> 315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <openssl/aes.h> 325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <openssl/md5.h> 335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#include <utils/Mutex.h> 348a414a2b8dc21143e13b9b75980aba68435a8a8eRobert Shih#include <inttypes.h> 355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangnamespace android { 375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong ZhangHTTPDownloader::HTTPDownloader( 395abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang const sp<IMediaHTTPService> &httpService, 405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang const KeyedVector<String8, String8> &headers) : 415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())), 425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mExtraHeaders(headers), 435abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mDisconnecting(false) { 445abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 455abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 465abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid HTTPDownloader::reconnect() { 475abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AutoMutex _l(mLock); 485abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mDisconnecting = false; 495abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 505abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 515abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangvoid HTTPDownloader::disconnect() { 525abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang { 535abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AutoMutex _l(mLock); 545abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mDisconnecting = true; 555abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 565abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mHTTPDataSource->disconnect(); 575abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 585abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 595abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangbool HTTPDownloader::isDisconnecting() { 605abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AutoMutex _l(mLock); 615abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return mDisconnecting; 625abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 635abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 645abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang/* 655abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * Illustration of parameters: 665abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * 675abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * 0 `range_offset` 685abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * +------------+-------------------------------------------------------+--+--+ 695abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * | | | next block to fetch | | | 705abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * | | `source` handle => `out` buffer | | | | 715abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * | `url` file |<--------- buffer size --------->|<--- `block_size` -->| | | 725abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * | |<----------- `range_length` / buffer capacity ----------->| | 735abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * |<------------------------------ file_size ------------------------------->| 745abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * 755abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * Special parameter values: 765abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * - range_length == -1 means entire file 775abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * - block_size == 0 means entire range 785abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang * 795abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang */ 805abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangssize_t HTTPDownloader::fetchBlock( 815abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang const char *url, sp<ABuffer> *out, 825abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang int64_t range_offset, int64_t range_length, 835abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang uint32_t block_size, /* download block size */ 845abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang String8 *actualUrl, 855abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bool reconnect /* force connect HTTP when resuing source */) { 865abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (isDisconnecting()) { 875abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return ERROR_NOT_CONNECTED; 885abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 895abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 905abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang off64_t size; 915abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 925abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (reconnect) { 935abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (!strncasecmp(url, "file://", 7)) { 945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mDataSource = new FileSource(url + 7); 955abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } else if (strncasecmp(url, "http://", 7) 965abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang && strncasecmp(url, "https://", 8)) { 975abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return ERROR_UNSUPPORTED; 985abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } else { 995abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang KeyedVector<String8, String8> headers = mExtraHeaders; 1005abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (range_offset > 0 || range_length >= 0) { 1015abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang headers.add( 1025abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang String8("Range"), 1035abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang String8( 1045abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang AStringPrintf( 1055abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang "bytes=%lld-%s", 1065abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang range_offset, 1075abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang range_length < 0 1085abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ? "" : AStringPrintf("%lld", 1095abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang range_offset + range_length - 1).c_str()).c_str())); 1105abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1115abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1125abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang status_t err = mHTTPDataSource->connect(url, &headers); 1135abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1145abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (isDisconnecting()) { 1155abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return ERROR_NOT_CONNECTED; 1165abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1175abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (err != OK) { 1195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return err; 1205abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mDataSource = mHTTPDataSource; 1235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang status_t getSizeErr = mDataSource->getSize(&size); 1275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (isDisconnecting()) { 1295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return ERROR_NOT_CONNECTED; 1305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (getSizeErr != OK) { 1335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang size = 65536; 1345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size); 1375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (*out == NULL) { 1385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang buffer->setRange(0, 0); 1395abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ssize_t bytesRead = 0; 1425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // adjust range_length if only reading partial block 1435abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (block_size > 0 && (range_length == -1 || (int64_t)(buffer->size() + block_size) < range_length)) { 1445abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang range_length = buffer->size() + block_size; 1455abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1465abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang for (;;) { 1475abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // Only resize when we don't know the size. 1485abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang size_t bufferRemaining = buffer->capacity() - buffer->size(); 1495abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (bufferRemaining == 0 && getSizeErr != OK) { 1505abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang size_t bufferIncrement = buffer->size() / 2; 1515abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (bufferIncrement < 32768) { 1525abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bufferIncrement = 32768; 1535abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1545abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bufferRemaining = bufferIncrement; 1555abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1565abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGV("increasing download buffer to %zu bytes", 1575abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang buffer->size() + bufferRemaining); 1585abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1595abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining); 1605abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang memcpy(copy->data(), buffer->data(), buffer->size()); 1615abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang copy->setRange(0, buffer->size()); 1625abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1635abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang buffer = copy; 1645abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1655abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1665abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang size_t maxBytesToRead = bufferRemaining; 1675abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (range_length >= 0) { 1685abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang int64_t bytesLeftInRange = range_length - buffer->size(); 1698a414a2b8dc21143e13b9b75980aba68435a8a8eRobert Shih if (bytesLeftInRange < 0) { 1708a414a2b8dc21143e13b9b75980aba68435a8a8eRobert Shih ALOGE("range_length %" PRId64 " wrapped around", range_length); 1718a414a2b8dc21143e13b9b75980aba68435a8a8eRobert Shih return ERROR_OUT_OF_RANGE; 1728a414a2b8dc21143e13b9b75980aba68435a8a8eRobert Shih } else if (bytesLeftInRange < (int64_t)maxBytesToRead) { 1735abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang maxBytesToRead = bytesLeftInRange; 1745abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1755abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (bytesLeftInRange == 0) { 1765abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang break; 1775abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1785abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1795abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1805abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1815abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0) 1825abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // to help us break out of the loop. 1835abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ssize_t n = mDataSource->readAt( 1845abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang buffer->size(), buffer->data() + buffer->size(), 1855abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang maxBytesToRead); 1865abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1875abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (isDisconnecting()) { 1885abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return ERROR_NOT_CONNECTED; 1895abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1905abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1915abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (n < 0) { 1925abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return n; 1935abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1945abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1955abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (n == 0) { 1965abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang break; 1975abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 1985abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 1995abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang buffer->setRange(0, buffer->size() + (size_t)n); 2005abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang bytesRead += n; 2015abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 2025abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2035abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang *out = buffer; 2045abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (actualUrl != NULL) { 2055abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang *actualUrl = mDataSource->getUri(); 2065abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (actualUrl->isEmpty()) { 2075abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang *actualUrl = url; 2085abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 2095abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 2105abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2115abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return bytesRead; 2125abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 2135abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2145abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangssize_t HTTPDownloader::fetchFile( 2155abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang const char *url, sp<ABuffer> *out, String8 *actualUrl) { 2165abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ssize_t err = fetchBlock(url, out, 0, -1, 0, actualUrl, true /* reconnect */); 2175abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2185abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // close off the connection after use 2195abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mHTTPDataSource->disconnect(); 2205abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2215abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return err; 2225abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 2235abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2245abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhangsp<M3UParser> HTTPDownloader::fetchPlaylist( 2255abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang const char *url, uint8_t *curPlaylistHash, bool *unchanged) { 2265abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGV("fetchPlaylist '%s'", url); 2275abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2285abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang *unchanged = false; 2295abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2305abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang sp<ABuffer> buffer; 2315abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang String8 actualUrl; 2325abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ssize_t err = fetchFile(url, &buffer, &actualUrl); 2335abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2345abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // close off the connection after use 2355abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang mHTTPDataSource->disconnect(); 2365abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2375abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (err <= 0) { 2385abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return NULL; 2395abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 2405abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2415abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // MD5 functionality is not available on the simulator, treat all 2425abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // playlists as changed. 2435abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2449d65efac5bbf88c03f7fa5e95120e2fbae35aa9bElliott Hughes#if defined(__ANDROID__) 2455abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang uint8_t hash[16]; 2465abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2475abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang MD5_CTX m; 2485abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang MD5_Init(&m); 2495abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang MD5_Update(&m, buffer->data(), buffer->size()); 2505abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2515abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang MD5_Final(hash, &m); 2525abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2535abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (curPlaylistHash != NULL && !memcmp(hash, curPlaylistHash, 16)) { 2545abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang // playlist unchanged 2555abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang *unchanged = true; 2565abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2575abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return NULL; 2585abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 2595abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2605abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (curPlaylistHash != NULL) { 2615abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang memcpy(curPlaylistHash, hash, sizeof(hash)); 2625abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 2635abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang#endif 2645abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2655abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang sp<M3UParser> playlist = 2665abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang new M3UParser(actualUrl.string(), buffer->data(), buffer->size()); 2675abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2685abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang if (playlist->initCheck() != OK) { 2695abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang ALOGE("failed to parse .m3u8 playlist"); 2705abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2715abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return NULL; 2725abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang } 2735abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2745abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang return playlist; 2755abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} 2765abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang 2775abbd3dcbb0bb32a3d4b90dddbcf90458967eb6fChong Zhang} // namespace android 278