RtpStream.cpp revision 8913af783fc2cf197ef55449792bb8416a356263
173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh/* 273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * Copyright (C) 2010 The Android Open Source Project 373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * 473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * you may not use this file except in compliance with the License. 673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * You may obtain a copy of the License at 773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * 873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * 1073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software 1173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 1273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * See the License for the specific language governing permissions and 1473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh * limitations under the License. 1573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh */ 1673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 1773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include <stdio.h> 1873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include <stdint.h> 1973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include <string.h> 2073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include <errno.h> 2173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include <sys/types.h> 2273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include <sys/socket.h> 2373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include <arpa/inet.h> 2473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include <netinet/in.h> 2573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 2673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#define LOG_TAG "RtpStream" 2773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include <utils/Log.h> 2873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 2973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include "jni.h" 3073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh#include "JNIHelp.h" 3173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 3273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yehextern int parse(JNIEnv *env, jstring jAddress, int port, sockaddr_storage *ss); 3373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 3473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yehnamespace { 3573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 3673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi YehjfieldID gNative; 3773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 3873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yehjint create(JNIEnv *env, jobject thiz, jstring jAddress) 3973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh{ 4073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh env->SetIntField(thiz, gNative, -1); 4173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 4273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh sockaddr_storage ss; 4373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh if (parse(env, jAddress, 0, &ss) < 0) { 4473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh // Exception already thrown. 4573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh return -1; 4673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } 4773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 4873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh int socket = ::socket(ss.ss_family, SOCK_DGRAM, 0); 4973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh socklen_t len = sizeof(ss); 5073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh if (socket == -1 || bind(socket, (sockaddr *)&ss, sizeof(ss)) != 0 || 5173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh getsockname(socket, (sockaddr *)&ss, &len) != 0) { 5273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh jniThrowException(env, "java/net/SocketException", strerror(errno)); 5373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh ::close(socket); 5473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh return -1; 5573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } 5673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 5773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh uint16_t *p = (ss.ss_family == AF_INET) ? 5873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh &((sockaddr_in *)&ss)->sin_port : &((sockaddr_in6 *)&ss)->sin6_port; 5973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh uint16_t port = ntohs(*p); 6073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh if ((port & 1) == 0) { 6173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh env->SetIntField(thiz, gNative, socket); 6273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh return port; 6373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } 6473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh ::close(socket); 6573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 6673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh socket = ::socket(ss.ss_family, SOCK_DGRAM, 0); 6773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh if (socket != -1) { 6873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh uint16_t delta = port << 1; 6973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh ++port; 7073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 7173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh for (int i = 0; i < 1000; ++i) { 7273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh do { 7373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh port += delta; 7473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } while (port < 1024); 7573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh *p = htons(port); 7673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 7773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh if (bind(socket, (sockaddr *)&ss, sizeof(ss)) == 0) { 7873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh env->SetIntField(thiz, gNative, socket); 7973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh return port; 8073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } 8173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } 8273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } 8373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 8473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh jniThrowException(env, "java/net/SocketException", strerror(errno)); 8573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh ::close(socket); 8673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh return -1; 8773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh} 8873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 8973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yehjint dup(JNIEnv *env, jobject thiz) 9073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh{ 91d85beac45c12a65076a1c157681de9a5b03bdec7Chia-chi Yeh int socket = ::dup(env->GetIntField(thiz, gNative)); 92d85beac45c12a65076a1c157681de9a5b03bdec7Chia-chi Yeh if (socket == -1) { 9373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh jniThrowException(env, "java/lang/IllegalStateException", strerror(errno)); 9473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } 95d85beac45c12a65076a1c157681de9a5b03bdec7Chia-chi Yeh return socket; 9673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh} 9773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 9873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yehvoid close(JNIEnv *env, jobject thiz) 9973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh{ 10073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh int socket = env->GetIntField(thiz, gNative); 10173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh ::close(socket); 10273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh env->SetIntField(thiz, gNative, -1); 10373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh} 10473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 10573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi YehJNINativeMethod gMethods[] = { 10673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh {"create", "(Ljava/lang/String;)I", (void *)create}, 10773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh {"dup", "()I", (void *)dup}, 10873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh {"close", "()V", (void *)close}, 10973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh}; 11073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 11173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh} // namespace 11273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 11373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yehint registerRtpStream(JNIEnv *env) 11473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh{ 11573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh jclass clazz; 11673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh if ((clazz = env->FindClass("android/net/rtp/RtpStream")) == NULL || 11773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh (gNative = env->GetFieldID(clazz, "mNative", "I")) == NULL || 11873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh env->RegisterNatives(clazz, gMethods, NELEM(gMethods)) < 0) { 1198913af783fc2cf197ef55449792bb8416a356263Steve Block ALOGE("JNI registration failed"); 12073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh return -1; 12173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } 12273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh return 0; 12373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh} 124