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

Commit 792eeb91 authored by Nico's avatar Nico Committed by Bruno Martins
Browse files

Partial revert "Move unused classes out of stagefright foundataion"



This imports the old foundation code in the standard platform stagefright.
The foundation variant is used in VNDK, we can't change the ABI there.

This reverts commit 5ec3d6ac.

Change-Id: Iebcf5d89a768fdb830bea90fbf2c2427a4c3d139
Signed-off-by: default avatarDennySPb <dennyspb@gmail.com>
Signed-off-by: default avatarLuca Stefani <luca.stefani.ge1@gmail.com>
parent 74c3785a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@
#include <media/IRemoteDisplayClient.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/ANetworkSession.h>
#include <media/stagefright/ANetworkSession.h>

namespace android {

+1400 −0

File added.

Preview size limit exceeded, changes collapsed.

+2 −0
Original line number Diff line number Diff line
@@ -296,6 +296,7 @@ cc_library {
        "ACodecBufferChannel.cpp",
        "AHierarchicalStateMachine.cpp",
        "AMRWriter.cpp",
        "ANetworkSession.cpp",
        "AudioSource.cpp",
        "BufferImpl.cpp",
        "CallbackDataSource.cpp",
@@ -325,6 +326,7 @@ cc_library {
        "OggWriter.cpp",
        "OMXClient.cpp",
        "OmxInfoBuilder.cpp",
        "ParsedMessage.cpp",
        "RemoteMediaExtractor.cpp",
        "RemoteMediaSource.cpp",
        "SimpleDecodingSource.cpp",
+301 −0
Original line number Diff line number Diff line
/*
 * Copyright 2012, 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 <ctype.h>
#include <media/stagefright/ParsedMessage.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/hexdump.h>

namespace android {

// static
sp<ParsedMessage> ParsedMessage::Parse(
        const char *data, size_t size, bool noMoreData, size_t *length) {
    sp<ParsedMessage> msg = new ParsedMessage;
    ssize_t res = msg->parse(data, size, noMoreData);

    if (res < 0) {
        *length = 0;
        return NULL;
    }

    *length = res;
    return msg;
}

ParsedMessage::ParsedMessage() {
}

ParsedMessage::~ParsedMessage() {
}

bool ParsedMessage::findString(const char *name, AString *value) const {
    AString key = name;
    key.tolower();

    ssize_t index = mDict.indexOfKey(key);

    if (index < 0) {
        value->clear();

        return false;
    }

    *value = mDict.valueAt(index);
    return true;
}

bool ParsedMessage::findInt32(const char *name, int32_t *value) const {
    AString stringValue;

    if (!findString(name, &stringValue)) {
        return false;
    }

    char *end;
    *value = strtol(stringValue.c_str(), &end, 10);

    if (end == stringValue.c_str() || *end != '\0') {
        *value = 0;
        return false;
    }

    return true;
}

const char *ParsedMessage::getContent() const {
    return mContent.c_str();
}

ssize_t ParsedMessage::parse(const char *data, size_t size, bool noMoreData) {
    if (size == 0) {
        return -1;
    }

    ssize_t lastDictIndex = -1;

    size_t offset = 0;
    bool headersComplete = false;
    while (offset < size) {
        size_t lineEndOffset = offset;
        while (lineEndOffset + 1 < size
                && (data[lineEndOffset] != '\r'
                        || data[lineEndOffset + 1] != '\n')) {
            ++lineEndOffset;
        }

        if (lineEndOffset + 1 >= size) {
            return -1;
        }

        AString line(&data[offset], lineEndOffset - offset);

        if (offset == 0) {
            // Special handling for the request/status line.

            mDict.add(AString("_"), line);
            offset = lineEndOffset + 2;

            continue;
        }

        if (lineEndOffset == offset) {
            // An empty line separates headers from body.
            headersComplete = true;
            offset += 2;
            break;
        }

        if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
            // Support for folded header values.

            if (lastDictIndex >= 0) {
                // Otherwise it's malformed since the first header line
                // cannot continue anything...

                AString &value = mDict.editValueAt(lastDictIndex);
                value.append(line);
            }

            offset = lineEndOffset + 2;
            continue;
        }

        ssize_t colonPos = line.find(":");
        if (colonPos >= 0) {
            AString key(line, 0, colonPos);
            key.trim();
            key.tolower();

            line.erase(0, colonPos + 1);

            lastDictIndex = mDict.add(key, line);
        }

        offset = lineEndOffset + 2;
    }

    if (!headersComplete && (!noMoreData || offset == 0)) {
        // We either saw the empty line separating headers from body
        // or we saw at least the status line and know that no more data
        // is going to follow.
        return -1;
    }

    for (size_t i = 0; i < mDict.size(); ++i) {
        mDict.editValueAt(i).trim();
    }

    int32_t contentLength;
    if (!findInt32("content-length", &contentLength) || contentLength < 0) {
        contentLength = 0;
    }

    size_t totalLength = offset + contentLength;

    if (size < totalLength) {
        return -1;
    }

    mContent.setTo(&data[offset], contentLength);

    return totalLength;
}

bool ParsedMessage::getRequestField(size_t index, AString *field) const {
    AString line;
    CHECK(findString("_", &line));

    size_t prevOffset = 0;
    size_t offset = 0;
    for (size_t i = 0; i <= index; ++i) {
        if (offset >= line.size()) {
            return false;
        }

        ssize_t spacePos = line.find(" ", offset);

        if (spacePos < 0) {
            spacePos = line.size();
        }

        prevOffset = offset;
        offset = spacePos + 1;
    }

    field->setTo(line, prevOffset, offset - prevOffset - 1);

    return true;
}

bool ParsedMessage::getStatusCode(int32_t *statusCode) const {
    AString statusCodeString;
    if (!getRequestField(1, &statusCodeString)) {
        *statusCode = 0;
        return false;
    }

    char *end;
    *statusCode = strtol(statusCodeString.c_str(), &end, 10);

    if (*end != '\0' || end == statusCodeString.c_str()
            || (*statusCode) < 100 || (*statusCode) > 999) {
        *statusCode = 0;
        return false;
    }

    return true;
}

AString ParsedMessage::debugString() const {
    AString line;
    CHECK(findString("_", &line));

    line.append("\n");

    for (size_t i = 0; i < mDict.size(); ++i) {
        const AString &key = mDict.keyAt(i);
        const AString &value = mDict.valueAt(i);

        if (key == AString("_")) {
            continue;
        }

        line.append(key);
        line.append(": ");
        line.append(value);
        line.append("\n");
    }

    line.append("\n");
    line.append(mContent);

    return line;
}

// static
bool ParsedMessage::GetAttribute(
        const char *s, const char *key, AString *value) {
    value->clear();

    size_t keyLen = strlen(key);

    for (;;) {
        while (isspace(*s)) {
            ++s;
        }

        const char *colonPos = strchr(s, ';');

        size_t len =
            (colonPos == NULL) ? strlen(s) : colonPos - s;

        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
            value->setTo(&s[keyLen + 1], len - keyLen - 1);
            return true;
        }

        if (colonPos == NULL) {
            return false;
        }

        s = colonPos + 1;
    }
}

// static
bool ParsedMessage::GetInt32Attribute(
        const char *s, const char *key, int32_t *value) {
    AString stringValue;
    if (!GetAttribute(s, key, &stringValue)) {
        *value = 0;
        return false;
    }

    char *end;
    *value = strtol(stringValue.c_str(), &end, 10);

    if (end == stringValue.c_str() || *end != '\0') {
        *value = 0;
        return false;
    }

    return true;
}

}  // namespace android
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright 2012, 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 A_NETWORK_SESSION_H_

#define A_NETWORK_SESSION_H_

#include <media/stagefright/foundation/ABase.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/Thread.h>

#include <netinet/in.h>

namespace android {

struct AMessage;

// Helper class to manage a number of live sockets (datagram and stream-based)
// on a single thread. Clients are notified about activity through AMessages.
struct ANetworkSession : public RefBase {
    ANetworkSession();

    status_t start();
    status_t stop();

    status_t createRTSPClient(
            const char *host, unsigned port, const sp<AMessage> &notify,
            int32_t *sessionID);

    status_t createRTSPServer(
            const struct in_addr &addr, unsigned port,
            const sp<AMessage> &notify, int32_t *sessionID);

    status_t createUDPSession(
            unsigned localPort, const sp<AMessage> &notify, int32_t *sessionID);

    status_t createUDPSession(
            unsigned localPort,
            const char *remoteHost,
            unsigned remotePort,
            const sp<AMessage> &notify,
            int32_t *sessionID);

    status_t connectUDPSession(
            int32_t sessionID, const char *remoteHost, unsigned remotePort);

    // passive
    status_t createTCPDatagramSession(
            const struct in_addr &addr, unsigned port,
            const sp<AMessage> &notify, int32_t *sessionID);

    // active
    status_t createTCPDatagramSession(
            unsigned localPort,
            const char *remoteHost,
            unsigned remotePort,
            const sp<AMessage> &notify,
            int32_t *sessionID);

    status_t destroySession(int32_t sessionID);

    status_t sendRequest(
            int32_t sessionID, const void *data, ssize_t size = -1,
            bool timeValid = false, int64_t timeUs = -1ll);

    status_t switchToWebSocketMode(int32_t sessionID);

    enum NotificationReason {
        kWhatError,
        kWhatConnected,
        kWhatClientConnected,
        kWhatData,
        kWhatDatagram,
        kWhatBinaryData,
        kWhatWebSocketMessage,
        kWhatNetworkStall,
    };

protected:
    virtual ~ANetworkSession();

private:
    struct NetworkThread;
    struct Session;

    Mutex mLock;
    sp<Thread> mThread;

    int32_t mNextSessionID;

    int mPipeFd[2];

    KeyedVector<int32_t, sp<Session> > mSessions;

    enum Mode {
        kModeCreateUDPSession,
        kModeCreateTCPDatagramSessionPassive,
        kModeCreateTCPDatagramSessionActive,
        kModeCreateRTSPServer,
        kModeCreateRTSPClient,
    };
    status_t createClientOrServer(
            Mode mode,
            const struct in_addr *addr,
            unsigned port,
            const char *remoteHost,
            unsigned remotePort,
            const sp<AMessage> &notify,
            int32_t *sessionID);

    void threadLoop();
    void interrupt();

    static status_t MakeSocketNonBlocking(int s);

    DISALLOW_EVIL_CONSTRUCTORS(ANetworkSession);
};

}  // namespace android

#endif  // A_NETWORK_SESSION_H_
Loading