139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber/*
239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * Copyright (C) 2010 The Android Open Source Project
339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber *
439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * you may not use this file except in compliance with the License.
639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * You may obtain a copy of the License at
739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber *
839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber *
1039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * Unless required by applicable law or agreed to in writing, software
1139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * See the License for the specific language governing permissions and
1439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber * limitations under the License.
1539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber */
1639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
176e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber//#define LOG_NDEBUG 0
186e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#define LOG_TAG "UDPPusher"
196e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#include <utils/Log.h>
206e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber
2139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "UDPPusher.h"
2239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
2339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
2439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/ADebug.h>
2539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/AMessage.h>
2639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <utils/ByteOrder.h>
2739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
2839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <sys/socket.h>
2939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
3039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubernamespace android {
3139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
3239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas HuberUDPPusher::UDPPusher(const char *filename, unsigned port)
3339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    : mFile(fopen(filename, "rb")),
3439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber      mFirstTimeMs(0),
3539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber      mFirstTimeUs(0) {
3639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK(mFile != NULL);
3739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
3839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mSocket = socket(AF_INET, SOCK_DGRAM, 0);
3939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
4039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    struct sockaddr_in addr;
4139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
4239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    addr.sin_family = AF_INET;
4339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    addr.sin_addr.s_addr = INADDR_ANY;
4439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    addr.sin_port = 0;
4539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
4639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ(0, bind(mSocket, (const struct sockaddr *)&addr, sizeof(addr)));
4739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
4839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    memset(mRemoteAddr.sin_zero, 0, sizeof(mRemoteAddr.sin_zero));
4939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRemoteAddr.sin_family = AF_INET;
5039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRemoteAddr.sin_addr.s_addr = INADDR_ANY;
5139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRemoteAddr.sin_port = htons(port);
5239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
5339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
5439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas HuberUDPPusher::~UDPPusher() {
5539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    close(mSocket);
5639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mSocket = -1;
5739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
5839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    fclose(mFile);
5939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mFile = NULL;
6039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
6139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
6239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid UDPPusher::start() {
6339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint32_t timeMs;
6439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ(fread(&timeMs, 1, sizeof(timeMs), mFile), sizeof(timeMs));
6539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mFirstTimeMs = fromlel(timeMs);
6639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mFirstTimeUs = ALooper::GetNowUs();
6739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
681d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPush, this))->post();
6939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
7039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
7139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberbool UDPPusher::onPush() {
7239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint32_t length;
7339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (fread(&length, 1, sizeof(length), mFile) < sizeof(length)) {
74df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("No more data to push.");
7539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return false;
7639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
7739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
7839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    length = fromlel(length);
7939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
8039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GT(length, 0u);
8139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
8239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sp<ABuffer> buffer = new ABuffer(length);
8339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (fread(buffer->data(), 1, length, mFile) < length) {
8429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("File truncated?.");
8539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return false;
8639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
8739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
8839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    ssize_t n = sendto(
8939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            mSocket, buffer->data(), buffer->size(), 0,
9039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            (const struct sockaddr *)&mRemoteAddr, sizeof(mRemoteAddr));
9139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
9239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ(n, (ssize_t)buffer->size());
9339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
9439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint32_t timeMs;
9539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (fread(&timeMs, 1, sizeof(timeMs), mFile) < sizeof(timeMs)) {
96df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("No more data to push.");
9739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return false;
9839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
9939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
10039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    timeMs = fromlel(timeMs);
10139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GE(timeMs, mFirstTimeMs);
10239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
10339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    timeMs -= mFirstTimeMs;
10439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    int64_t whenUs = mFirstTimeUs + timeMs * 1000ll;
10539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    int64_t nowUs = ALooper::GetNowUs();
1061d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPush, this))->post(whenUs - nowUs);
10739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
10839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return true;
10939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
11039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
11139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid UDPPusher::onMessageReceived(const sp<AMessage> &msg) {
11239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    switch (msg->what()) {
11339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        case kWhatPush:
11439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        {
11539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            if (!onPush() && !(ntohs(mRemoteAddr.sin_port) & 1)) {
116df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                ALOGI("emulating BYE packet");
11739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
11839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                sp<ABuffer> buffer = new ABuffer(8);
11939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                uint8_t *data = buffer->data();
12039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                *data++ = (2 << 6) | 1;
12139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                *data++ = 203;
12239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                *data++ = 0;
12339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                *data++ = 1;
12439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                *data++ = 0x8f;
12539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                *data++ = 0x49;
12639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                *data++ = 0xc0;
12739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                *data++ = 0xd0;
12839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                buffer->setRange(0, 8);
12939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
13039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                struct sockaddr_in tmp = mRemoteAddr;
13139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                tmp.sin_port = htons(ntohs(mRemoteAddr.sin_port) | 1);
13239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
13339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                ssize_t n = sendto(
13439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                        mSocket, buffer->data(), buffer->size(), 0,
13539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                        (const struct sockaddr *)&tmp,
13639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                        sizeof(tmp));
13739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
13839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                CHECK_EQ(n, (ssize_t)buffer->size());
13939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
14039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            break;
14139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
14239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
14339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        default:
14439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            TRESPASS();
14539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            break;
14639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
14739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
14839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
14939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}  // namespace android
15039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
151