14c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh/* 24c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * Copyright (C) 2010 The Android Open Source Project 34c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * 44c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 54c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * you may not use this file except in compliance with the License. 64c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * You may obtain a copy of the License at 74c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * 84c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 94c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * 104c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software 114c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 124c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * See the License for the specific language governing permissions and 144c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh * limitations under the License. 154c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh */ 164c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 174c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include <stdio.h> 184c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include <stdint.h> 194c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include <string.h> 204c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include <errno.h> 214c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include <sys/types.h> 224c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include <sys/socket.h> 234c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include <arpa/inet.h> 244c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include <netinet/in.h> 254c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 264c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#define LOG_TAG "RtpStream" 274c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include <utils/Log.h> 284c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 294c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include "jni.h" 304c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh#include "JNIHelp.h" 314c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 324c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yehextern int parse(JNIEnv *env, jstring jAddress, int port, sockaddr_storage *ss); 334c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 344c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yehnamespace { 354c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 36e66950506c473e660f2e5762d7a71e13808be387Chia-chi YehjfieldID gSocket; 374c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 384c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yehjint create(JNIEnv *env, jobject thiz, jstring jAddress) 394c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh{ 40e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh env->SetIntField(thiz, gSocket, -1); 414c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 424c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh sockaddr_storage ss; 434c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh if (parse(env, jAddress, 0, &ss) < 0) { 444c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh // Exception already thrown. 454c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh return -1; 464c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh } 474c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 484c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh int socket = ::socket(ss.ss_family, SOCK_DGRAM, 0); 494c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh socklen_t len = sizeof(ss); 504c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh if (socket == -1 || bind(socket, (sockaddr *)&ss, sizeof(ss)) != 0 || 514c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh getsockname(socket, (sockaddr *)&ss, &len) != 0) { 524c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh jniThrowException(env, "java/net/SocketException", strerror(errno)); 534c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh ::close(socket); 544c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh return -1; 554c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh } 564c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 574c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh uint16_t *p = (ss.ss_family == AF_INET) ? 584c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh &((sockaddr_in *)&ss)->sin_port : &((sockaddr_in6 *)&ss)->sin6_port; 594c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh uint16_t port = ntohs(*p); 604c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh if ((port & 1) == 0) { 61e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh env->SetIntField(thiz, gSocket, socket); 624c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh return port; 634c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh } 644c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh ::close(socket); 654c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 664c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh socket = ::socket(ss.ss_family, SOCK_DGRAM, 0); 674c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh if (socket != -1) { 684c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh uint16_t delta = port << 1; 694c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh ++port; 704c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 714c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh for (int i = 0; i < 1000; ++i) { 724c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh do { 734c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh port += delta; 744c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh } while (port < 1024); 754c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh *p = htons(port); 764c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 774c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh if (bind(socket, (sockaddr *)&ss, sizeof(ss)) == 0) { 78e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh env->SetIntField(thiz, gSocket, socket); 794c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh return port; 804c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh } 814c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh } 824c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh } 834c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 844c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh jniThrowException(env, "java/net/SocketException", strerror(errno)); 854c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh ::close(socket); 864c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh return -1; 874c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh} 884c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 894c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yehvoid close(JNIEnv *env, jobject thiz) 904c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh{ 91e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh int socket = env->GetIntField(thiz, gSocket); 924c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh ::close(socket); 93e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh env->SetIntField(thiz, gSocket, -1); 944c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh} 954c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 964c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi YehJNINativeMethod gMethods[] = { 974c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh {"create", "(Ljava/lang/String;)I", (void *)create}, 984c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh {"close", "()V", (void *)close}, 994c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh}; 1004c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 1014c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh} // namespace 1024c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh 1034c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yehint registerRtpStream(JNIEnv *env) 1044c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh{ 1054c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh jclass clazz; 1064c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh if ((clazz = env->FindClass("android/net/rtp/RtpStream")) == NULL || 107e66950506c473e660f2e5762d7a71e13808be387Chia-chi Yeh (gSocket = env->GetFieldID(clazz, "mSocket", "I")) == NULL || 1084c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh env->RegisterNatives(clazz, gMethods, NELEM(gMethods)) < 0) { 1093762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("JNI registration failed"); 1104c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh return -1; 1114c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh } 1124c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh return 0; 1134c5d28cee0537c83ff0e5bc0daaae78f68dfc7c8Chia-chi Yeh} 114