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 362bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi YehjfieldID gSocket; 3773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 3873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yehjint create(JNIEnv *env, jobject thiz, jstring jAddress) 3973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh{ 402bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh env->SetIntField(thiz, gSocket, -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) { 612bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh env->SetIntField(thiz, gSocket, 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) { 782bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh env->SetIntField(thiz, gSocket, 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 Yehvoid close(JNIEnv *env, jobject thiz) 9073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh{ 912bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh int socket = env->GetIntField(thiz, gSocket); 9273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh ::close(socket); 932bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh env->SetIntField(thiz, gSocket, -1); 9473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh} 9573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 9673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi YehJNINativeMethod gMethods[] = { 9773f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh {"create", "(Ljava/lang/String;)I", (void *)create}, 9873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh {"close", "()V", (void *)close}, 9973f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh}; 10073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 10173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh} // namespace 10273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh 10373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yehint registerRtpStream(JNIEnv *env) 10473f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh{ 10573f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh jclass clazz; 10673f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh if ((clazz = env->FindClass("android/net/rtp/RtpStream")) == NULL || 1072bf2e642d061e7b48dd71927752e9151a5126fb2Chia-chi Yeh (gSocket = env->GetFieldID(clazz, "mSocket", "I")) == NULL || 10873f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh env->RegisterNatives(clazz, gMethods, NELEM(gMethods)) < 0) { 1098913af783fc2cf197ef55449792bb8416a356263Steve Block ALOGE("JNI registration failed"); 11073f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh return -1; 11173f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh } 11273f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh return 0; 11373f6df1f0aac12c243e2110e30337ab01aa71598Chia-chi Yeh} 114