mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-26 18:53:41 +00:00
add jni functions
This commit is contained in:
+102
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user