diff options
author | Andreas Huber <andih@google.com> | 2011-02-17 13:35:08 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2011-02-17 14:30:05 -0800 |
commit | 8cb0c4168bf4b678e4a6edfcf409247016be20d5 (patch) | |
tree | d3a274bc9913bacca91d58456697823b31bbaf93 | |
parent | f71eb135c28dd7b305b7030776ef0d44fac732c4 (diff) | |
download | frameworks_av-8cb0c4168bf4b678e4a6edfcf409247016be20d5.zip frameworks_av-8cb0c4168bf4b678e4a6edfcf409247016be20d5.tar.gz frameworks_av-8cb0c4168bf4b678e4a6edfcf409247016be20d5.tar.bz2 |
Experimental support for https transfers in stagefright.
Change-Id: If1bd0f265dda136c7c34b53317f64383023b53a3
-rw-r--r-- | media/libstagefright/Android.mk | 6 | ||||
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 3 | ||||
-rw-r--r-- | media/libstagefright/DataSource.cpp | 3 | ||||
-rw-r--r-- | media/libstagefright/HTTPStream.cpp | 99 | ||||
-rw-r--r-- | media/libstagefright/NuHTTPDataSource.cpp | 34 | ||||
-rw-r--r-- | media/libstagefright/httplive/LiveSession.cpp | 3 | ||||
-rw-r--r-- | media/libstagefright/include/HTTPStream.h | 5 | ||||
-rw-r--r-- | media/libstagefright/include/NuHTTPDataSource.h | 2 |
8 files changed, 133 insertions, 22 deletions
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 53435f8..80eb59f 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -58,7 +58,8 @@ LOCAL_C_INCLUDES:= \ $(TOP)/frameworks/base/include/media/stagefright/openmax \ $(TOP)/external/flac/include \ $(TOP)/external/tremolo \ - $(TOP)/frameworks/base/media/libstagefright/rtsp + $(TOP)/frameworks/base/media/libstagefright/rtsp \ + $(TOP)/external/openssl/include \ LOCAL_SHARED_LIBRARIES := \ libbinder \ @@ -72,7 +73,8 @@ LOCAL_SHARED_LIBRARIES := \ libstagefright_yuv \ libcamera_client \ libdrmframework \ - libcrypto + libcrypto \ + libssl LOCAL_STATIC_LIBRARIES := \ libstagefright_color_conversion \ diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 8866750..b1d3630 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -1481,7 +1481,8 @@ status_t AwesomePlayer::prepareAsync_l() { status_t AwesomePlayer::finishSetDataSource_l() { sp<DataSource> dataSource; - if (!strncasecmp("http://", mUri.string(), 7)) { + if (!strncasecmp("http://", mUri.string(), 7) + || !strncasecmp("https://", mUri.string(), 8)) { mConnectingDataSource = new NuHTTPDataSource; mLock.unlock(); diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index 8f9c150..3b38208 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -125,7 +125,8 @@ sp<DataSource> DataSource::CreateFromURI( sp<DataSource> source; if (!strncasecmp("file://", uri, 7)) { source = new FileSource(uri + 7); - } else if (!strncasecmp("http://", uri, 7)) { + } else if (!strncasecmp("http://", uri, 7) + || !strncasecmp("https://", uri, 8)) { sp<NuHTTPDataSource> httpSource = new NuHTTPDataSource; if (httpSource->connect(uri, headers) != OK) { return NULL; diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp index 77a61a5..498c7b8 100644 --- a/media/libstagefright/HTTPStream.cpp +++ b/media/libstagefright/HTTPStream.cpp @@ -34,6 +34,8 @@ #include <media/stagefright/foundation/ADebug.h> +#include <openssl/ssl.h> + namespace android { // static @@ -41,11 +43,18 @@ const char *HTTPStream::kStatusKey = ":status:"; // MUST be lowercase. HTTPStream::HTTPStream() : mState(READY), - mSocket(-1) { + mSocket(-1), + mSSLContext(NULL), + mSSL(NULL) { } HTTPStream::~HTTPStream() { disconnect(); + + if (mSSLContext != NULL) { + SSL_CTX_free((SSL_CTX *)mSSLContext); + mSSLContext = NULL; + } } static bool MakeSocketBlocking(int s, bool blocking) { @@ -198,7 +207,11 @@ 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) { +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; @@ -249,6 +262,47 @@ status_t HTTPStream::connect(const char *server, int port) { 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; @@ -261,6 +315,13 @@ status_t HTTPStream::disconnect() { return ERROR_NOT_CONNECTED; } + if (mSSL != NULL) { + SSL_shutdown((SSL *)mSSL); + + SSL_free((SSL *)mSSL); + mSSL = NULL; + } + CHECK(mSocket >= 0); close(mSocket); mSocket = -1; @@ -276,7 +337,16 @@ status_t HTTPStream::send(const char *data, size_t size) { } while (size > 0) { - ssize_t n = MySend(mSocket, data, 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(); @@ -317,7 +387,17 @@ status_t HTTPStream::receive_line(char *line, size_t size) { for (;;) { char c; - ssize_t n = MyReceive(mSocket, &c, 1, 0); + 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(); @@ -437,7 +517,16 @@ status_t HTTPStream::receive_header(int *http_status) { ssize_t HTTPStream::receive(void *data, size_t size) { size_t total = 0; while (total < size) { - ssize_t n = MyReceive(mSocket, (char *)data + total, size - total, 0); + 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)); diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp index 0376e1c..e39fab3 100644 --- a/media/libstagefright/NuHTTPDataSource.cpp +++ b/media/libstagefright/NuHTTPDataSource.cpp @@ -24,22 +24,30 @@ static bool ParseSingleUnsignedLong( } static bool ParseURL( - const char *url, String8 *host, unsigned *port, String8 *path) { + const char *url, String8 *host, unsigned *port, + String8 *path, bool *https) { host->setTo(""); *port = 0; path->setTo(""); - if (strncasecmp("http://", url, 7)) { + 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[7], '/'); + const char *slashPos = strchr(&url[hostStart], '/'); if (slashPos == NULL) { - host->setTo(&url[7]); + host->setTo(&url[hostStart]); path->setTo("/"); } else { - host->setTo(&url[7], slashPos - &url[7]); + host->setTo(&url[hostStart], slashPos - &url[hostStart]); path->setTo(slashPos); } @@ -57,7 +65,7 @@ static bool ParseURL( String8 tmp(host->string(), colonOffset); *host = tmp; } else { - *port = 80; + *port = (*https) ? 443 : 80; } return true; @@ -66,6 +74,7 @@ static bool ParseURL( NuHTTPDataSource::NuHTTPDataSource() : mState(DISCONNECTED), mPort(0), + mHTTPS(false), mOffset(0), mContentLength(0), mContentLengthValid(false), @@ -111,11 +120,12 @@ status_t NuHTTPDataSource::connect( mUri = uri; - if (!ParseURL(uri, &host, &port, &path)) { + bool https; + if (!ParseURL(uri, &host, &port, &path, &https)) { return ERROR_MALFORMED; } - return connect(host, port, path, headers, offset); + return connect(host, port, path, https, headers, offset); } static bool IsRedirectStatusCode(int httpStatus) { @@ -125,6 +135,7 @@ static bool IsRedirectStatusCode(int httpStatus) { status_t NuHTTPDataSource::connect( const char *host, unsigned port, const char *path, + bool https, const String8 &headers, off64_t offset) { LOGI("connect to %s:%u%s @%lld", host, port, path, offset); @@ -132,7 +143,7 @@ status_t NuHTTPDataSource::connect( bool needsToReconnect = true; if (mState == CONNECTED && host == mHost && port == mPort - && offset == mOffset) { + && https == mHTTPS && offset == mOffset) { if (mContentLengthValid && mOffset == mContentLength) { LOGI("Didn't have to reconnect, old one's still good."); needsToReconnect = false; @@ -142,6 +153,7 @@ status_t NuHTTPDataSource::connect( mHost = host; mPort = port; mPath = path; + mHTTPS = https; mHeaders = headers; status_t err = OK; @@ -150,7 +162,7 @@ status_t NuHTTPDataSource::connect( if (needsToReconnect) { mHTTP.disconnect(); - err = mHTTP.connect(host, port); + err = mHTTP.connect(host, port, https); } if (err != OK) { @@ -353,7 +365,7 @@ ssize_t NuHTTPDataSource::readAt(off64_t offset, void *data, size_t size) { String8 host = mHost; String8 path = mPath; String8 headers = mHeaders; - status_t err = connect(host, mPort, path, headers, offset); + status_t err = connect(host, mPort, path, mHTTPS, headers, offset); if (err != OK) { return err; diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index f7a9085..ee845a3 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -189,7 +189,8 @@ status_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) { if (!strncasecmp(url, "file://", 7)) { source = new FileSource(url + 7); - } else if (strncasecmp(url, "http://", 7)) { + } else if (strncasecmp(url, "http://", 7) + && strncasecmp(url, "https://", 8)) { return ERROR_UNSUPPORTED; } else { { diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h index 545cd0c..09e6a5f 100644 --- a/media/libstagefright/include/HTTPStream.h +++ b/media/libstagefright/include/HTTPStream.h @@ -32,7 +32,7 @@ public: HTTPStream(); ~HTTPStream(); - status_t connect(const char *server, int port = 80); + status_t connect(const char *server, int port = -1, bool https = false); status_t disconnect(); status_t send(const char *data, size_t size); @@ -71,6 +71,9 @@ private: KeyedVector<AString, AString> mHeaders; + void *mSSLContext; + void *mSSL; + HTTPStream(const HTTPStream &); HTTPStream &operator=(const HTTPStream &); }; diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h index a99e84a..3918434 100644 --- a/media/libstagefright/include/NuHTTPDataSource.h +++ b/media/libstagefright/include/NuHTTPDataSource.h @@ -57,6 +57,7 @@ private: String8 mHost; unsigned mPort; String8 mPath; + bool mHTTPS; String8 mHeaders; String8 mUri; @@ -83,6 +84,7 @@ private: status_t connect( const char *host, unsigned port, const char *path, + bool https, const String8 &headers, off64_t offset); |