/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define LOG_TAG "RtpStream"
#include <utils/Log.h>

#include "jni.h"
#include <nativehelper/JNIHelp.h>

extern int parse(JNIEnv *env, jstring jAddress, int port, sockaddr_storage *ss);

namespace {

jfieldID gSocket;

jint create(JNIEnv *env, jobject thiz, jstring jAddress)
{
    env->SetIntField(thiz, gSocket, -1);

    sockaddr_storage ss;
    if (parse(env, jAddress, 0, &ss) < 0) {
        // Exception already thrown.
        return -1;
    }

    int socket = ::socket(ss.ss_family, SOCK_DGRAM, 0);
    socklen_t len = sizeof(ss);
    if (socket == -1 || bind(socket, (sockaddr *)&ss, sizeof(ss)) != 0 ||
        getsockname(socket, (sockaddr *)&ss, &len) != 0) {
        jniThrowException(env, "java/net/SocketException", strerror(errno));
        ::close(socket);
        return -1;
    }

    uint16_t *p = (ss.ss_family == AF_INET) ?
        &((sockaddr_in *)&ss)->sin_port : &((sockaddr_in6 *)&ss)->sin6_port;
    uint16_t port = ntohs(*p);
    if ((port & 1) == 0) {
        env->SetIntField(thiz, gSocket, socket);
        return port;
    }
    ::close(socket);

    socket = ::socket(ss.ss_family, SOCK_DGRAM, 0);
    if (socket != -1) {
        uint16_t delta = port << 1;
        ++port;

        for (int i = 0; i < 1000; ++i) {
            do {
                port += delta;
            } while (port < 1024);
            *p = htons(port);

            if (bind(socket, (sockaddr *)&ss, sizeof(ss)) == 0) {
                env->SetIntField(thiz, gSocket, socket);
                return port;
            }
        }
    }

    jniThrowException(env, "java/net/SocketException", strerror(errno));
    ::close(socket);
    return -1;
}

void close(JNIEnv *env, jobject thiz)
{
    int socket = env->GetIntField(thiz, gSocket);
    ::close(socket);
    env->SetIntField(thiz, gSocket, -1);
}

JNINativeMethod gMethods[] = {
    {"create", "(Ljava/lang/String;)I", (void *)create},
    {"close", "()V", (void *)close},
};

} // namespace

int registerRtpStream(JNIEnv *env)
{
    jclass clazz;
    if ((clazz = env->FindClass("android/net/rtp/RtpStream")) == NULL ||
        (gSocket = env->GetFieldID(clazz, "mSocket", "I")) == NULL ||
        env->RegisterNatives(clazz, gMethods, NELEM(gMethods)) < 0) {
        ALOGE("JNI registration failed");
        return -1;
    }
    return 0;
}
