UDPPusher.cpp revision 1d15ab58bf8239069ef343de6cb21aabf3ef7d78
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