summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/stagefright/HTTPDataSource.h5
-rw-r--r--media/libstagefright/HTTPDataSource.cpp236
2 files changed, 98 insertions, 143 deletions
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index 83be475..ea31942 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -77,9 +77,6 @@ private:
int mStartingPort;
HTTPStream *mHttp;
- char *mHost;
- int mPort;
- char *mPath;
void *mBuffer;
size_t mBufferLength;
@@ -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 &);
};
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index 48f8e7a..a0b1993 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -29,74 +29,101 @@
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) {
- String8 request;
- request.append("GET ");
- request.append(path->c_str());
- request.append(" HTTP/1.1\r\n");
- request.append(headers);
- request.append("Host: ");
- request.append(host->c_str());
- request.append("\r\n\r\n");
-
- status_t err = http->send(request.string());
-
- int http_status;
- if (err == OK) {
- err = http->receive_header(&http_status);
- }
+status_t HTTPDataSource::connectWithRedirectsAndRange(off_t rangeStart) {
+ string host = mStartingHost.string();
+ string path = mStartingPath.string();
+ int port = mStartingPort;
- *result = err;
+ LOGV("Connecting to host '%s', port %d, path '%s'",
+ host.c_str(), port, path.c_str());
- if (err != OK) {
- return false;
- }
+ int numRedirectsRemaining = 5;
+ while (numRedirectsRemaining-- > 0) {
+ status_t err = mHttp->connect(host.c_str(), port);
- if (http_status != 301 && http_status != 302) {
- return false;
- }
+ if (err != OK) {
+ return err;
+ }
- string location;
- CHECK(http->find_header_value("Location", &location));
+ String8 request;
+ request.append("GET ");
+ request.append(path.c_str());
+ request.append(" HTTP/1.1\r\n");
+ request.append(mHeaders);
+ request.append("Host: ");
+ request.append(host.c_str());
+ request.append("\r\n");
- CHECK(string(location, 0, 7) == "http://");
- location.erase(0, 7);
- string::size_type slashPos = location.find('/');
- if (slashPos == string::npos) {
- slashPos = location.size();
- location += '/';
- }
+ if (rangeStart > 0) {
+ char range[128];
+ sprintf(range, "Range: bytes=%ld-\r\n", rangeStart);
- http->disconnect();
+ request.append(range);
+ }
- LOGI("Redirecting to %s\n", location.c_str());
+ request.append("\r\n");
- *host = string(location, 0, slashPos);
+ err = mHttp->send(request.string());
- string::size_type colonPos = host->find(':');
- if (colonPos != string::npos) {
- const char *start = host->c_str() + colonPos + 1;
- char *end;
- long tmp = strtol(start, &end, 10);
- CHECK(end > start && (*end == '\0'));
+ if (err != OK) {
+ return err;
+ }
- *port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80;
+ int httpStatus;
+ err = mHttp->receive_header(&httpStatus);
- host->erase(colonPos, host->size() - colonPos);
- } else {
- *port = 80;
- }
+ 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;
+ }
- *path = string(location, slashPos);
+ string location;
+ CHECK(mHttp->find_header_value("Location", &location));
+
+ CHECK(string(location, 0, 7) == "http://");
+ location.erase(0, 7);
+ string::size_type slashPos = location.find('/');
+ if (slashPos == string::npos) {
+ slashPos = location.size();
+ location += '/';
+ }
+
+ mHttp->disconnect();
+
+ LOGV("Redirecting to %s\n", location.c_str());
+
+ host = string(location, 0, slashPos);
+
+ string::size_type colonPos = host.find(':');
+ if (colonPos != string::npos) {
+ 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;
+
+ host.erase(colonPos, host.size() - colonPos);
+ } else {
+ port = 80;
+ }
- return true;
+ path = string(location, slashPos);
+
+ mStartingHost = host.c_str();
+ mStartingPath = path.c_str();
+ mStartingPort = port;
+ }
+
+ return ERROR_IO;
}
HTTPDataSource::HTTPDataSource(
@@ -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);
@@ -176,39 +199,17 @@ 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);
-
- if (err != OK) {
- Mutex::Autolock autoLock(mStateLock);
-
- if (mState != CONNECTING) {
- LOGV("connect() cancelled");
- }
- mState = DISCONNECTED;
-
- return err;
- }
- } while (PerformRedirectIfNecessary(
- mHttp, mHeaders, &host, &path, &port, &result)
- && numRedirectsRemaining-- > 0);
+ status_t err = connectWithRedirectsAndRange(0);
- if (result != OK) {
- // An error occurred while attempting to follow redirections/connect.
+ if (err != OK) {
Mutex::Autolock autoLock(mStateLock);
+ if (mState != CONNECTING) {
+ LOGV("connect() cancelled");
+ }
mState = DISCONNECTED;
- return result;
+ return err;
}
string value;
@@ -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) {
@@ -233,6 +230,7 @@ status_t HTTPDataSource::connect() {
}
mState = CONNECTED;
+
return OK;
}
@@ -278,57 +276,13 @@ 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) {
- 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;
+ if (err != OK) {
+ return err;
}
string value;
@@ -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;
}