Loading include/media/stagefright/HTTPDataSource.h +2 −3 Original line number Diff line number Diff line Loading @@ -77,9 +77,6 @@ private: int mStartingPort; HTTPStream *mHttp; char *mHost; int mPort; char *mPath; void *mBuffer; size_t mBufferLength; Loading @@ -95,6 +92,8 @@ private: ssize_t sendRangeRequest(size_t offset); void initHeaders(const KeyedVector<String8, String8> *overrides); status_t connectWithRedirectsAndRange(off_t rangeStart); HTTPDataSource(const HTTPDataSource &); HTTPDataSource &operator=(const HTTPDataSource &); }; Loading media/libstagefright/HTTPDataSource.cpp +96 −140 Original line number Diff line number Diff line Loading @@ -29,42 +29,64 @@ namespace android { // Given a connected HTTPStream, determine if the given path redirects // somewhere else, if so, disconnect the stream, update host path and port // accordingly and return true, otherwise return false and leave the stream // connected. static bool PerformRedirectIfNecessary( HTTPStream *http, const String8 &headers, string *host, string *path, int *port, status_t *result) { status_t HTTPDataSource::connectWithRedirectsAndRange(off_t rangeStart) { string host = mStartingHost.string(); string path = mStartingPath.string(); int port = mStartingPort; LOGV("Connecting to host '%s', port %d, path '%s'", host.c_str(), port, path.c_str()); int numRedirectsRemaining = 5; while (numRedirectsRemaining-- > 0) { status_t err = mHttp->connect(host.c_str(), port); if (err != OK) { return err; } String8 request; request.append("GET "); request.append(path->c_str()); request.append(path.c_str()); request.append(" HTTP/1.1\r\n"); request.append(headers); request.append(mHeaders); request.append("Host: "); request.append(host->c_str()); request.append("\r\n\r\n"); request.append(host.c_str()); request.append("\r\n"); status_t err = http->send(request.string()); if (rangeStart > 0) { char range[128]; sprintf(range, "Range: bytes=%ld-\r\n", rangeStart); int http_status; if (err == OK) { err = http->receive_header(&http_status); request.append(range); } *result = err; request.append("\r\n"); err = mHttp->send(request.string()); if (err != OK) { return false; return err; } if (http_status != 301 && http_status != 302) { return false; int httpStatus; err = mHttp->receive_header(&httpStatus); if (err != OK) { return err; } if (httpStatus >= 200 && httpStatus < 300) { return OK; } if (httpStatus != 301 && httpStatus != 302) { LOGE("HTTP request failed w/ http status %d", httpStatus); return ERROR_IO; } string location; CHECK(http->find_header_value("Location", &location)); CHECK(mHttp->find_header_value("Location", &location)); CHECK(string(location, 0, 7) == "http://"); location.erase(0, 7); Loading @@ -74,29 +96,34 @@ static bool PerformRedirectIfNecessary( location += '/'; } http->disconnect(); mHttp->disconnect(); LOGI("Redirecting to %s\n", location.c_str()); LOGV("Redirecting to %s\n", location.c_str()); *host = string(location, 0, slashPos); host = string(location, 0, slashPos); string::size_type colonPos = host->find(':'); string::size_type colonPos = host.find(':'); if (colonPos != string::npos) { const char *start = host->c_str() + colonPos + 1; const char *start = host.c_str() + colonPos + 1; char *end; long tmp = strtol(start, &end, 10); CHECK(end > start && (*end == '\0')); *port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80; port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80; host->erase(colonPos, host->size() - colonPos); host.erase(colonPos, host.size() - colonPos); } else { *port = 80; port = 80; } *path = string(location, slashPos); path = string(location, slashPos); return true; mStartingHost = host.c_str(); mStartingPath = path.c_str(); mStartingPort = port; } return ERROR_IO; } HTTPDataSource::HTTPDataSource( Loading Loading @@ -150,10 +177,6 @@ void HTTPDataSource::init(const KeyedVector<String8, String8> *headers) { mState = DISCONNECTED; mHttp = new HTTPStream; mHost = NULL; mPort = 0; mPath = NULL; initHeaders(headers); mBuffer = malloc(kBufferSize); Loading @@ -176,17 +199,7 @@ status_t HTTPDataSource::connect() { mBufferOffset = 0; mContentLengthValid = false; string host = mStartingHost.string(); string path = mStartingPath.string(); int port = mStartingPort; LOGI("Connecting to host '%s', port %d, path '%s'", host.c_str(), port, path.c_str()); int numRedirectsRemaining = 5; status_t result; do { status_t err = mHttp->connect(host.c_str(), port); status_t err = connectWithRedirectsAndRange(0); if (err != OK) { Mutex::Autolock autoLock(mStateLock); Loading @@ -198,18 +211,6 @@ status_t HTTPDataSource::connect() { return err; } } while (PerformRedirectIfNecessary( mHttp, mHeaders, &host, &path, &port, &result) && numRedirectsRemaining-- > 0); if (result != OK) { // An error occurred while attempting to follow redirections/connect. Mutex::Autolock autoLock(mStateLock); mState = DISCONNECTED; return result; } string value; if (mHttp->find_header_value("Content-Length", &value)) { Loading @@ -218,10 +219,6 @@ status_t HTTPDataSource::connect() { mContentLengthValid = true; } mHost = strdup(host.c_str()); mPort = port; mPath = strdup(path.c_str()); Mutex::Autolock autoLock(mStateLock); if (mState != CONNECTING) { Loading @@ -233,6 +230,7 @@ status_t HTTPDataSource::connect() { } mState = CONNECTED; return OK; } Loading Loading @@ -278,59 +276,15 @@ HTTPDataSource::~HTTPDataSource() { free(mBuffer); mBuffer = NULL; if (mPath) { free(mPath); mPath = NULL; } if (mHost) { free(mHost); mHost = NULL; } } ssize_t HTTPDataSource::sendRangeRequest(size_t offset) { char host[128]; sprintf(host, "Host: %s\r\n", mHost); status_t err = connectWithRedirectsAndRange(offset); char range[128]; if (offset > 0) { sprintf(range, "Range: bytes=%d-\r\n", offset); } else { range[0] = '\0'; } int http_status; status_t err; int attempt = 1; for (;;) { if ((err = mHttp->send("GET ")) != OK || (err = mHttp->send(mPath)) != OK || (err = mHttp->send(" HTTP/1.1\r\n")) != OK || (err = mHttp->send(mHeaders.string())) != OK || (err = mHttp->send(host)) != OK || (err = mHttp->send(range)) != OK || (err = mHttp->send("\r\n")) != OK || (err = mHttp->receive_header(&http_status)) != OK) { if (attempt == 3) { if (err != OK) { return err; } mHttp->connect(mHost, mPort); ++attempt; } else { break; } } if ((http_status / 100) != 2) { LOGE("HTTP request failed, http status = %d", http_status); return UNKNOWN_ERROR; } string value; if (!mHttp->find_header_value("Content-Length", &value)) { return kBufferSize; Loading Loading @@ -407,8 +361,10 @@ rinse_repeat: if (num_bytes_received < 0 || (mContentLengthValid && num_bytes_received < contentLength)) { if (mNumRetriesLeft-- > 0) { disconnect(); if (connect() == OK) { mHttp->disconnect(); mBufferLength = 0; num_bytes_received = connectWithRedirectsAndRange(mBufferOffset); if (num_bytes_received == OK) { LOGI("retrying connection succeeded."); goto rinse_repeat; } Loading Loading
include/media/stagefright/HTTPDataSource.h +2 −3 Original line number Diff line number Diff line Loading @@ -77,9 +77,6 @@ private: int mStartingPort; HTTPStream *mHttp; char *mHost; int mPort; char *mPath; void *mBuffer; size_t mBufferLength; Loading @@ -95,6 +92,8 @@ private: ssize_t sendRangeRequest(size_t offset); void initHeaders(const KeyedVector<String8, String8> *overrides); status_t connectWithRedirectsAndRange(off_t rangeStart); HTTPDataSource(const HTTPDataSource &); HTTPDataSource &operator=(const HTTPDataSource &); }; Loading
media/libstagefright/HTTPDataSource.cpp +96 −140 Original line number Diff line number Diff line Loading @@ -29,42 +29,64 @@ namespace android { // Given a connected HTTPStream, determine if the given path redirects // somewhere else, if so, disconnect the stream, update host path and port // accordingly and return true, otherwise return false and leave the stream // connected. static bool PerformRedirectIfNecessary( HTTPStream *http, const String8 &headers, string *host, string *path, int *port, status_t *result) { status_t HTTPDataSource::connectWithRedirectsAndRange(off_t rangeStart) { string host = mStartingHost.string(); string path = mStartingPath.string(); int port = mStartingPort; LOGV("Connecting to host '%s', port %d, path '%s'", host.c_str(), port, path.c_str()); int numRedirectsRemaining = 5; while (numRedirectsRemaining-- > 0) { status_t err = mHttp->connect(host.c_str(), port); if (err != OK) { return err; } String8 request; request.append("GET "); request.append(path->c_str()); request.append(path.c_str()); request.append(" HTTP/1.1\r\n"); request.append(headers); request.append(mHeaders); request.append("Host: "); request.append(host->c_str()); request.append("\r\n\r\n"); request.append(host.c_str()); request.append("\r\n"); status_t err = http->send(request.string()); if (rangeStart > 0) { char range[128]; sprintf(range, "Range: bytes=%ld-\r\n", rangeStart); int http_status; if (err == OK) { err = http->receive_header(&http_status); request.append(range); } *result = err; request.append("\r\n"); err = mHttp->send(request.string()); if (err != OK) { return false; return err; } if (http_status != 301 && http_status != 302) { return false; int httpStatus; err = mHttp->receive_header(&httpStatus); if (err != OK) { return err; } if (httpStatus >= 200 && httpStatus < 300) { return OK; } if (httpStatus != 301 && httpStatus != 302) { LOGE("HTTP request failed w/ http status %d", httpStatus); return ERROR_IO; } string location; CHECK(http->find_header_value("Location", &location)); CHECK(mHttp->find_header_value("Location", &location)); CHECK(string(location, 0, 7) == "http://"); location.erase(0, 7); Loading @@ -74,29 +96,34 @@ static bool PerformRedirectIfNecessary( location += '/'; } http->disconnect(); mHttp->disconnect(); LOGI("Redirecting to %s\n", location.c_str()); LOGV("Redirecting to %s\n", location.c_str()); *host = string(location, 0, slashPos); host = string(location, 0, slashPos); string::size_type colonPos = host->find(':'); string::size_type colonPos = host.find(':'); if (colonPos != string::npos) { const char *start = host->c_str() + colonPos + 1; const char *start = host.c_str() + colonPos + 1; char *end; long tmp = strtol(start, &end, 10); CHECK(end > start && (*end == '\0')); *port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80; port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80; host->erase(colonPos, host->size() - colonPos); host.erase(colonPos, host.size() - colonPos); } else { *port = 80; port = 80; } *path = string(location, slashPos); path = string(location, slashPos); return true; mStartingHost = host.c_str(); mStartingPath = path.c_str(); mStartingPort = port; } return ERROR_IO; } HTTPDataSource::HTTPDataSource( Loading Loading @@ -150,10 +177,6 @@ void HTTPDataSource::init(const KeyedVector<String8, String8> *headers) { mState = DISCONNECTED; mHttp = new HTTPStream; mHost = NULL; mPort = 0; mPath = NULL; initHeaders(headers); mBuffer = malloc(kBufferSize); Loading @@ -176,17 +199,7 @@ status_t HTTPDataSource::connect() { mBufferOffset = 0; mContentLengthValid = false; string host = mStartingHost.string(); string path = mStartingPath.string(); int port = mStartingPort; LOGI("Connecting to host '%s', port %d, path '%s'", host.c_str(), port, path.c_str()); int numRedirectsRemaining = 5; status_t result; do { status_t err = mHttp->connect(host.c_str(), port); status_t err = connectWithRedirectsAndRange(0); if (err != OK) { Mutex::Autolock autoLock(mStateLock); Loading @@ -198,18 +211,6 @@ status_t HTTPDataSource::connect() { return err; } } while (PerformRedirectIfNecessary( mHttp, mHeaders, &host, &path, &port, &result) && numRedirectsRemaining-- > 0); if (result != OK) { // An error occurred while attempting to follow redirections/connect. Mutex::Autolock autoLock(mStateLock); mState = DISCONNECTED; return result; } string value; if (mHttp->find_header_value("Content-Length", &value)) { Loading @@ -218,10 +219,6 @@ status_t HTTPDataSource::connect() { mContentLengthValid = true; } mHost = strdup(host.c_str()); mPort = port; mPath = strdup(path.c_str()); Mutex::Autolock autoLock(mStateLock); if (mState != CONNECTING) { Loading @@ -233,6 +230,7 @@ status_t HTTPDataSource::connect() { } mState = CONNECTED; return OK; } Loading Loading @@ -278,59 +276,15 @@ HTTPDataSource::~HTTPDataSource() { free(mBuffer); mBuffer = NULL; if (mPath) { free(mPath); mPath = NULL; } if (mHost) { free(mHost); mHost = NULL; } } ssize_t HTTPDataSource::sendRangeRequest(size_t offset) { char host[128]; sprintf(host, "Host: %s\r\n", mHost); status_t err = connectWithRedirectsAndRange(offset); char range[128]; if (offset > 0) { sprintf(range, "Range: bytes=%d-\r\n", offset); } else { range[0] = '\0'; } int http_status; status_t err; int attempt = 1; for (;;) { if ((err = mHttp->send("GET ")) != OK || (err = mHttp->send(mPath)) != OK || (err = mHttp->send(" HTTP/1.1\r\n")) != OK || (err = mHttp->send(mHeaders.string())) != OK || (err = mHttp->send(host)) != OK || (err = mHttp->send(range)) != OK || (err = mHttp->send("\r\n")) != OK || (err = mHttp->receive_header(&http_status)) != OK) { if (attempt == 3) { if (err != OK) { return err; } mHttp->connect(mHost, mPort); ++attempt; } else { break; } } if ((http_status / 100) != 2) { LOGE("HTTP request failed, http status = %d", http_status); return UNKNOWN_ERROR; } string value; if (!mHttp->find_header_value("Content-Length", &value)) { return kBufferSize; Loading Loading @@ -407,8 +361,10 @@ rinse_repeat: if (num_bytes_received < 0 || (mContentLengthValid && num_bytes_received < contentLength)) { if (mNumRetriesLeft-- > 0) { disconnect(); if (connect() == OK) { mHttp->disconnect(); mBufferLength = 0; num_bytes_received = connectWithRedirectsAndRange(mBufferOffset); if (num_bytes_received == OK) { LOGI("retrying connection succeeded."); goto rinse_repeat; } Loading