summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libstagefright/HTTPDataSource.cpp110
-rw-r--r--media/libstagefright/string.cpp13
2 files changed, 112 insertions, 11 deletions
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index 5536801..7e8bbc6 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -24,6 +24,69 @@
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, string *host, string *path, int *port) {
+ String8 request;
+ request.append("HEAD ");
+ request.append(path->c_str());
+ request.append(" HTTP/1.1\r\n");
+ 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);
+ }
+
+ if (err != OK) {
+ return false;
+ }
+
+ if (http_status != 301 && http_status != 302) {
+ return false;
+ }
+
+ string location;
+ CHECK(http->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 += '/';
+ }
+
+ http->disconnect();
+
+ LOGI("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;
+ } else {
+ *port = 80;
+ }
+
+ *path = string(location, slashPos);
+
+ return true;
+}
+
HTTPDataSource::HTTPDataSource(const char *uri)
: mHttp(new HTTPStream),
mHost(NULL),
@@ -63,22 +126,44 @@ HTTPDataSource::HTTPDataSource(const char *uri)
LOGI("Connecting to host '%s', port %d, path '%s'",
host.c_str(), port, path.c_str());
+ do {
+ mInitCheck = mHttp->connect(host.c_str(), port);
+
+ if (mInitCheck != OK) {
+ return;
+ }
+ } while (PerformRedirectIfNecessary(mHttp, &host, &path, &port));
+
mHost = strdup(host.c_str());
mPort = port;
mPath = strdup(path.c_str());
-
- mInitCheck = mHttp->connect(mHost, mPort);
}
-HTTPDataSource::HTTPDataSource(const char *host, int port, const char *path)
+HTTPDataSource::HTTPDataSource(const char *_host, int port, const char *_path)
: mHttp(new HTTPStream),
- mHost(strdup(host)),
- mPort(port),
- mPath(strdup(path)),
+ mHost(NULL),
+ mPort(0),
+ mPath(NULL),
mBuffer(malloc(kBufferSize)),
mBufferLength(0),
mBufferOffset(0) {
- mInitCheck = mHttp->connect(mHost, mPort);
+ string host = _host;
+ string path = _path;
+
+ LOGI("Connecting to host '%s', port %d, path '%s'",
+ host.c_str(), port, path.c_str());
+
+ do {
+ mInitCheck = mHttp->connect(host.c_str(), port);
+
+ if (mInitCheck != OK) {
+ return;
+ }
+ } while (PerformRedirectIfNecessary(mHttp, &host, &path, &port));
+
+ mHost = strdup(host.c_str());
+ mPort = port;
+ mPath = strdup(path.c_str());
}
status_t HTTPDataSource::initCheck() const {
@@ -91,8 +176,15 @@ HTTPDataSource::~HTTPDataSource() {
free(mBuffer);
mBuffer = NULL;
- free(mPath);
- mPath = NULL;
+ if (mPath) {
+ free(mPath);
+ mPath = NULL;
+ }
+
+ if (mHost) {
+ free(mHost);
+ mHost = NULL;
+ }
delete mHttp;
mHttp = NULL;
diff --git a/media/libstagefright/string.cpp b/media/libstagefright/string.cpp
index bd6204b..8b2c36c 100644
--- a/media/libstagefright/string.cpp
+++ b/media/libstagefright/string.cpp
@@ -16,6 +16,8 @@
#include "include/stagefright_string.h"
+#include <media/stagefright/MediaDebug.h>
+
namespace android {
// static
@@ -28,8 +30,15 @@ string::string(const char *s, size_t length)
: mString(s, length) {
}
-string::string(const string &from, size_type start, size_type length)
- : mString(from.c_str() + start, length) {
+string::string(const string &from, size_type start, size_type length) {
+ CHECK(start <= from.size());
+ if (length == npos) {
+ length = from.size() - start;
+ } else {
+ CHECK(start + length <= from.size());
+ }
+
+ mString.setTo(from.c_str() + start, length);
}
string::string(const char *s)