Browse Source

add jni functions

Max Lv 11 years ago
parent
commit
8a8ff6b081
3 changed files with 127 additions and 0 deletions
  1. 102
      src/android.cpp
  2. 9
      src/android.h
  3. 16
      src/local.c

102
src/android.cpp

@ -0,0 +1,102 @@
#define LOG_TAG "Shadowsocks"
#include "android.h"
#include <android/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cpu-features.h>
#define LOGI(...) do { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); } while(0)
#define LOGW(...) do { __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); } while(0)
#define LOGE(...) do { __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); } while(0)
/*
* This is called by the VM when the shared library is first loaded.
*/
typedef union {
JNIEnv* env;
void* venv;
} UnionJNIEnvToVoid;
static UnionJNIEnvToVoid uenv;
static jmethodID newProtectedSocketMethod = NULL;
static jmethodID freeProtectedSocketMethod = NULL;
static jclass clazz = NULL;
static const char *classPathName = "com/github/shadowsocks/Socket";
/*
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className)
{
if (clazz == NULL)
{
clazz = env->FindClass(className);
}
if (clazz == NULL)
{
LOGE("Native registration unable to find class '%s'", className);
return JNI_FALSE;
}
newProtectedSocketMethod = env->GetStaticMethodID(clazz, "newProtectedSocket", "()I");
if (newProtectedSocketMethod < 0)
{
LOGE("RegisterNatives failed for newProtectedSocketMethod");
return JNI_FALSE;
}
freeProtectedSocketMethod = env->GetStaticMethodID(clazz, "freeProtectedSocket", "(I)V");
if (freeProtectedSocketMethod < 0)
{
LOGE("RegisterNatives failed for freeProtectedSocketMethod");
return JNI_FALSE;
}
return JNI_TRUE;
}
jint new_protected_socket()
{
if (newProtectedSocketMethod != NULL)
{
JNIEnv* env = uenv.env;
return (*env)->CallStaticIntMethod(env, SocketCls, newProtectedSocketMethod);
}
return -1;
}
void free_protected_socket(jint fd)
{
if (newProtectedSocketMethod != NULL)
{
JNIEnv* env = uenv.env;
(*env)->CallStaticVoidMethod(env, SocketCls, freeProtectedSocketMethod, fd);
}
}
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
uenv.venv = NULL;
jint result = -1;
JNIEnv* env = NULL;
LOGI("JNI_OnLoad");
if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed");
goto bail;
}
env = uenv.env;
if (registerNativeMethods(env, classPathName) != JNI_TRUE) {
LOGE("ERROR: registerNatives failed");
goto bail;
}
result = JNI_VERSION_1_4;
bail:
return result;
}

9
src/android.h

@ -0,0 +1,9 @@
#ifndef _JNI_H
#define _JNI_H
#include <jni.h>
jint new_protected_socket();
void free_protected_socket(jint fd);
#endif // _JNI_H

16
src/local.c

@ -8,6 +8,10 @@
#include <unistd.h>
#include <getopt.h>
#ifdef ANDROID
#include "android.h"
#endif
#ifndef __MINGW32__
#include <errno.h>
#include <arpa/inet.h>
@ -757,7 +761,11 @@ static void close_and_free_remote(EV_P_ struct remote *remote)
ev_timer_stop(EV_A_ &remote->send_ctx->watcher);
ev_io_stop(EV_A_ &remote->send_ctx->io);
ev_io_stop(EV_A_ &remote->recv_ctx->io);
#ifdef ANDROID
free_protect_fd(remote->fd);
#else
close(remote->fd);
#endif
free_remote(remote);
}
}
@ -868,8 +876,16 @@ static struct remote* connect_to_remote(struct listen_ctx *listener,
return NULL;
}
#ifdef ANDROID
sockfd = new_protect_socket();
#else
sockfd = socket(remote_res->ai_family, remote_res->ai_socktype,
remote_res->ai_protocol);
#endif
if (sockfd < 0)
{
ERROR("socket");

Loading…
Cancel
Save