summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/NuHTTPDataSource.cpp
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2010-11-18 11:03:48 -0800
committerAndreas Huber <andih@google.com>2010-11-18 12:45:12 -0800
commit7d23aa2a8354046ae0390eb5ad492346af5bce0f (patch)
treebca61c738bda9d21f15ab9a22e49388210e5a6b2 /media/libstagefright/NuHTTPDataSource.cpp
parent14d32754d3a9c1ccf49188c489f224800cd747a7 (diff)
downloadframeworks_av-7d23aa2a8354046ae0390eb5ad492346af5bce0f.zip
frameworks_av-7d23aa2a8354046ae0390eb5ad492346af5bce0f.tar.gz
frameworks_av-7d23aa2a8354046ae0390eb5ad492346af5bce0f.tar.bz2
Support for "chunked" HTTP transfer encoding.
Change-Id: I2f20d2d9ec0fa0c840b429049b0385289a30e774 related-to-bug: 3205131
Diffstat (limited to 'media/libstagefright/NuHTTPDataSource.cpp')
-rw-r--r--media/libstagefright/NuHTTPDataSource.cpp106
1 files changed, 96 insertions, 10 deletions
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 40f501a..c3c0d81 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -69,6 +69,8 @@ NuHTTPDataSource::NuHTTPDataSource()
mOffset(0),
mContentLength(0),
mContentLengthValid(false),
+ mHasChunkedTransferEncoding(false),
+ mChunkDataBytesLeft(0),
mNumBandwidthHistoryItems(0),
mTotalTransferTimeUs(0),
mTotalTransferBytes(0),
@@ -193,17 +195,27 @@ status_t NuHTTPDataSource::connect(
return ERROR_IO;
}
+ mHasChunkedTransferEncoding = false;
+
{
string value;
- if (mHTTP.find_header_value("Transfer-Encoding", &value)) {
- // We don't currently support any transfer encodings.
-
- mState = DISCONNECTED;
- mHTTP.disconnect();
-
- LOGE("We don't support '%s' transfer encoding.", value.c_str());
-
- return ERROR_UNSUPPORTED;
+ if (mHTTP.find_header_value("Transfer-Encoding", &value)
+ || mHTTP.find_header_value("Transfer-encoding", &value)) {
+ // We don't currently support any transfer encodings but
+ // chunked.
+
+ if (!strcasecmp(value.c_str(), "chunked")) {
+ LOGI("Chunked transfer encoding applied.");
+ mHasChunkedTransferEncoding = true;
+ mChunkDataBytesLeft = 0;
+ } else {
+ mState = DISCONNECTED;
+ mHTTP.disconnect();
+
+ LOGE("We don't support '%s' transfer encoding.", value.c_str());
+
+ return ERROR_UNSUPPORTED;
+ }
}
}
@@ -216,8 +228,17 @@ status_t NuHTTPDataSource::connect(
&& ParseSingleUnsignedLong(value.c_str(), &x)) {
mContentLength = (off_t)x;
mContentLengthValid = true;
+ } else {
+ LOGW("Server did not give us the content length!");
}
} else {
+ if (httpStatus != 206 /* Partial Content */) {
+ // We requested a range but the server didn't support that.
+ LOGE("We requested a range but the server didn't "
+ "support that.");
+ return ERROR_UNSUPPORTED;
+ }
+
string value;
unsigned long x;
if (mHTTP.find_header_value(string("Content-Range"), &value)) {
@@ -245,6 +266,71 @@ status_t NuHTTPDataSource::initCheck() const {
return mState == CONNECTED ? OK : NO_INIT;
}
+ssize_t NuHTTPDataSource::internalRead(void *data, size_t size) {
+ if (!mHasChunkedTransferEncoding) {
+ return mHTTP.receive(data, size);
+ }
+
+ if (mChunkDataBytesLeft < 0) {
+ return 0;
+ } else if (mChunkDataBytesLeft == 0) {
+ char line[1024];
+ status_t err = mHTTP.receive_line(line, sizeof(line));
+
+ if (err != OK) {
+ return err;
+ }
+
+ LOGV("line = '%s'", line);
+
+ char *end;
+ unsigned long n = strtoul(line, &end, 16);
+
+ if (end == line || (*end != ';' && *end != '\0')) {
+ LOGE("malformed HTTP chunk '%s'", line);
+ return ERROR_MALFORMED;
+ }
+
+ mChunkDataBytesLeft = n;
+ LOGV("chunk data size = %lu", n);
+
+ if (mChunkDataBytesLeft == 0) {
+ mChunkDataBytesLeft = -1;
+ return 0;
+ }
+
+ // fall through
+ }
+
+ if (size > (size_t)mChunkDataBytesLeft) {
+ size = mChunkDataBytesLeft;
+ }
+
+ ssize_t n = mHTTP.receive(data, size);
+
+ if (n < 0) {
+ return n;
+ }
+
+ mChunkDataBytesLeft -= (size_t)n;
+
+ if (mChunkDataBytesLeft == 0) {
+ char line[1024];
+ status_t err = mHTTP.receive_line(line, sizeof(line));
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (line[0] != '\0') {
+ LOGE("missing HTTP chunk terminator.");
+ return ERROR_MALFORMED;
+ }
+ }
+
+ return n;
+}
+
ssize_t NuHTTPDataSource::readAt(off_t offset, void *data, size_t size) {
LOGV("readAt offset %ld, size %d", offset, size);
@@ -275,7 +361,7 @@ ssize_t NuHTTPDataSource::readAt(off_t offset, void *data, size_t size) {
int64_t startTimeUs = ALooper::GetNowUs();
ssize_t n =
- mHTTP.receive((uint8_t *)data + numBytesRead, size - numBytesRead);
+ internalRead((uint8_t *)data + numBytesRead, size - numBytesRead);
if (n < 0) {
return n;