From dab718bba3945332dc75e268e1e7f0fe2eb91c4a Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Wed, 13 Jul 2011 15:45:01 -0700 Subject: Remove legacy http support from stagefright, chromium is the new hotness. Change-Id: I6725d42d38b91e6a1cbca43174870f445aeb3d99 --- media/libstagefright/Android.mk | 3 - media/libstagefright/HTTPBase.cpp | 19 +- media/libstagefright/HTTPStream.cpp | 623 ------------------------ media/libstagefright/NuHTTPDataSource.cpp | 560 --------------------- media/libstagefright/ShoutcastSource.cpp | 157 ------ media/libstagefright/include/HTTPBase.h | 2 + media/libstagefright/include/HTTPStream.h | 91 ---- media/libstagefright/include/NuHTTPDataSource.h | 114 ----- media/libstagefright/rtsp/ARTSPConnection.cpp | 4 +- media/libstagefright/rtsp/MyHandler.h | 6 +- 10 files changed, 19 insertions(+), 1560 deletions(-) delete mode 100644 media/libstagefright/HTTPStream.cpp delete mode 100644 media/libstagefright/NuHTTPDataSource.cpp delete mode 100644 media/libstagefright/ShoutcastSource.cpp delete mode 100644 media/libstagefright/include/HTTPStream.h delete mode 100644 media/libstagefright/include/NuHTTPDataSource.h (limited to 'media') diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 7b3b95b..1d880fa 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -24,7 +24,6 @@ LOCAL_SRC_FILES:= \ FileSource.cpp \ FLACExtractor.cpp \ HTTPBase.cpp \ - HTTPStream.cpp \ JPEGSource.cpp \ MP3Extractor.cpp \ MPEG2TSWriter.cpp \ @@ -38,13 +37,11 @@ LOCAL_SRC_FILES:= \ MediaSourceSplitter.cpp \ MetaData.cpp \ NuCachedSource2.cpp \ - NuHTTPDataSource.cpp \ OMXClient.cpp \ OMXCodec.cpp \ OggExtractor.cpp \ SampleIterator.cpp \ SampleTable.cpp \ - ShoutcastSource.cpp \ StagefrightMediaScanner.cpp \ StagefrightMetadataRetriever.cpp \ ThrottledSource.cpp \ diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp index 0d24551..f9d8501 100644 --- a/media/libstagefright/HTTPBase.cpp +++ b/media/libstagefright/HTTPBase.cpp @@ -24,10 +24,11 @@ #include "include/ChromiumHTTPDataSource.h" #endif -#include "include/NuHTTPDataSource.h" - +#include #include + #include +#include namespace android { @@ -44,14 +45,12 @@ HTTPBase::HTTPBase() // static sp HTTPBase::Create(uint32_t flags) { #if CHROMIUM_AVAILABLE - char value[PROPERTY_VALUE_MAX]; - if (!property_get("media.stagefright.use-chromium", value, NULL) - || (strcasecmp("false", value) && strcmp("0", value))) { return new ChromiumHTTPDataSource(flags); - } else #endif { - return new NuHTTPDataSource(flags); + TRESPASS(); + + return NULL; } } @@ -135,4 +134,10 @@ bool HTTPBase::getUID(uid_t *uid) const { return true; } +// static +void HTTPBase::RegisterSocketUser(int s, uid_t uid) { + static const uint32_t kTag = 0xdeadbeef; + set_qtaguid(s, kTag, uid); +} + } // namespace android diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp deleted file mode 100644 index d526ebd..0000000 --- a/media/libstagefright/HTTPStream.cpp +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "HTTPStream" -#include - -#include "include/HTTPStream.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace android { - -// static -const char *HTTPStream::kStatusKey = ":status:"; // MUST be lowercase. - -HTTPStream::HTTPStream() - : mState(READY), - mUIDValid(false), - mSocket(-1), - mSSLContext(NULL), - mSSL(NULL) { -} - -HTTPStream::~HTTPStream() { - disconnect(); - - if (mSSLContext != NULL) { - SSL_CTX_free((SSL_CTX *)mSSLContext); - mSSLContext = NULL; - } -} - -void HTTPStream::setUID(uid_t uid) { - mUIDValid = true; - mUID = uid; -} - -static bool MakeSocketBlocking(int s, bool blocking) { - // Make socket non-blocking. - int flags = fcntl(s, F_GETFL, 0); - if (flags == -1) { - return false; - } - - if (blocking) { - flags &= ~O_NONBLOCK; - } else { - flags |= O_NONBLOCK; - } - - return fcntl(s, F_SETFL, flags) != -1; -} - -static status_t MyConnect( - int s, const struct sockaddr *addr, socklen_t addrlen) { - status_t result = UNKNOWN_ERROR; - - MakeSocketBlocking(s, false); - - if (connect(s, addr, addrlen) == 0) { - result = OK; - } else if (errno != EINPROGRESS) { - result = -errno; - } else { - for (;;) { - fd_set rs, ws; - FD_ZERO(&rs); - FD_ZERO(&ws); - FD_SET(s, &rs); - FD_SET(s, &ws); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 100000ll; - - int nfds = ::select(s + 1, &rs, &ws, NULL, &tv); - - if (nfds < 0) { - if (errno == EINTR) { - continue; - } - - result = -errno; - break; - } - - if (FD_ISSET(s, &ws) && !FD_ISSET(s, &rs)) { - result = OK; - break; - } - - if (FD_ISSET(s, &rs) || FD_ISSET(s, &ws)) { - // Get the pending error. - int error = 0; - socklen_t errorLen = sizeof(error); - if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &errorLen) == -1) { - // Couldn't get the real error, so report why not. - result = -errno; - } else { - result = -error; - } - break; - } - - // Timeout expired. Try again. - } - } - - MakeSocketBlocking(s, true); - - return result; -} - -// Apparently under out linux closing a socket descriptor from one thread -// will not unblock a pending send/recv on that socket on another thread. -static ssize_t MySendReceive( - int s, void *data, size_t size, int flags, bool sendData) { - ssize_t result = 0; - - if (s < 0) { - return -1; - } - while (size > 0) { - fd_set rs, ws, es; - FD_ZERO(&rs); - FD_ZERO(&ws); - FD_ZERO(&es); - FD_SET(s, sendData ? &ws : &rs); - FD_SET(s, &es); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 100000ll; - - int nfds = ::select( - s + 1, - sendData ? NULL : &rs, - sendData ? &ws : NULL, - &es, - &tv); - - if (nfds < 0) { - if (errno == EINTR) { - continue; - } - - result = -errno; - break; - } else if (nfds == 0) { - // timeout - - continue; - } - - CHECK_EQ(nfds, 1); - - ssize_t nbytes = - sendData ? send(s, data, size, flags) : recv(s, data, size, flags); - - if (nbytes < 0) { - if (errno == EINTR) { - continue; - } - - result = -errno; - break; - } else if (nbytes == 0) { - result = 0; - break; - } - - data = (uint8_t *)data + nbytes; - size -= nbytes; - - result = nbytes; - break; - } - - return result; -} - -static ssize_t MySend(int s, const void *data, size_t size, int flags) { - return MySendReceive( - s, const_cast(data), size, flags, true /* sendData */); -} - -static ssize_t MyReceive(int s, void *data, size_t size, int flags) { - return MySendReceive(s, data, size, flags, false /* sendData */); -} - -status_t HTTPStream::connect(const char *server, int port, bool https) { - if (port < 0) { - port = https ? 443 : 80; - } - - Mutex::Autolock autoLock(mLock); - - status_t err = OK; - - if (mState == CONNECTED) { - return ERROR_ALREADY_CONNECTED; - } - - if (port < 0 || port > (int) USHRT_MAX) { - return UNKNOWN_ERROR; - } - - char service[sizeof("65536")]; - sprintf(service, "%d", port); - struct addrinfo hints, *ai; - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; - hints.ai_socktype = SOCK_STREAM; - - int ret = getaddrinfo(server, service, &hints, &ai); - if (ret) { - return ERROR_UNKNOWN_HOST; - } - - CHECK_EQ(mSocket, -1); - - mState = CONNECTING; - status_t res = -1; - struct addrinfo *tmp; - for (tmp = ai; tmp; tmp = tmp->ai_next) { - mSocket = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol); - if (mSocket < 0) { - continue; - } - - if (mUIDValid) { - RegisterSocketUser(mSocket, mUID); - } - - setReceiveTimeout(30); // Time out reads after 30 secs by default. - - int s = mSocket; - - mLock.unlock(); - - res = MyConnect(s, tmp->ai_addr, tmp->ai_addrlen); - - mLock.lock(); - - if (mState != CONNECTING) { - close(s); - freeaddrinfo(ai); - return UNKNOWN_ERROR; - } - - if (res == OK) { - break; - } - - close(s); - } - - freeaddrinfo(ai); - - if (res != OK) { - close(mSocket); - mSocket = -1; - - mState = READY; - return res; - } - - if (https) { - CHECK(mSSL == NULL); - - if (mSSLContext == NULL) { - SSL_library_init(); - - mSSLContext = SSL_CTX_new(TLSv1_client_method()); - - if (mSSLContext == NULL) { - LOGE("failed to create SSL context"); - mState = READY; - return ERROR_IO; - } - } - - mSSL = SSL_new((SSL_CTX *)mSSLContext); - - if (mSSL == NULL) { - LOGE("failed to create SSL session"); - - mState = READY; - return ERROR_IO; - } - - int res = SSL_set_fd((SSL *)mSSL, mSocket); - - if (res == 1) { - res = SSL_connect((SSL *)mSSL); - } - - if (res != 1) { - SSL_free((SSL *)mSSL); - mSSL = NULL; - - LOGE("failed to connect over SSL"); - mState = READY; - - return ERROR_IO; - } - } - - mState = CONNECTED; - - return OK; -} - -status_t HTTPStream::disconnect() { - Mutex::Autolock autoLock(mLock); - - if (mState != CONNECTED && mState != CONNECTING) { - return ERROR_NOT_CONNECTED; - } - - if (mSSL != NULL) { - SSL_shutdown((SSL *)mSSL); - - SSL_free((SSL *)mSSL); - mSSL = NULL; - } - - CHECK(mSocket >= 0); - close(mSocket); - mSocket = -1; - - mState = READY; - - return OK; -} - -status_t HTTPStream::send(const char *data, size_t size) { - if (mState != CONNECTED) { - return ERROR_NOT_CONNECTED; - } - - while (size > 0) { - ssize_t n; - if (mSSL != NULL) { - n = SSL_write((SSL *)mSSL, data, size); - - if (n < 0) { - n = -SSL_get_error((SSL *)mSSL, n); - } - } else { - n = MySend(mSocket, data, size, 0); - } - - if (n < 0) { - disconnect(); - - return n; - } else if (n == 0) { - disconnect(); - - return ERROR_CONNECTION_LOST; - } - - size -= (size_t)n; - data += (size_t)n; - } - - return OK; -} - -status_t HTTPStream::send(const char *data) { - return send(data, strlen(data)); -} - -// A certain application spawns a local webserver that sends invalid responses, -// specifically it terminates header line with only a newline instead of the -// CRLF (carriage-return followed by newline) required by the HTTP specs. -// The workaround accepts both behaviours but could potentially break -// legitimate responses that use a single newline to "fold" headers, which is -// why it's not yet on by default. -#define WORKAROUND_FOR_MISSING_CR 1 - -status_t HTTPStream::receive_line(char *line, size_t size) { - if (mState != CONNECTED) { - return ERROR_NOT_CONNECTED; - } - - bool saw_CR = false; - size_t length = 0; - - for (;;) { - char c; - ssize_t n; - if (mSSL != NULL) { - n = SSL_read((SSL *)mSSL, &c, 1); - - if (n < 0) { - n = -SSL_get_error((SSL *)mSSL, n); - } - } else { - n = MyReceive(mSocket, &c, 1, 0); - } - - if (n < 0) { - disconnect(); - - return ERROR_IO; - } else if (n == 0) { - disconnect(); - - return ERROR_CONNECTION_LOST; - } - -#if WORKAROUND_FOR_MISSING_CR - if (c == '\n') { - // We have a complete line. - - line[saw_CR ? length - 1 : length] = '\0'; - return OK; - } -#else - if (saw_CR && c == '\n') { - // We have a complete line. - - line[length - 1] = '\0'; - return OK; - } -#endif - - saw_CR = (c == '\r'); - - if (length + 1 >= size) { - return ERROR_MALFORMED; - } - line[length++] = c; - } -} - -status_t HTTPStream::receive_header(int *http_status) { - *http_status = -1; - mHeaders.clear(); - - char line[2048]; - status_t err = receive_line(line, sizeof(line)); - if (err != OK) { - return err; - } - - mHeaders.add(AString(kStatusKey), AString(line)); - - char *spacePos = strchr(line, ' '); - if (spacePos == NULL) { - // Malformed response? - return UNKNOWN_ERROR; - } - - char *status_start = spacePos + 1; - char *status_end = status_start; - while (isdigit(*status_end)) { - ++status_end; - } - - if (status_end == status_start) { - // Malformed response, status missing? - return UNKNOWN_ERROR; - } - - memmove(line, status_start, status_end - status_start); - line[status_end - status_start] = '\0'; - - long tmp = strtol(line, NULL, 10); - if (tmp < 0 || tmp > 999) { - return UNKNOWN_ERROR; - } - - *http_status = (int)tmp; - - for (;;) { - err = receive_line(line, sizeof(line)); - if (err != OK) { - return err; - } - - if (*line == '\0') { - // Empty line signals the end of the header. - break; - } - - // puts(line); - - char *colonPos = strchr(line, ':'); - if (colonPos == NULL) { - AString key = line; - key.tolower(); - - mHeaders.add(key, AString()); - } else { - char *end_of_key = colonPos; - while (end_of_key > line && isspace(end_of_key[-1])) { - --end_of_key; - } - - char *start_of_value = colonPos + 1; - while (isspace(*start_of_value)) { - ++start_of_value; - } - - *end_of_key = '\0'; - - AString key = line; - key.tolower(); - - mHeaders.add(key, AString(start_of_value)); - } - } - - return OK; -} - -ssize_t HTTPStream::receive(void *data, size_t size) { - size_t total = 0; - while (total < size) { - ssize_t n; - if (mSSL != NULL) { - n = SSL_read((SSL *)mSSL, (char *)data + total, size - total); - - if (n < 0) { - n = -SSL_get_error((SSL *)mSSL, n); - } - } else { - n = MyReceive(mSocket, (char *)data + total, size - total, 0); - } - - if (n < 0) { - LOGE("recv failed, errno = %d (%s)", (int)n, strerror(-n)); - - disconnect(); - return (ssize_t)ERROR_IO; - } else if (n == 0) { - disconnect(); - - LOGE("recv failed, server is gone, total received: %d bytes", - total); - - return total == 0 ? (ssize_t)ERROR_CONNECTION_LOST : total; - } - - total += (size_t)n; - } - - return (ssize_t)total; -} - -bool HTTPStream::find_header_value(const AString &key, AString *value) const { - AString key_lower = key; - key_lower.tolower(); - - ssize_t index = mHeaders.indexOfKey(key_lower); - if (index < 0) { - value->clear(); - return false; - } - - *value = mHeaders.valueAt(index); - - return true; -} - -void HTTPStream::setReceiveTimeout(int seconds) { - if (seconds < 0) { - // Disable the timeout. - seconds = 0; - } - - struct timeval tv; - tv.tv_usec = 0; - tv.tv_sec = seconds; - CHECK_EQ(0, setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))); -} - -// static -void HTTPStream::RegisterSocketUser(int s, uid_t uid) { - // Lower bits MUST be 0. - static const uint64_t kTag = 0xdeadbeef00000000ll; - - AString line = StringPrintf("t %d %llu %d", s, kTag, uid); - - int fd = open("/proc/net/xt_qtaguid/ctrl", O_WRONLY); - write(fd, line.c_str(), line.size()); - close(fd); - fd = -1; -} - -} // namespace android - diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp deleted file mode 100644 index 2949767..0000000 --- a/media/libstagefright/NuHTTPDataSource.cpp +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "NuHTTPDataSource" -#include - -#include "include/NuHTTPDataSource.h" - -#include -#include -#include -#include - -namespace android { - -static bool ParseSingleUnsignedLong( - const char *from, unsigned long *x) { - char *end; - *x = strtoul(from, &end, 10); - - if (end == from || *end != '\0') { - return false; - } - - return true; -} - -static bool ParseURL( - const char *url, String8 *host, unsigned *port, - String8 *path, bool *https) { - host->setTo(""); - *port = 0; - path->setTo(""); - - size_t hostStart; - if (!strncasecmp("http://", url, 7)) { - hostStart = 7; - *https = false; - } else if (!strncasecmp("https://", url, 8)) { - hostStart = 8; - *https = true; - } else { - return false; - } - - const char *slashPos = strchr(&url[hostStart], '/'); - - if (slashPos == NULL) { - host->setTo(&url[hostStart]); - path->setTo("/"); - } else { - host->setTo(&url[hostStart], slashPos - &url[hostStart]); - path->setTo(slashPos); - } - - const char *colonPos = strchr(host->string(), ':'); - - if (colonPos != NULL) { - unsigned long x; - if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) { - return false; - } - - *port = x; - - size_t colonOffset = colonPos - host->string(); - String8 tmp(host->string(), colonOffset); - *host = tmp; - } else { - *port = (*https) ? 443 : 80; - } - - return true; -} - -NuHTTPDataSource::NuHTTPDataSource(uint32_t flags) - : mFlags(flags), - mState(DISCONNECTED), - mPort(0), - mHTTPS(false), - mOffset(0), - mContentLength(0), - mContentLengthValid(false), - mHasChunkedTransferEncoding(false), - mChunkDataBytesLeft(0), - mDecryptHandle(NULL), - mDrmManagerClient(NULL) { -} - -NuHTTPDataSource::~NuHTTPDataSource() { - if (mDecryptHandle != NULL) { - // To release mDecryptHandle - CHECK(mDrmManagerClient); - mDrmManagerClient->closeDecryptSession(mDecryptHandle); - mDecryptHandle = NULL; - } - - if (mDrmManagerClient != NULL) { - delete mDrmManagerClient; - mDrmManagerClient = NULL; - } -} - -status_t NuHTTPDataSource::connect( - const char *uri, - const KeyedVector *overrides, - off64_t offset) { - String8 headers; - MakeFullHeaders(overrides, &headers); - - return connect(uri, headers, offset); -} - -status_t NuHTTPDataSource::connect( - const char *uri, - const String8 &headers, - off64_t offset) { - String8 host, path; - unsigned port; - - mUri = uri; - mContentType = String8("application/octet-stream"); - - bool https; - if (!ParseURL(uri, &host, &port, &path, &https)) { - return ERROR_MALFORMED; - } - - uid_t uid; - if (getUID(&uid)) { - mHTTP.setUID(uid); - } - - return connect(host, port, path, https, headers, offset); -} - -static bool IsRedirectStatusCode(int httpStatus) { - return httpStatus == 301 || httpStatus == 302 - || httpStatus == 303 || httpStatus == 307; -} - -status_t NuHTTPDataSource::connect( - const char *host, unsigned port, const char *path, - bool https, - const String8 &headers, - off64_t offset) { - if (!(mFlags & kFlagIncognito)) { - LOGI("connect to %s:%u%s @%lld", host, port, path, offset); - } else { - LOGI("connect to @%lld", offset); - } - - bool needsToReconnect = true; - - if (mState == CONNECTED && host == mHost && port == mPort - && https == mHTTPS && offset == mOffset) { - if (mContentLengthValid && mOffset == mContentLength) { - LOGI("Didn't have to reconnect, old one's still good."); - needsToReconnect = false; - } - } - - mHost = host; - mPort = port; - mPath = path; - mHTTPS = https; - mHeaders = headers; - - status_t err = OK; - - mState = CONNECTING; - - if (needsToReconnect) { - mHTTP.disconnect(); - err = mHTTP.connect(host, port, https); - } - - if (err != OK) { - mState = DISCONNECTED; - } else if (mState != CONNECTING) { - err = UNKNOWN_ERROR; - } else { - mState = CONNECTED; - - mOffset = offset; - mContentLength = 0; - mContentLengthValid = false; - - String8 request("GET "); - request.append(mPath); - request.append(" HTTP/1.1\r\n"); - request.append("Host: "); - request.append(mHost); - if (mPort != 80) { - request.append(StringPrintf(":%u", mPort).c_str()); - } - request.append("\r\n"); - - if (offset != 0) { - char rangeHeader[128]; - sprintf(rangeHeader, "Range: bytes=%lld-\r\n", offset); - request.append(rangeHeader); - } - - request.append(mHeaders); - request.append("\r\n"); - - int httpStatus; - if ((err = mHTTP.send(request.string(), request.size())) != OK - || (err = mHTTP.receive_header(&httpStatus)) != OK) { - mHTTP.disconnect(); - mState = DISCONNECTED; - return err; - } - - if (IsRedirectStatusCode(httpStatus)) { - AString value; - CHECK(mHTTP.find_header_value("Location", &value)); - - mState = DISCONNECTED; - - mHTTP.disconnect(); - - return connect(value.c_str(), headers, offset); - } - - if (httpStatus < 200 || httpStatus >= 300) { - mState = DISCONNECTED; - mHTTP.disconnect(); - - return ERROR_IO; - } - - mHasChunkedTransferEncoding = false; - - { - AString value; - if (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; - } - } - } - - { - AString value; - if (mHTTP.find_header_value("Content-Type", &value)) { - mContentType = String8(value.c_str()); - } else { - mContentType = String8("application/octet-stream"); - } - } - - applyTimeoutResponse(); - - if (offset == 0) { - AString value; - unsigned long x; - if (mHTTP.find_header_value(AString("Content-Length"), &value) - && ParseSingleUnsignedLong(value.c_str(), &x)) { - mContentLength = (off64_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; - } - - AString value; - unsigned long x; - if (mHTTP.find_header_value(AString("Content-Range"), &value)) { - const char *slashPos = strchr(value.c_str(), '/'); - if (slashPos != NULL - && ParseSingleUnsignedLong(slashPos + 1, &x)) { - mContentLength = x; - mContentLengthValid = true; - } - } - } - } - - return err; -} - -void NuHTTPDataSource::disconnect() { - if (mState == CONNECTING || mState == CONNECTED) { - mHTTP.disconnect(); - } - mState = DISCONNECTED; -} - -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(off64_t offset, void *data, size_t size) { - LOGV("readAt offset %ld, size %d", offset, size); - - Mutex::Autolock autoLock(mLock); - - if (offset != mOffset) { - String8 host = mHost; - String8 path = mPath; - String8 headers = mHeaders; - status_t err = connect(host, mPort, path, mHTTPS, headers, offset); - - if (err != OK) { - return err; - } - } - - if (mContentLengthValid) { - size_t avail = - (offset >= mContentLength) ? 0 : mContentLength - offset; - - if (size > avail) { - size = avail; - } - } - - size_t numBytesRead = 0; - while (numBytesRead < size) { - int64_t startTimeUs = ALooper::GetNowUs(); - - ssize_t n = - internalRead((uint8_t *)data + numBytesRead, size - numBytesRead); - - if (n < 0) { - if (numBytesRead == 0 || mContentLengthValid) { - return n; - } - - // If there was an error we want to at least return the data - // we've already successfully read. The next call to read will - // then return the error. - n = 0; - } - - int64_t delayUs = ALooper::GetNowUs() - startTimeUs; - addBandwidthMeasurement(n, delayUs); - - numBytesRead += (size_t)n; - - if (n == 0) { - if (mContentLengthValid) { - // We know the content length and made sure not to read beyond - // it and yet the server closed the connection on us. - return ERROR_IO; - } - - break; - } - } - - mOffset += numBytesRead; - - return numBytesRead; -} - -status_t NuHTTPDataSource::getSize(off64_t *size) { - *size = 0; - - if (mState != CONNECTED) { - return ERROR_IO; - } - - if (mContentLengthValid) { - *size = mContentLength; - return OK; - } - - return ERROR_UNSUPPORTED; -} - -uint32_t NuHTTPDataSource::flags() { - return kWantsPrefetching | kIsHTTPBasedSource; -} - -// static -void NuHTTPDataSource::MakeFullHeaders( - const KeyedVector *overrides, String8 *headers) { - headers->setTo(""); - - headers->append("User-Agent: stagefright/1.1 (Linux;Android "); - -#if (PROPERTY_VALUE_MAX < 8) -#error "PROPERTY_VALUE_MAX must be at least 8" -#endif - - char value[PROPERTY_VALUE_MAX]; - property_get("ro.build.version.release", value, "Unknown"); - headers->append(value); - headers->append(")\r\n"); - - if (overrides == NULL) { - return; - } - - for (size_t i = 0; i < overrides->size(); ++i) { - String8 line; - line.append(overrides->keyAt(i)); - line.append(": "); - line.append(overrides->valueAt(i)); - line.append("\r\n"); - - headers->append(line); - } -} - -void NuHTTPDataSource::applyTimeoutResponse() { - AString timeout; - if (mHTTP.find_header_value("X-SocketTimeout", &timeout)) { - const char *s = timeout.c_str(); - char *end; - long tmp = strtol(s, &end, 10); - if (end == s || *end != '\0') { - LOGW("Illegal X-SocketTimeout value given."); - return; - } - - LOGI("overriding default timeout, new timeout is %ld seconds", tmp); - mHTTP.setReceiveTimeout(tmp); - } -} - -sp NuHTTPDataSource::DrmInitialization() { - if (mDrmManagerClient == NULL) { - mDrmManagerClient = new DrmManagerClient(); - } - - if (mDrmManagerClient == NULL) { - return NULL; - } - - if (mDecryptHandle == NULL) { - /* Note if redirect occurs, mUri is the redirect uri instead of the - * original one - */ - mDecryptHandle = mDrmManagerClient->openDecryptSession(mUri); - } - - if (mDecryptHandle == NULL) { - delete mDrmManagerClient; - mDrmManagerClient = NULL; - } - - return mDecryptHandle; -} - -void NuHTTPDataSource::getDrmInfo(sp &handle, DrmManagerClient **client) { - handle = mDecryptHandle; - - *client = mDrmManagerClient; -} - -String8 NuHTTPDataSource::getUri() { - return mUri; -} - -String8 NuHTTPDataSource::getMIMEType() const { - return mContentType; -} - -} // namespace android diff --git a/media/libstagefright/ShoutcastSource.cpp b/media/libstagefright/ShoutcastSource.cpp deleted file mode 100644 index 783f2d0..0000000 --- a/media/libstagefright/ShoutcastSource.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "include/HTTPStream.h" - -#include - -#include -#include -#include -#include -#include -#include - -namespace android { - -ShoutcastSource::ShoutcastSource(HTTPStream *http) - : mHttp(http), - mMetaDataOffset(0), - mBytesUntilMetaData(0), - mGroup(NULL), - mStarted(false) { - AString metaint; - if (mHttp->find_header_value("icy-metaint", &metaint)) { - char *end; - const char *start = metaint.c_str(); - mMetaDataOffset = strtol(start, &end, 10); - CHECK(end > start && *end == '\0'); - CHECK(mMetaDataOffset > 0); - - mBytesUntilMetaData = mMetaDataOffset; - } -} - -ShoutcastSource::~ShoutcastSource() { - if (mStarted) { - stop(); - } - - delete mHttp; - mHttp = NULL; -} - -status_t ShoutcastSource::start(MetaData *) { - CHECK(!mStarted); - - mGroup = new MediaBufferGroup; - mGroup->add_buffer(new MediaBuffer(4096)); // XXX - - mStarted = true; - - return OK; -} - -status_t ShoutcastSource::stop() { - CHECK(mStarted); - - delete mGroup; - mGroup = NULL; - - mStarted = false; - - return OK; -} - -sp ShoutcastSource::getFormat() { - sp meta = new MetaData; - meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); - meta->setInt32(kKeySampleRate, 44100); - meta->setInt32(kKeyChannelCount, 2); // XXX - - return meta; -} - -status_t ShoutcastSource::read( - MediaBuffer **out, const ReadOptions *options) { - CHECK(mStarted); - - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - if (options && options->getSeekTo(&seekTimeUs, &mode)) { - return ERROR_UNSUPPORTED; - } - - MediaBuffer *buffer; - status_t err = mGroup->acquire_buffer(&buffer); - if (err != OK) { - return err; - } - - *out = buffer; - - size_t num_bytes = buffer->size(); - if (mMetaDataOffset > 0 && num_bytes > mBytesUntilMetaData) { - num_bytes = mBytesUntilMetaData; - } - - ssize_t n = mHttp->receive(buffer->data(), num_bytes); - - if (n <= 0) { - return (status_t)n; - } - - buffer->set_range(0, n); - - mBytesUntilMetaData -= (size_t)n; - - if (mBytesUntilMetaData == 0) { - unsigned char num_16_byte_blocks = 0; - n = mHttp->receive((char *)&num_16_byte_blocks, 1); - CHECK_EQ(n, 1); - - char meta[255 * 16]; - size_t meta_size = num_16_byte_blocks * 16; - size_t meta_length = 0; - while (meta_length < meta_size) { - n = mHttp->receive(&meta[meta_length], meta_size - meta_length); - if (n <= 0) { - return (status_t)n; - } - - meta_length += (size_t) n; - } - - while (meta_length > 0 && meta[meta_length - 1] == '\0') { - --meta_length; - } - - if (meta_length > 0) { - // Technically we should probably attach this meta data to the - // next buffer. XXX - buffer->meta_data()->setData('shou', 'shou', meta, meta_length); - } - - mBytesUntilMetaData = mMetaDataOffset; - } - - return OK; -} - -} // namespace android - diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h index 2e25dd9..0e9af69 100644 --- a/media/libstagefright/include/HTTPBase.h +++ b/media/libstagefright/include/HTTPBase.h @@ -53,6 +53,8 @@ struct HTTPBase : public DataSource { static sp Create(uint32_t flags = 0); + static void RegisterSocketUser(int s, uid_t uid); + protected: void addBandwidthMeasurement(size_t numBytes, int64_t delayUs); diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h deleted file mode 100644 index 88ba9d6..0000000 --- a/media/libstagefright/include/HTTPStream.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef HTTP_STREAM_H_ - -#define HTTP_STREAM_H_ - -#include - -#include -#include -#include -#include - -namespace android { - -class HTTPStream { -public: - HTTPStream(); - ~HTTPStream(); - - void setUID(uid_t uid); - - status_t connect(const char *server, int port = -1, bool https = false); - status_t disconnect(); - - status_t send(const char *data, size_t size); - - // Assumes data is a '\0' terminated string. - status_t send(const char *data); - - // Receive up to "size" bytes of data. - ssize_t receive(void *data, size_t size); - - status_t receive_header(int *http_status); - - // The header key used to retrieve the status line. - static const char *kStatusKey; - - bool find_header_value( - const AString &key, AString *value) const; - - // Pass a negative value to disable the timeout. - void setReceiveTimeout(int seconds); - - // Receive a line of data terminated by CRLF, line will be '\0' terminated - // _excluding_ the termianting CRLF. - status_t receive_line(char *line, size_t size); - - static void RegisterSocketUser(int s, uid_t uid); - -private: - enum State { - READY, - CONNECTING, - CONNECTED - }; - - State mState; - Mutex mLock; - - bool mUIDValid; - uid_t mUID; - - int mSocket; - - KeyedVector mHeaders; - - void *mSSLContext; - void *mSSL; - - HTTPStream(const HTTPStream &); - HTTPStream &operator=(const HTTPStream &); -}; - -} // namespace android - -#endif // HTTP_STREAM_H_ diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h deleted file mode 100644 index c265b3a..0000000 --- a/media/libstagefright/include/NuHTTPDataSource.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NU_HTTP_DATA_SOURCE_H_ - -#define NU_HTTP_DATA_SOURCE_H_ - -#include -#include -#include - -#include "HTTPStream.h" -#include "include/HTTPBase.h" - -namespace android { - -struct NuHTTPDataSource : public HTTPBase { - NuHTTPDataSource(uint32_t flags = 0); - - virtual status_t connect( - const char *uri, - const KeyedVector *headers = NULL, - off64_t offset = 0); - - virtual void disconnect(); - - virtual status_t initCheck() const; - - virtual ssize_t readAt(off64_t offset, void *data, size_t size); - virtual status_t getSize(off64_t *size); - virtual uint32_t flags(); - - virtual sp DrmInitialization(); - virtual void getDrmInfo(sp &handle, DrmManagerClient **client); - virtual String8 getUri(); - - virtual String8 getMIMEType() const; - -protected: - virtual ~NuHTTPDataSource(); - -private: - enum State { - DISCONNECTED, - CONNECTING, - CONNECTED - }; - - Mutex mLock; - - uint32_t mFlags; - - State mState; - - String8 mHost; - unsigned mPort; - String8 mPath; - bool mHTTPS; - String8 mHeaders; - String8 mUri; - - HTTPStream mHTTP; - off64_t mOffset; - off64_t mContentLength; - bool mContentLengthValid; - bool mHasChunkedTransferEncoding; - - String8 mContentType; - - // The number of data bytes in the current chunk before any subsequent - // chunk header (or -1 if no more chunks). - ssize_t mChunkDataBytesLeft; - - sp mDecryptHandle; - DrmManagerClient *mDrmManagerClient; - - status_t connect( - const char *uri, const String8 &headers, off64_t offset); - - status_t connect( - const char *host, unsigned port, const char *path, - bool https, - const String8 &headers, - off64_t offset); - - // Read up to "size" bytes of data, respect transfer encoding. - ssize_t internalRead(void *data, size_t size); - - void applyTimeoutResponse(); - - static void MakeFullHeaders( - const KeyedVector *overrides, - String8 *headers); - - NuHTTPDataSource(const NuHTTPDataSource &); - NuHTTPDataSource &operator=(const NuHTTPDataSource &); -}; - -} // namespace android - -#endif // NU_HTTP_DATA_SOURCE_H_ diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp index 072d6b2..b398c9d 100644 --- a/media/libstagefright/rtsp/ARTSPConnection.cpp +++ b/media/libstagefright/rtsp/ARTSPConnection.cpp @@ -34,7 +34,7 @@ #include #include -#include "HTTPStream.h" +#include "HTTPBase.h" namespace android { @@ -251,7 +251,7 @@ void ARTSPConnection::onConnect(const sp &msg) { mSocket = socket(AF_INET, SOCK_STREAM, 0); if (mUIDValid) { - HTTPStream::RegisterSocketUser(mSocket, mUID); + HTTPBase::RegisterSocketUser(mSocket, mUID); } MakeSocketBlocking(mSocket, false); diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index 3188959..71d68f6 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -40,7 +40,7 @@ #include #include -#include "HTTPStream.h" +#include "HTTPBase.h" // If no access units are received within 5 secs, assume that the rtp // stream has ended and signal end of stream. @@ -1181,8 +1181,8 @@ private: &info->mRTPSocket, &info->mRTCPSocket, &rtpPort); if (mUIDValid) { - HTTPStream::RegisterSocketUser(info->mRTPSocket, mUID); - HTTPStream::RegisterSocketUser(info->mRTCPSocket, mUID); + HTTPBase::RegisterSocketUser(info->mRTPSocket, mUID); + HTTPBase::RegisterSocketUser(info->mRTCPSocket, mUID); } request.append("Transport: RTP/AVP/UDP;unicast;client_port="); -- cgit v1.1