R4SAS
3 months ago
24 changed files with 686 additions and 450 deletions
@ -0,0 +1,80 @@ |
|||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := i2pd |
||||||
|
LOCAL_CPP_FEATURES := rtti exceptions |
||||||
|
LOCAL_C_INCLUDES += $(IFADDRS_PATH) $(LIB_SRC_PATH) $(LIB_CLIENT_SRC_PATH) $(LANG_SRC_PATH) $(DAEMON_SRC_PATH) |
||||||
|
LOCAL_STATIC_LIBRARIES := \
|
||||||
|
boost_system \
|
||||||
|
boost_date_time \
|
||||||
|
boost_filesystem \
|
||||||
|
boost_program_options \
|
||||||
|
crypto \
|
||||||
|
ssl \
|
||||||
|
miniupnpc |
||||||
|
LOCAL_LDLIBS := -lz |
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
DaemonAndroid.cpp \
|
||||||
|
i2pd_android.cpp \
|
||||||
|
$(IFADDRS_PATH)/ifaddrs.cpp \
|
||||||
|
$(IFADDRS_PATH)/bionic_netlink.cpp \
|
||||||
|
$(wildcard $(LIB_SRC_PATH)/*.cpp) \
|
||||||
|
$(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp) \
|
||||||
|
$(wildcard $(LANG_SRC_PATH)/*.cpp) \
|
||||||
|
$(DAEMON_SRC_PATH)/Daemon.cpp \
|
||||||
|
$(DAEMON_SRC_PATH)/UPnP.cpp \
|
||||||
|
$(DAEMON_SRC_PATH)/HTTPServer.cpp \
|
||||||
|
$(DAEMON_SRC_PATH)/I2PControl.cpp \
|
||||||
|
$(DAEMON_SRC_PATH)/I2PControlHandlers.cpp |
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := boost_system |
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/lib/libboost_system.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := boost_date_time |
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := boost_filesystem |
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := boost_program_options |
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := crypto |
||||||
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/out/$(TARGET_ARCH_ABI)/lib/libcrypto.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/out/$(TARGET_ARCH_ABI)/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := ssl |
||||||
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/out/$(TARGET_ARCH_ABI)/lib/libssl.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/out/$(TARGET_ARCH_ABI)/include |
||||||
|
LOCAL_STATIC_LIBRARIES := crypto |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := miniupnpc |
||||||
|
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc/out/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc/out/$(TARGET_ARCH_ABI)/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
@ -0,0 +1,23 @@ |
|||||||
|
NDK_TOOLCHAIN_VERSION := clang |
||||||
|
APP_STL := c++_static |
||||||
|
|
||||||
|
# Enable c++17 extensions in source code
|
||||||
|
APP_CPPFLAGS += -std=c++17 -fexceptions -frtti |
||||||
|
|
||||||
|
APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP -Wno-deprecated-declarations |
||||||
|
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) |
||||||
|
APP_CPPFLAGS += -DANDROID_ARM7A |
||||||
|
endif |
||||||
|
|
||||||
|
IFADDRS_PATH = $(NDK_MODULE_PATH)/android-ifaddrs |
||||||
|
BOOST_PATH = $(NDK_MODULE_PATH)/boost |
||||||
|
MINIUPNP_PATH = $(NDK_MODULE_PATH)/miniupnp |
||||||
|
OPENSSL_PATH = $(NDK_MODULE_PATH)/openssl |
||||||
|
|
||||||
|
# don't change me
|
||||||
|
I2PD_SRC_PATH = $(NDK_MODULE_PATH)/i2pd |
||||||
|
|
||||||
|
LIB_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd |
||||||
|
LIB_CLIENT_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd_client |
||||||
|
LANG_SRC_PATH = $(I2PD_SRC_PATH)/i18n |
||||||
|
DAEMON_SRC_PATH = $(I2PD_SRC_PATH)/daemon |
@ -0,0 +1,138 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2022, The PurpleI2P Project |
||||||
|
* |
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3 |
||||||
|
* |
||||||
|
* See full license text in LICENSE file at top of project tree |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <iostream> |
||||||
|
#include <chrono> |
||||||
|
#include <thread> |
||||||
|
#include <exception> |
||||||
|
#include <boost/exception/diagnostic_information.hpp> |
||||||
|
#include <boost/exception_ptr.hpp> |
||||||
|
//#include "mainwindow.h"
|
||||||
|
#include "FS.h" |
||||||
|
#include "DaemonAndroid.h" |
||||||
|
#include "Daemon.h" |
||||||
|
#include "I18N.h" |
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace android |
||||||
|
{ |
||||||
|
std::string dataDir = ""; |
||||||
|
std::string language = ""; |
||||||
|
|
||||||
|
DaemonAndroidImpl::DaemonAndroidImpl () |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
DaemonAndroidImpl::~DaemonAndroidImpl () |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
bool DaemonAndroidImpl::init(int argc, char* argv[]) |
||||||
|
{ |
||||||
|
return Daemon.init(argc, argv); |
||||||
|
} |
||||||
|
|
||||||
|
void DaemonAndroidImpl::start() |
||||||
|
{ |
||||||
|
Daemon.start(); |
||||||
|
} |
||||||
|
|
||||||
|
void DaemonAndroidImpl::stop() |
||||||
|
{ |
||||||
|
Daemon.stop(); |
||||||
|
} |
||||||
|
|
||||||
|
void DaemonAndroidImpl::restart() |
||||||
|
{ |
||||||
|
stop(); |
||||||
|
start(); |
||||||
|
} |
||||||
|
|
||||||
|
void DaemonAndroidImpl::setDataDir(std::string path) |
||||||
|
{ |
||||||
|
Daemon.setDataDir(path); |
||||||
|
} |
||||||
|
|
||||||
|
static DaemonAndroidImpl daemon; |
||||||
|
static char* argv[1]={strdup("tmp")}; |
||||||
|
/**
|
||||||
|
* returns error details if failed |
||||||
|
* returns "ok" if daemon initialized and started okay |
||||||
|
*/ |
||||||
|
std::string start(/*int argc, char* argv[]*/) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
{ |
||||||
|
// make sure assets are ready before proceed
|
||||||
|
i2p::fs::DetectDataDir(dataDir, false); |
||||||
|
int numAttempts = 0; |
||||||
|
do |
||||||
|
{ |
||||||
|
if (i2p::fs::Exists (i2p::fs::DataDirPath("assets.ready"))) break; // assets ready
|
||||||
|
numAttempts++; |
||||||
|
std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second
|
||||||
|
} |
||||||
|
while (numAttempts <= 10); // 10 seconds max
|
||||||
|
|
||||||
|
// Set application directory
|
||||||
|
daemon.setDataDir(dataDir); |
||||||
|
|
||||||
|
bool daemonInitSuccess = daemon.init(1, argv); |
||||||
|
if(!daemonInitSuccess) |
||||||
|
{ |
||||||
|
return "Daemon init failed"; |
||||||
|
} |
||||||
|
|
||||||
|
// Set webconsole language from application
|
||||||
|
i2p::i18n::SetLanguage(language); |
||||||
|
|
||||||
|
daemon.start(); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (boost::exception& ex) |
||||||
|
{ |
||||||
|
std::stringstream ss; |
||||||
|
ss << boost::diagnostic_information(ex); |
||||||
|
return ss.str(); |
||||||
|
} |
||||||
|
catch (std::exception& ex) |
||||||
|
{ |
||||||
|
std::stringstream ss; |
||||||
|
ss << ex.what(); |
||||||
|
return ss.str(); |
||||||
|
} |
||||||
|
catch(...) |
||||||
|
{ |
||||||
|
return "unknown exception"; |
||||||
|
} |
||||||
|
return "ok"; |
||||||
|
} |
||||||
|
|
||||||
|
void stop() |
||||||
|
{ |
||||||
|
daemon.stop(); |
||||||
|
} |
||||||
|
|
||||||
|
void SetDataDir(std::string jdataDir) |
||||||
|
{ |
||||||
|
dataDir = jdataDir; |
||||||
|
} |
||||||
|
|
||||||
|
std::string GetDataDir(void) |
||||||
|
{ |
||||||
|
return dataDir; |
||||||
|
} |
||||||
|
|
||||||
|
void SetLanguage(std::string jlanguage) |
||||||
|
{ |
||||||
|
language = jlanguage; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2022, The PurpleI2P Project |
||||||
|
* |
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3 |
||||||
|
* |
||||||
|
* See full license text in LICENSE file at top of project tree |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef DAEMON_ANDROID_H |
||||||
|
#define DAEMON_ANDROID_H |
||||||
|
|
||||||
|
#include <string> |
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace android |
||||||
|
{ |
||||||
|
class DaemonAndroidImpl |
||||||
|
{ |
||||||
|
public: |
||||||
|
|
||||||
|
DaemonAndroidImpl (); |
||||||
|
~DaemonAndroidImpl (); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @return success |
||||||
|
*/ |
||||||
|
bool init (int argc, char* argv[]); |
||||||
|
void start (); |
||||||
|
void stop (); |
||||||
|
void restart (); |
||||||
|
|
||||||
|
void setDataDir (std::string path); |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* returns "ok" if daemon init failed |
||||||
|
* returns errinfo if daemon initialized and started okay |
||||||
|
*/ |
||||||
|
std::string start (); |
||||||
|
|
||||||
|
void stop (); |
||||||
|
|
||||||
|
// set datadir received from jni
|
||||||
|
void SetDataDir (std::string jdataDir); |
||||||
|
// get datadir
|
||||||
|
std::string GetDataDir (void); |
||||||
|
// set webconsole language
|
||||||
|
void SetLanguage (std::string jlanguage); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif // DAEMON_ANDROID_H
|
@ -0,0 +1,141 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2022, The PurpleI2P Project |
||||||
|
* |
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3 |
||||||
|
* |
||||||
|
* See full license text in LICENSE file at top of project tree |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <jni.h> |
||||||
|
#include "org_purplei2p_i2pd_I2PD_JNI.h" |
||||||
|
#include "DaemonAndroid.h" |
||||||
|
#include "Config.h" |
||||||
|
#include "RouterContext.h" |
||||||
|
#include "ClientContext.h" |
||||||
|
#include "Transports.h" |
||||||
|
#include "Tunnel.h" |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith |
||||||
|
(JNIEnv *env, jclass clazz) { |
||||||
|
#if defined(__arm__) |
||||||
|
#if defined(__ARM_ARCH_7A__) |
||||||
|
#if defined(__ARM_NEON__) |
||||||
|
#if defined(__ARM_PCS_VFP) |
||||||
|
#define ABI "armeabi-v7a/NEON (hard-float)" |
||||||
|
#else |
||||||
|
#define ABI "armeabi-v7a/NEON" |
||||||
|
#endif |
||||||
|
#else |
||||||
|
#if defined(__ARM_PCS_VFP) |
||||||
|
#define ABI "armeabi-v7a (hard-float)" |
||||||
|
#else |
||||||
|
#define ABI "armeabi-v7a" |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
#else |
||||||
|
#define ABI "armeabi" |
||||||
|
#endif |
||||||
|
#elif defined(__i386__) |
||||||
|
#define ABI "x86" |
||||||
|
#elif defined(__x86_64__) |
||||||
|
#define ABI "x86_64" |
||||||
|
#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */ |
||||||
|
#define ABI "mips64" |
||||||
|
#elif defined(__mips__) |
||||||
|
#define ABI "mips" |
||||||
|
#elif defined(__aarch64__) |
||||||
|
#define ABI "arm64-v8a" |
||||||
|
#else |
||||||
|
#define ABI "unknown" |
||||||
|
#endif |
||||||
|
|
||||||
|
return env->NewStringUTF(ABI); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon |
||||||
|
(JNIEnv *env, jclass clazz) { |
||||||
|
return env->NewStringUTF(i2p::android::start().c_str()); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getDataDir |
||||||
|
(JNIEnv *env, jclass clazz) { |
||||||
|
return env->NewStringUTF(i2p::android::GetDataDir().c_str()); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon |
||||||
|
(JNIEnv *env, jclass clazz) { |
||||||
|
i2p::android::stop(); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels |
||||||
|
(JNIEnv *env, jclass clazz) { |
||||||
|
i2p::context.SetAcceptsTunnels (false); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels |
||||||
|
(JNIEnv *env, jclass clazz) { |
||||||
|
i2p::context.SetAcceptsTunnels (true); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_reloadTunnelsConfigs |
||||||
|
(JNIEnv *env, jclass clazz) { |
||||||
|
i2p::client::context.ReloadConfig(); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged |
||||||
|
(JNIEnv *env, jclass clazz, jboolean isConnected) { |
||||||
|
bool isConnectedBool = (bool) isConnected; |
||||||
|
i2p::transport::transports.SetOnline (isConnectedBool); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir |
||||||
|
(JNIEnv *env, jclass clazz, jstring jdataDir) { |
||||||
|
auto dataDir = env->GetStringUTFChars(jdataDir, NULL); |
||||||
|
i2p::android::SetDataDir(dataDir); |
||||||
|
env->ReleaseStringUTFChars(jdataDir, dataDir); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getTransitTunnelsCount |
||||||
|
(JNIEnv *env, jclass clazz) { |
||||||
|
return i2p::tunnel::tunnels.CountTransitTunnels(); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getWebConsAddr |
||||||
|
(JNIEnv *env, jclass clazz) { |
||||||
|
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); |
||||||
|
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); |
||||||
|
std::string result = "http://" + httpAddr + ":" + std::to_string(httpPort) + "/"; |
||||||
|
return env->NewStringUTF(result.c_str()); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setLanguage |
||||||
|
(JNIEnv *env, jclass clazz, jstring jlanguage) { |
||||||
|
auto language = env->GetStringUTFChars(jlanguage, NULL); |
||||||
|
i2p::android::SetLanguage(language); |
||||||
|
env->ReleaseStringUTFChars(jlanguage, language); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getHTTPProxyState |
||||||
|
(JNIEnv *, jclass) { |
||||||
|
return i2p::client::context.GetHttpProxy () ? true : false; |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getSOCKSProxyState |
||||||
|
(JNIEnv *, jclass) { |
||||||
|
return i2p::client::context.GetSocksProxy() ? true : false; |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getBOBState |
||||||
|
(JNIEnv *, jclass) { |
||||||
|
return i2p::client::context.GetBOBCommandChannel() ? true : false; |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getSAMState |
||||||
|
(JNIEnv *, jclass) { |
||||||
|
return i2p::client::context.GetSAMBridge() ? true : false; |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getI2CPState |
||||||
|
(JNIEnv *, jclass) { |
||||||
|
return i2p::client::context.GetI2CPServer() ? true : false; |
||||||
|
} |
@ -0,0 +1,73 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2022, The PurpleI2P Project |
||||||
|
* |
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3 |
||||||
|
* |
||||||
|
* See full license text in LICENSE file at top of project tree |
||||||
|
*/ |
||||||
|
|
||||||
|
/* DO NOT EDIT THIS FILE - it is machine generated */ |
||||||
|
#include <jni.h> |
||||||
|
/* Header for class org_purplei2p_i2pd_I2PD_JNI */ |
||||||
|
|
||||||
|
#ifndef _Included_org_purplei2p_i2pd_I2PD_JNI |
||||||
|
#define _Included_org_purplei2p_i2pd_I2PD_JNI |
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_reloadTunnelsConfigs |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir |
||||||
|
(JNIEnv *env, jclass clazz, jstring jdataDir); |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setLanguage |
||||||
|
(JNIEnv *env, jclass clazz, jstring jlanguage); |
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getTransitTunnelsCount |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getWebConsAddr |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getDataDir |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getHTTPProxyState |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getSOCKSProxyState |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getBOBState |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getSAMState |
||||||
|
(JNIEnv *, jclass) ; |
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getI2CPState |
||||||
|
(JNIEnv *, jclass); |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged |
||||||
|
(JNIEnv * env, jclass clazz, jboolean isConnected); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
||||||
|
#endif |
@ -1,7 +0,0 @@ |
|||||||
package org.purplei2p.i2pd; |
|
||||||
|
|
||||||
public interface AbstractProcess { |
|
||||||
/** @param tr can be null |
|
||||||
*/ |
|
||||||
void kill(Throwable tr); |
|
||||||
} |
|
@ -0,0 +1,35 @@ |
|||||||
|
package org.purplei2p.i2pd; |
||||||
|
|
||||||
|
public class I2PD_JNI { |
||||||
|
public static native String getABICompiledWith(); |
||||||
|
|
||||||
|
public static void loadLibraries() { |
||||||
|
System.loadLibrary("i2pd"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* returns error info if failed |
||||||
|
* returns "ok" if daemon initialized and started okay |
||||||
|
*/ |
||||||
|
public static native String startDaemon(); |
||||||
|
public static native void stopDaemon(); |
||||||
|
|
||||||
|
public static native void startAcceptingTunnels(); |
||||||
|
public static native void stopAcceptingTunnels(); |
||||||
|
public static native void reloadTunnelsConfigs(); |
||||||
|
|
||||||
|
public static native void setDataDir(String jdataDir); |
||||||
|
public static native void setLanguage(String jlanguage); |
||||||
|
|
||||||
|
public static native int getTransitTunnelsCount(); |
||||||
|
public static native String getWebConsAddr(); |
||||||
|
public static native String getDataDir(); |
||||||
|
|
||||||
|
public static native boolean getHTTPProxyState(); |
||||||
|
public static native boolean getSOCKSProxyState(); |
||||||
|
public static native boolean getBOBState(); |
||||||
|
public static native boolean getSAMState(); |
||||||
|
public static native boolean getI2CPState(); |
||||||
|
|
||||||
|
public static native void onNetworkStateChanged(boolean isConnected); |
||||||
|
} |
@ -1,154 +0,0 @@ |
|||||||
package org.purplei2p.i2pd; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.util.Log; |
|
||||||
|
|
||||||
import java.io.BufferedInputStream; |
|
||||||
import java.io.BufferedReader; |
|
||||||
import java.io.File; |
|
||||||
import java.io.InputStreamReader; |
|
||||||
|
|
||||||
/** i2pd process API calls via TCP between the Android Java app and i2pd C++-only process. |
|
||||||
* TODO |
|
||||||
*/ |
|
||||||
public class I2pdApi { |
|
||||||
private static String dataDir; |
|
||||||
private static AbstractProcess i2pdProcess; |
|
||||||
private static final String TAG = "I2pdApi"; |
|
||||||
|
|
||||||
/** |
|
||||||
* returns error info if failed |
|
||||||
* returns "ok" if daemon initialized and started okay |
|
||||||
*/ |
|
||||||
public static String startDaemon(final Context ctx, final String dataDir, String ignoredLanguage, final DaemonWrapper daemonWrapper){ |
|
||||||
try { |
|
||||||
i2pdProcess = null; |
|
||||||
I2pdApi.dataDir = dataDir; |
|
||||||
File pidFile = new File(dataDir, "i2pd.pid"); |
|
||||||
Log.i(TAG,"Launching an i2pd process"); |
|
||||||
final Process p = Runtime.getRuntime().exec(new String[]{ |
|
||||||
"/system/bin/sh", |
|
||||||
"-c", |
|
||||||
"ulimit -c unlimited && "+ |
|
||||||
ctx.getApplicationInfo().nativeLibraryDir + |
|
||||||
"/libi2pd.so --datadir=" + dataDir + |
|
||||||
" --pidfile=" + pidFile.getAbsolutePath() + |
|
||||||
" > "+dataDir+"/s.log 2>&1" |
|
||||||
}); |
|
||||||
i2pdProcess = (Throwable tr) -> { |
|
||||||
try { |
|
||||||
if (tr != null) |
|
||||||
Log.e(TAG, "destroying the subprocess \"i2pd\", reason: " + tr, tr); |
|
||||||
else |
|
||||||
Log.e(TAG, "destroying the subprocess \"i2pd\", reason: null"); |
|
||||||
p.destroy(); |
|
||||||
} catch (Throwable tr2) { |
|
||||||
Log.e(TAG, "", tr2); |
|
||||||
} |
|
||||||
}; |
|
||||||
new Thread(() -> { |
|
||||||
try { |
|
||||||
try (BufferedInputStream bis = new BufferedInputStream(p.getInputStream())) { |
|
||||||
try (InputStreamReader sr = new InputStreamReader(bis)) { |
|
||||||
try (BufferedReader r = new BufferedReader(sr)) { |
|
||||||
while (true) { |
|
||||||
String s = r.readLine(); |
|
||||||
if (s == null) break; |
|
||||||
Log.i(TAG, s); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} catch (Throwable tr) { |
|
||||||
Log.e(TAG, "", tr); |
|
||||||
} |
|
||||||
}, "i2pd-stdout").start(); |
|
||||||
new Thread(() -> { |
|
||||||
try { |
|
||||||
try (BufferedInputStream bis = new BufferedInputStream(p.getErrorStream())) { |
|
||||||
try (InputStreamReader sr = new InputStreamReader(bis)) { |
|
||||||
try (BufferedReader r = new BufferedReader(sr)) { |
|
||||||
while (true) { |
|
||||||
String s = r.readLine(); |
|
||||||
if (s == null) break; |
|
||||||
Log.i(TAG, s); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} catch (Throwable tr) { |
|
||||||
Log.e(TAG, "", tr); |
|
||||||
} |
|
||||||
try { |
|
||||||
p.waitFor(); |
|
||||||
} catch (Throwable tr) { |
|
||||||
Log.e(TAG, "", tr); |
|
||||||
} |
|
||||||
final int errorLevel = p.exitValue(); |
|
||||||
Log.i(TAG, "i2pd process exit code: " + errorLevel); |
|
||||||
final Throwable trReason = new Throwable("subprocess \"i2pd\" exited with exit code " + errorLevel); |
|
||||||
try { |
|
||||||
stopDaemon(trReason); |
|
||||||
Log.i(TAG, "stopDaemon completed"); |
|
||||||
} catch (Throwable tr) { |
|
||||||
Log.e(TAG, "Called stopDaemon, got exception", tr); |
|
||||||
} |
|
||||||
new Thread(() -> { |
|
||||||
try { |
|
||||||
daemonWrapper.stopDaemon(trReason); |
|
||||||
Log.i(TAG, "daemonWrapper.stopDaemon completed"); |
|
||||||
} catch (Throwable tr) { |
|
||||||
Log.e(TAG, "Called daemonWrapper.stopDaemon, got exception", tr); |
|
||||||
} |
|
||||||
}, "stop the daemonWrapper thread").start(); |
|
||||||
}, "i2pd-stderr").start(); |
|
||||||
new Thread(() -> { |
|
||||||
try { |
|
||||||
// try (BufferedOutputStream bos = new BufferedOutputStream(p.getOutputStream())) {
|
|
||||||
// try (OutputStreamWriter sr = new OutputStreamWriter(bos)) {
|
|
||||||
// try (BufferedWriter r = new BufferedWriter(sr)) {
|
|
||||||
while (true) { |
|
||||||
synchronized (Thread.currentThread()) { |
|
||||||
Thread.currentThread().wait(100); |
|
||||||
} |
|
||||||
} |
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
} catch (Throwable tr) { |
|
||||||
Log.e(TAG, "", tr); |
|
||||||
} |
|
||||||
}, "i2pd-stdin").start(); |
|
||||||
return "ok"; |
|
||||||
} catch (Throwable tr) { |
|
||||||
Log.e(TAG, "", tr); |
|
||||||
return "Error in exec(): " + tr; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void stopDaemon(Throwable tr){ |
|
||||||
AbstractProcess p = i2pdProcess; |
|
||||||
if (p != null) { |
|
||||||
p.kill(tr); |
|
||||||
i2pdProcess = null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void startAcceptingTunnels(){} |
|
||||||
public static void stopAcceptingTunnels(){} |
|
||||||
public static void reloadTunnelsConfigs(){} |
|
||||||
|
|
||||||
public static int getTransitTunnelsCount(){return -1;} |
|
||||||
public static String getWebConsAddr(){return "";} |
|
||||||
public static String getDataDir() { |
|
||||||
return dataDir; |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean getHTTPProxyState(){return false;} |
|
||||||
public static boolean getSOCKSProxyState(){return false;} |
|
||||||
public static boolean getBOBState(){return false;} |
|
||||||
public static boolean getSAMState(){return false;} |
|
||||||
public static boolean getI2CPState(){return false;} |
|
||||||
|
|
||||||
public static void onNetworkStateChanged(boolean isConnected){} |
|
||||||
} |
|
@ -1,126 +0,0 @@ |
|||||||
package org.purplei2p.i2pd.appscope; |
|
||||||
|
|
||||||
import android.app.Application; |
|
||||||
import android.content.ComponentName; |
|
||||||
import android.content.Context; |
|
||||||
import android.content.Intent; |
|
||||||
import android.content.ServiceConnection; |
|
||||||
import android.net.ConnectivityManager; |
|
||||||
import android.os.IBinder; |
|
||||||
import android.util.Log; |
|
||||||
|
|
||||||
import org.purplei2p.i2pd.BuildConfig; |
|
||||||
import org.purplei2p.i2pd.I2PDActivity; |
|
||||||
import org.purplei2p.i2pd.*; |
|
||||||
|
|
||||||
public class App extends Application { |
|
||||||
private static final String TAG = "i2pd.app"; |
|
||||||
|
|
||||||
//private static final I2PD_JNI jniHolder = new I2PD_JNI();
|
|
||||||
|
|
||||||
private static volatile DaemonWrapper daemonWrapper; |
|
||||||
private String versionName; |
|
||||||
|
|
||||||
private static volatile boolean mIsBound; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized static DaemonWrapper getDaemonWrapper() { |
|
||||||
return daemonWrapper; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onCreate() { |
|
||||||
super.onCreate(); |
|
||||||
synchronized (this) { |
|
||||||
if (getDaemonWrapper() == null) { |
|
||||||
createDaemonWrapper(); |
|
||||||
} |
|
||||||
versionName = BuildConfig.VERSION_NAME; |
|
||||||
doBindService(); |
|
||||||
startService(new Intent(this, ForegroundService.class)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void createDaemonWrapper() { |
|
||||||
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService( |
|
||||||
Context.CONNECTIVITY_SERVICE); |
|
||||||
daemonWrapper = new DaemonWrapper(getApplicationContext(), getAssets(), connectivityManager); |
|
||||||
ForegroundService.init(daemonWrapper); |
|
||||||
} |
|
||||||
|
|
||||||
private synchronized void doBindService() { |
|
||||||
if (mIsBound) |
|
||||||
return; |
|
||||||
// Establish a connection with the service. We use an explicit
|
|
||||||
// class name because we want a specific service implementation that
|
|
||||||
// we know will be running in our own process (and thus won't be
|
|
||||||
// supporting component replacement by other applications).
|
|
||||||
bindService(new Intent(this, ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE); |
|
||||||
mIsBound = true; |
|
||||||
} |
|
||||||
|
|
||||||
private synchronized void doUnbindService() { |
|
||||||
if (mIsBound) { |
|
||||||
// Detach our existing connection.
|
|
||||||
unbindService(mConnection); |
|
||||||
mIsBound = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTerminate() { |
|
||||||
quit(); |
|
||||||
super.onTerminate(); |
|
||||||
} |
|
||||||
|
|
||||||
private final ServiceConnection mConnection = new ServiceConnection() { |
|
||||||
public void onServiceConnected(ComponentName className, IBinder service) { |
|
||||||
/* This is called when the connection with the service has been |
|
||||||
established, giving us the service object we can use to |
|
||||||
interact with the service. Because we have bound to a explicit |
|
||||||
service that we know is running in our own process, we can |
|
||||||
cast its IBinder to a concrete class and directly access it. */ |
|
||||||
// mBoundService = ((LocalService.LocalBinder)service).getService();
|
|
||||||
|
|
||||||
/* Tell the user about this for our demo. */ |
|
||||||
// Toast.makeText(Binding.this, R.string.local_service_connected,
|
|
||||||
// Toast.LENGTH_SHORT).show();
|
|
||||||
} |
|
||||||
|
|
||||||
public void onServiceDisconnected(ComponentName className) { |
|
||||||
/* This is called when the connection with the service has been |
|
||||||
unexpectedly disconnected -- that is, its process crashed. |
|
||||||
Because it is running in our same process, we should never |
|
||||||
see this happen. */ |
|
||||||
// mBoundService = null;
|
|
||||||
// Toast.makeText(Binding.this, R.string.local_service_disconnected,
|
|
||||||
// Toast.LENGTH_SHORT).show();
|
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
public synchronized void quit() { |
|
||||||
try { |
|
||||||
if(daemonWrapper!=null)daemonWrapper.stopDaemon(null); |
|
||||||
} catch (Throwable tr) { |
|
||||||
Log.e(TAG, "", tr); |
|
||||||
} |
|
||||||
try { |
|
||||||
doUnbindService(); |
|
||||||
} catch (IllegalArgumentException ex) { |
|
||||||
Log.e(TAG, "throwable caught and ignored", ex); |
|
||||||
if (ex.getMessage().startsWith("Service not registered: " + I2PDActivity.class.getName())) { |
|
||||||
Log.i(TAG, "Service not registered exception seems to be normal, not a bug it seems."); |
|
||||||
} |
|
||||||
} catch (Throwable tr) { |
|
||||||
Log.e(TAG, "throwable caught and ignored", tr); |
|
||||||
} |
|
||||||
try{ |
|
||||||
ForegroundService fs = ForegroundService.getInstance(); |
|
||||||
if(fs!=null)fs.stop(); |
|
||||||
}catch(Throwable tr) { |
|
||||||
Log.e(TAG, "", tr); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue