Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f0a4853 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Experimental support for https transfers in stagefright."

parents 5b025c46 118a150a
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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 \
+2 −1
Original line number Diff line number Diff line
@@ -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();
+2 −1
Original line number Diff line number Diff line
@@ -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;
+94 −5
Original line number Diff line number Diff line
@@ -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));
+23 −11
Original line number Diff line number Diff line
@@ -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;
Loading