From 4371901e705a7477f4cb52638496eb25cc180c1f Mon Sep 17 00:00:00 2001 From: jeff Date: Thu, 3 Oct 2019 09:54:21 -0400 Subject: [PATCH 01/17] flesh out vpn c api clean up cruft --- include/llarp.h | 216 +++++++++++++++++++++++++++++------------------- 1 file changed, 129 insertions(+), 87 deletions(-) diff --git a/include/llarp.h b/include/llarp.h index 24779c17d..c1213d799 100644 --- a/include/llarp.h +++ b/include/llarp.h @@ -1,15 +1,7 @@ #ifndef LLARP_H_ #define LLARP_H_ - +#include #ifdef __cplusplus -#include -#include -#include // for handlers -#include // for service::address -#include -#include -#include - extern "C" { #endif @@ -27,106 +19,156 @@ extern "C" /// llarp application context for C api struct llarp_main; - /// initialize application context and load config - struct llarp_main * - llarp_main_init(const char *fname, bool multiProcess); + /// llarp_application config + struct llarp_config; - /// handle signal for main context - void - llarp_main_signal(struct llarp_main *ptr, int sig); + /// get default config for current platform + struct llarp_config * + llarp_default_config(); - /// give main context a vpn file descriptor pair (android/ios) - void - llarp_main_inject_vpn_fd(struct llarp_main *m, int rfd, int wfd); + /// packet writer to send packets to lokinet internals + struct llarp_vpn_writer_pipe; + /// packet reader to recv packets from lokinet internals + struct llarp_vpn_reader_pipe; - /// setup main context, returns 0 on success - int - llarp_main_setup(struct llarp_main *ptr, bool debugMode); + /// vpn io api + /// all hooks called in native code + /// for use with a vpn interface managed by external code + /// the external vpn interface MUST be up and have addresses set + struct llarp_vpn_io + { + /// private implementation + void *impl; + /// user data + void *user; + /// hook set by user called by lokinet core when lokinet is done with the + /// vpn io + void (*closed)(struct llarp_vpn_io *); + /// hook set by user called from lokinet core after attempting to inject + /// into endpoint passed a bool set to true if we were injected otherwise + /// set to false + void (*injected)(struct llarp_vpn_io *, bool); + /// hook set by user called every event loop tick + void (*tick)(struct llarp_vpn_io *); + }; - /// run main context, returns 0 on success, blocks until program end - int - llarp_main_run(struct llarp_main *ptr); + /// info about the network interface that we give to lokinet core + struct llarp_vpn_ifaddr_info + { + /// name of the network interface + char ifname[64]; + /// interface's address + struct sockaddr_storage ifaddr; + /// interface's netmask + struct sockaddr_storage netmask; + }; - /// free main context and end all operations + /// initialize llarp_vpn_io private implementation void - llarp_main_free(struct llarp_main *ptr); - -#ifdef __cplusplus + llarp_vpn_io_init(struct llarp_vpn_io *io); + + /// get the packet pipe for writing IP packets to lokinet internals + /// can return nullptr + struct llarp_vpn_pkt_writer * + llarp_vpn_io_packet_writer(struct llarp_vpn_io *io); + + /// get the packet pipe for reading IP packets from lokinet internals + /// can return nullptr + struct llarp_vpn_pkt_reader * + llarp_vpn_io_packet_reader(struct llarp_vpn_io *io); + + /// blocking read on packet reader from lokinet internals + /// returns -1 on error, returns size of packet read + /// thread safe + ssize_t + llarp_vpn_io_readpkt(struct llarp_vpn_pkt_reader *r, unsigned char *dst, + size_t dstlen); + + /// blocking write on packet writer to lokinet internals + /// returns false if we can't write this packet + /// return true if we wrote this packet + /// thread safe + bool + llarp_vpn_io_writepkt(struct llarp_vpn_pkt_writer *w, unsigned char *pktbuf, + size_t pktlen); + /// close vpn io and free private implementation after done + /// operation is async and calls llarp_vpn_io.closed after fully closed + /// after fully closed the llarp_vpn_io MUST be re-initialized by + /// llarp_vpn_io_init if it is to be used again void - llarp_main_abort(struct llarp_main *ptr); + llarp_vpn_io_close_async(struct llarp_vpn_io *io); + /// get the default endpoint's name for injection const char * - handleBaseCmdLineArgs(int argc, char *argv[]); - - /// load nodeDB into memory - int - llarp_main_loadDatabase(struct llarp_main *ptr); + llarp_main_get_default_endpoint_name(struct llarp_main *m); - /// iterator on nodedb entries - int - llarp_main_iterateDatabase(struct llarp_main *ptr, - struct llarp_nodedb_iter i); + /// give main context a vpn io for mobile when it is reader to do io with + /// associated info tries to give the vpn io to endpoint with name epName a + /// deferred call to llarp_vpn_io.injected is queued unconditionally + /// thread safe + void + llarp_main_inject_vpn_by_name(struct llarp_main *m, const char *epName, + struct llarp_vpn_io *io, + struct llarp_vpn_ifaddr_info info); + + /// give main context a vpn io on its default endpoint + static void + llarp_main_inject_default_vpn(struct llarp_main *m, struct llarp_vpn_io *io, + struct llarp_vpn_ifaddr_info info) + { + llarp_main_inject_vpn_by_name(m, llarp_main_get_default_endpoint_name(m), + io, info); + } - /// put RC into nodeDB + /// load config from file by name bool - llarp_main_putDatabase(struct llarp_main *ptr, - struct llarp::RouterContact &rc); - - // fwd declr - struct check_online_request; + llarp_config_load_file(const char *fname, struct llarp_config **config); - /// check_online_request hook definition - typedef void (*check_online_request_hook_func)(struct check_online_request *); + /// make a main context from configuration + struct llarp_main * + llarp_main_init_from_config(struct llarp_config *conf); - struct check_online_request + /// initialize application context and load config + static struct llarp_main * + llarp_main_init(const char *fname, bool) { - struct llarp_main *ptr; - struct llarp_router_lookup_job *job; - bool online; - size_t nodes; - bool first; - check_online_request_hook_func hook; - }; - - /// get RC from DHT but wait until online - void - llarp_main_queryDHT(struct check_online_request *request); + struct llarp_config *conf = NULL; + if(!llarp_config_load_file(fname, &conf)) + return NULL; + if(conf == NULL) + return NULL; + return llarp_main_init_from_config(conf); + } + + /// initialize applicatin context with all defaults + static struct llarp_main * + llarp_main_default_init() + { + struct llarp_config *conf; + conf = llarp_default_config(); + if(conf == NULL) + return NULL; + return llarp_main_init_from_config(conf); + } - /// get RC from DHT + /// handle signal for main context void - llarp_main_queryDHT_RC(struct llarp_main *ptr, - struct llarp_router_lookup_job *job); - - /// set up DNS libs with a context - bool - llarp_main_init_dnsd(struct llarp_main *ptr, struct dnsd_context *dnsd, - const llarp::Addr &dnsd_sockaddr, - const llarp::Addr &dnsc_sockaddr); - - /// set up dotLokiLookup with logic for setting timers - bool - llarp_main_init_dotLokiLookup(struct llarp_main *ptr, - struct dotLokiLookup *dll); + llarp_main_signal(struct llarp_main *ptr, int sig); - llarp::RouterContact * - llarp_main_getLocalRC(struct llarp_main *ptr); - /// get RC from nodeDB - llarp::RouterContact * - llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk); + /// setup main context, returns 0 on success + int + llarp_main_setup(struct llarp_main *ptr, bool debugMode); - llarp_tun_io * - main_router_getRange(struct llarp_main *ptr); + /// run main context, returns 0 on success, blocks until program end + int + llarp_main_run(struct llarp_main *ptr); - /// map an (host byte order) ip to a hidden service address - bool - main_router_mapAddress(struct llarp_main *ptr, - const llarp::service::Address &addr, uint32_t ip); + /// free main context and end all operations + void + llarp_main_free(struct llarp_main *ptr); - /// info of possible path usage - bool - main_router_prefetch(struct llarp_main *ptr, - const llarp::service::Address &addr); +#ifdef __cplusplus } #endif #endif From 6dc350a8f372d36a099c7eb4172d9a82d3ec77ca Mon Sep 17 00:00:00 2001 From: jeff Date: Fri, 4 Oct 2019 14:16:39 -0400 Subject: [PATCH 02/17] update cmake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d03b7099..ed9a69cfd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,8 +163,8 @@ endif() if (NOT MSVC OR NOT MSVC_VERSION) add_compile_options(${OPTIMIZE_FLAGS} ${CRYPTO_FLAGS}) endif() -add_subdirectory(${ABSEIL_DIR}) add_subdirectory(vendor/gtest) +add_subdirectory(${ABSEIL_DIR}) if (FS_LIB STREQUAL "cppbackport") add_subdirectory(vendor) From 313898999d50c3868fdfcb79d8a0bac4e4fa7422 Mon Sep 17 00:00:00 2001 From: jeff Date: Mon, 7 Oct 2019 06:05:12 -0400 Subject: [PATCH 03/17] initial jni wrapper stuff --- .../network/loki/lokinet/LokiNetActivity.java | 8 +-- .../network/loki/lokinet/LokinetService.java | 1 + .../src/network/loki/lokinet/Lokinet_JNI.java | 44 ------------- jni/lokinet_android.cpp | 61 ++----------------- 4 files changed, 9 insertions(+), 105 deletions(-) delete mode 100644 android/src/network/loki/lokinet/Lokinet_JNI.java diff --git a/android/src/network/loki/lokinet/LokiNetActivity.java b/android/src/network/loki/lokinet/LokiNetActivity.java index b299a94fd..8654d676b 100755 --- a/android/src/network/loki/lokinet/LokiNetActivity.java +++ b/android/src/network/loki/lokinet/LokiNetActivity.java @@ -33,20 +33,16 @@ import android.widget.TextView; public class LokiNetActivity extends Activity { private static final String TAG = "lokinet-activity"; private TextView textView; - private static final String DefaultBootstrapURL = "https://i2p.rocks/bootstrap.signed"; + private static final String DefaultBootstrapURL = "https://seed.lokinet.org/bootstrap.signed"; private AsyncBootstrap bootstrapper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - // copy assets - //String conf = copyFileAsset("daemon.ini"); textView = new TextView(this); setContentView(textView); - - Lokinet_JNI.loadLibraries(); + System.loadLibrary("lokinetandroid"); } diff --git a/android/src/network/loki/lokinet/LokinetService.java b/android/src/network/loki/lokinet/LokinetService.java index 9030a1f21..7dbae6236 100644 --- a/android/src/network/loki/lokinet/LokinetService.java +++ b/android/src/network/loki/lokinet/LokinetService.java @@ -5,4 +5,5 @@ import android.net.VpnService; public class LokinetService extends VpnService { + } diff --git a/android/src/network/loki/lokinet/Lokinet_JNI.java b/android/src/network/loki/lokinet/Lokinet_JNI.java deleted file mode 100644 index a5d3cda40..000000000 --- a/android/src/network/loki/lokinet/Lokinet_JNI.java +++ /dev/null @@ -1,44 +0,0 @@ -package network.loki.lokinet; - -public class Lokinet_JNI { - - public static final String STATUS_OK = "ok"; - - public static native String getABICompiledWith(); - - /** - * returns error info if failed - * returns "ok" if daemon initialized and started okay - */ - public static native String startLokinet(String config); - - /** - * stop daemon if running - */ - public static native void stopLokinet(); - - /** get interface address we want */ - public static native String getIfAddr(); - - /** get interface address range we want */ - public static native int getIfRange(); - - /** - * change network status - */ - public static native void onNetworkStateChanged(boolean isConnected); - - /** - * set vpn network interface fd pair - * @param rfd the file descriptor of read end - * @param wfd the file descriptor of the write end - */ - public static native void setVPNFileDescriptor(int rfd, int wfd); - - /** - * load jni libraries - */ - public static void loadLibraries() { - System.loadLibrary("lokinetandroid"); - } -} diff --git a/jni/lokinet_android.cpp b/jni/lokinet_android.cpp index 2ecc41243..4c4cc0ac4 100644 --- a/jni/lokinet_android.cpp +++ b/jni/lokinet_android.cpp @@ -39,10 +39,10 @@ struct AndroidMain { if(m_impl || m_thread) return true; - m_impl = llarp_main_init(configFile.c_str(), true); + m_impl = llarp_main_default_init(); if(m_impl == nullptr) return false; - if(llarp_main_setup(m_impl, false)) + if(llarp_main_setup(m_impl)) { llarp_main_free(m_impl); m_impl = nullptr; @@ -63,7 +63,8 @@ struct AndroidMain void Run() { - if(llarp_main_run(m_impl)) + llarp_main_runtime_opts opts; + if(llarp_main_run(m_impl, opts)) { // on error llarp::LogError("daemon run fail"); @@ -74,50 +75,6 @@ struct AndroidMain } } - const char* - GetIfAddr() - { - std::string addr; - if(m_impl) - { - auto* ctx = llarp_main_get_context(m_impl); - if(!ctx) - return ""; - - ctx->router->hiddenServiceContext().ForEachService( - [&addr](const std::string&, - const llarp::service::Endpoint_ptr& ep) -> bool { - if(addr.empty()) - { - if(ep->HasIfAddr()) - { - // TODO: v4 - const auto ip = ep->GetIfAddr(); - if(ip.h) - { - addr = ip.ToString(); - return false; - } - } - } - return true; - }); - } - return addr.c_str(); - } - - int - GetIfRange() const - { - if(m_impl) - { - auto* ctx = llarp_main_get_context(m_impl); - if(!ctx) - return -1; - } - return -1; - } - void SetVPN_FD(int rfd, int wfd) { @@ -200,19 +157,13 @@ extern "C" JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getIfAddr(JNIEnv* env, jclass) { - if(daemon_ptr) - return env->NewStringUTF(daemon_ptr->GetIfAddr()); - else - return env->NewStringUTF(""); + return env->NewStringUTF(""); } JNIEXPORT jint JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getIfRange(JNIEnv*, jclass) { - if(daemon_ptr) - return daemon_ptr->GetIfRange(); - else - return -1; + return -1; } JNIEXPORT void JNICALL From c26b67c379073dd60d430758529ab85b8fb89e80 Mon Sep 17 00:00:00 2001 From: jeff Date: Tue, 8 Oct 2019 10:52:01 -0400 Subject: [PATCH 04/17] finish wiring up jni shizz --- CMakeLists.txt | 5 +- daemon/main.cpp | 9 +- include/llarp.h | 52 ++++++- jni/CMakeLists.txt | 10 ++ jni/lokinet_config.cpp | 38 +++++ jni/lokinet_daemon.cpp | 82 ++++++++++ jni/lokinet_jni_common.hpp | 77 ++++++++++ jni/lokinet_jni_vpnio.hpp | 141 ++++++++++++++++++ jni/lokinet_vpn.cpp | 90 +++++++++++ jni/network_loki_lokinet_LokinetConfig.h | 38 +++++ jni/network_loki_lokinet_LokinetDaemon.h | 70 +++++++++ jni/network_loki_lokinet_LokinetVPN.h | 69 +++++++++ jni/network_loki_lokinet_LokinetVPN_VPNInfo.h | 14 ++ llarp/context.cpp | 52 ++++--- llarp/service/context.cpp | 2 +- 15 files changed, 717 insertions(+), 32 deletions(-) create mode 100644 jni/CMakeLists.txt create mode 100644 jni/lokinet_config.cpp create mode 100644 jni/lokinet_daemon.cpp create mode 100644 jni/lokinet_jni_common.hpp create mode 100644 jni/lokinet_jni_vpnio.hpp create mode 100644 jni/lokinet_vpn.cpp create mode 100644 jni/network_loki_lokinet_LokinetConfig.h create mode 100644 jni/network_loki_lokinet_LokinetDaemon.h create mode 100644 jni/network_loki_lokinet_LokinetVPN.h create mode 100644 jni/network_loki_lokinet_LokinetVPN_VPNInfo.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ed9a69cfd..29b38ff15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -311,10 +311,7 @@ else() target_link_libraries(lokinet-rcutil PUBLIC ${EXE_LIBS} ${LIBS}) if(ANDROID) - add_library(${ANDROID_LIB} SHARED jni/lokinet_android.cpp) - set_property(TARGET ${ANDROID_LIB} PROPERTY CXX_STANDARD 14) - add_log_tag(${ANDROID_LIB}) - target_link_libraries(${ANDROID_LIB} ${STATIC_LIB} ${LIBS}) + add_subdirectory(jni) endif(ANDROID) endif(SHADOW) diff --git a/daemon/main.cpp b/daemon/main.cpp index 61aa78440..fd6e9ea74 100644 --- a/daemon/main.cpp +++ b/daemon/main.cpp @@ -149,9 +149,9 @@ main(int argc, char *argv[]) options.parse_positional("config"); // clang-format on - bool genconfigOnly = false; - bool asRouter = false; - bool overWrite = false; + bool genconfigOnly = false; + bool asRouter = false; + bool overWrite = false; std::string conffname; // suggestions: confFName? conf_fname? try { @@ -319,8 +319,7 @@ main(int argc, char *argv[]) return 0; } - std::thread main_thread{ - std::bind(&run_main_context, conffname, opts)}; + std::thread main_thread{std::bind(&run_main_context, conffname, opts)}; auto ftr = exit_code.get_future(); do { diff --git a/include/llarp.h b/include/llarp.h index cb4bca0c2..f1dd044c7 100644 --- a/include/llarp.h +++ b/include/llarp.h @@ -35,6 +35,10 @@ extern "C" struct llarp_config * llarp_default_config(); + /// free previously allocated configuration + void + llarp_config_free(struct llarp_config *); + /// packet writer to send packets to lokinet internals struct llarp_vpn_writer_pipe; /// packet reader to recv packets from lokinet internals @@ -68,8 +72,8 @@ extern "C" char ifname[64]; /// interface's address as string char ifaddr[128]; - /// netmask bits - unsigned char netmask; + /// netmask number of bits set + uint8_t netmask; }; /// initialize llarp_vpn_io private implementation @@ -132,10 +136,19 @@ extern "C" } /// load config from file by name + /// allocates new config and puts it into c + /// return false on failure + bool + llarp_config_load_file(const char *fname, struct llarp_config **c); + + /// loads config from file by name + /// uses already allocated config + /// return false on failure bool - llarp_config_load_file(const char *fname, struct llarp_config **config); + llarp_config_read_file(struct llarp_config *c, const char *f); /// make a main context from configuration + /// copies config contents struct llarp_main * llarp_main_init_from_config(struct llarp_config *conf); @@ -143,25 +156,41 @@ extern "C" static struct llarp_main * llarp_main_init(const char *fname) { + struct llarp_main *m = 0; struct llarp_config *conf = 0; if(!llarp_config_load_file(fname, &conf)) return 0; if(conf == NULL) return 0; - return llarp_main_init_from_config(conf); + m = llarp_main_init_from_config(conf); + llarp_config_free(conf); + return m; } /// initialize applicatin context with all defaults static struct llarp_main * llarp_main_default_init() { + struct llarp_main *m; struct llarp_config *conf; conf = llarp_default_config(); if(conf == 0) return 0; - return llarp_main_init_from_config(conf); + m = llarp_main_init_from_config(conf); + llarp_config_free(conf); + return m; } + /// (re)configure main context + /// return true if (re)configuration was successful + bool + llarp_main_configure(struct llarp_main *ptr, struct llarp_config *conf); + + /// return true if this main context is running + /// return false otherwise + bool + llarp_main_is_running(struct llarp_main *ptr); + /// handle signal for main context void llarp_main_signal(struct llarp_main *ptr, int sig); @@ -174,6 +203,11 @@ extern "C" int llarp_main_run(struct llarp_main *ptr, struct llarp_main_runtime_opts opts); + /// tell main context to stop and wait for complete stop + /// after calling this you can call llarp_main_free safely + void + llarp_main_stop(struct llarp_main *ptr); + /// free main context and end all operations void llarp_main_free(struct llarp_main *ptr); @@ -182,6 +216,14 @@ extern "C" const char * llarp_version(); + /// return sizeof(llarp_main); for jni + size_t + llarp_main_size(); + + /// return sizeof(llarp_config); for jni + size_t + llarp_config_size(); + #ifdef __cplusplus } #endif diff --git a/jni/CMakeLists.txt b/jni/CMakeLists.txt new file mode 100644 index 000000000..d6cf96b53 --- /dev/null +++ b/jni/CMakeLists.txt @@ -0,0 +1,10 @@ + + set(ANDROID_SRC + jni/lokinet_config.cpp + jni/lokinet_daemon.cpp + jni/lokinet_vnp.cpp + ) + add_library(${ANDROID_LIB} SHARED ${ANDROID_SRC}) + set_property(TARGET ${ANDROID_LIB} PROPERTY CXX_STANDARD 14) + add_log_tag(${ANDROID_LIB}) + target_link_libraries(${ANDROID_LIB} ${STATIC_LIB} ${LIBS}) \ No newline at end of file diff --git a/jni/lokinet_config.cpp b/jni/lokinet_config.cpp new file mode 100644 index 000000000..8cf59e10b --- /dev/null +++ b/jni/lokinet_config.cpp @@ -0,0 +1,38 @@ +#include "network_loki_lokinet_LokinetConfig.h" +#include +#include "lokinet_jni_common.hpp" + +extern "C +{ + JNIEXPORT jobject JNICALL + Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv* env, jclass* c) + { + llarp_config* conf = llarp_default_config(); + if(conf == nullptr) + return nullptr; + return env->NewDirectByteBuffer(conf, llarp_config_size()); + } + + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv* env, jclass c, + jobject buf) + { + llarp_config_free(FromBuffer< llarp_config >(env, buf)); + } + + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv* env, jobject self, + jstring fname) + { + llarp_config* conf = FromObjectMember< llarp_config >(env, self, "impl"); + if(conf == nullptr) + return JNI_FALSE; + return VisitStringAsStringView< jboolean >( + env, fname, [conf](llarp::string_view val) -> jboolean { + const auto filename = llarp::string_view_string(val); + if(llarp_config_read_file(conf, filename.c_str())) + return JNI_TRUE; + return JNI_FALSE; + }); + } +} \ No newline at end of file diff --git a/jni/lokinet_daemon.cpp b/jni/lokinet_daemon.cpp new file mode 100644 index 000000000..8a542bbcc --- /dev/null +++ b/jni/lokinet_daemon.cpp @@ -0,0 +1,82 @@ +#include "network_loki_lokinet_LokinetDaemon.h" +#include "lokinet_jni_common.hpp" +#include "lokinet_jni_vpnio.hpp" +#include + +extern "C" +{ + JNIEXPORT jobject JNICALL + Java_network_loki_lokinet_LokinetDaemon_Obtain(JNIEnv *env, jclass) + { + llarp_main *ptr = llarp_main_default_init(); + if(ptr == nullptr) + return nullptr; + return env->NewDirectByteBuffer(ptr, llarp_main_size()); + } + + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetDaemon_Free(JNIEnv *env, jclass, jobject buf) + { + llarp_main *ptr = FromBuffer< llarp_main >(env, buf); + llarp_main_free(ptr); + } + + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetDaemon_Configure(JNIEnv *env, jobject self, + jobject conf) + { + llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); + llarp_config *config = FromObjectMember< llarp_config >(env, conf, "impl"); + if(ptr == nullptr || config == nullptr) + return JNI_FALSE; + if(llarp_main_configure(ptr, config)) + return JNI_TRUE; + return JNI_FALSE; + } + + JNIEXPORT jint JNICALL + Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv *env, jobject self) + { + static llarp_main_runtime_opts opts; + llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); + if(ptr == nullptr) + return -1; + return llarp_main_run(ptr, opts); + } + + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetDaemon_IsRunning(JNIEnv *env, jobject self) + { + llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); + return (ptr != nullptr && llarp_main_is_running(ptr)) ? JNI_TRUE + : JNI_FALSE; + } + + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetDaemon_Stop(JNIEnv *env, jobject self) + { + llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); + if(ptr == nullptr) + return JNI_FALSE; + if(not llarp_main_is_running(ptr)) + return JNI_FALSE; + llarp_main_stop(ptr); + return llarp_main_is_running(ptr) ? JNI_FALSE : JNI_TRUE; + } + + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetDaemon_InjectVPN(JNIEnv *env, jobject self, + jobject vpn) + { + llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); + lokinet_jni_vpnio *impl = + FromObjectMember< lokinet_jni_vpnio >(env, vpn, "impl"); + if(ptr == nullptr || impl == nullptr) + return JNI_FALSE; + if(not impl->Init(ptr)) + return JNI_FASE; + return llarp_main_inject_default_vpn(ptr, &impl->io, impl->info) + ? JNI_TRUE + : JNI_FALSE; + } +} \ No newline at end of file diff --git a/jni/lokinet_jni_common.hpp b/jni/lokinet_jni_common.hpp new file mode 100644 index 000000000..79e8e0b13 --- /dev/null +++ b/jni/lokinet_jni_common.hpp @@ -0,0 +1,77 @@ +#ifndef LOKINET_JNI_COMMON_HPP +#define LOKINET_JNI_COMMON_HPP + +#include +#include +#include + +/// visit string as native bytes +template < typename T, typename V > +static T +VisitStringAsStringView(JNIEnv* env, jobject str, V visit) +{ + const jclass stringClass = env->GetObjectClass(str); + const jmethodID getBytes = + env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B"); + + const jstring charsetName = env->NewStringUTF("UTF-8"); + const jbyteArray stringJbytes = + (jbyteArray)env->CallObjectMethod(str, getBytes, charsetName); + env->DeleteLocalRef(charsetName); + + const jsize length = env->GetArrayLength(stringJbytes); + const jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL); + + T result = visit(llarp::string_view(bBytes, length)); + + env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); + env->DeleteLocalRef(stringJbytes); + + return std::move(result); +} + +/// cast jni buffer to T * +template < typename T > +static T* +FromBuffer(JNIEnv* env, jobject o) +{ + if(o == nullptr) + return nullptr; + return static_cast< T* >(env->GetDirectBufferAddress(o)); +} + +/// get T * from object member called membername +template < typename T > +static T* +FromObjectMember(JNIEnv* env, jobject self, const char* membername) +{ + jclass cl = env->GetObjectClass(self); + jfieldID name = env->GetFieldID(cl, membername, "Ljava/nio/Buffer;"); + jobject buffer = env->GetObjectField(self, name); + return FromBuffer< T >(env, buffer); +} + +/// visit object string member called membername as bytes +template < typename T, typename V > +static T +VisitObjectMemberStringAsStringView(JNIEnv* env, jobject self, + const char* membername, V v) +{ + jclass cl = env->GetObjectClass(self); + jfieldID name = env->GetFieldID(cl, membername, "Ljava/lang/String;"); + jobject str = env->GetObjectField(self, name); + return VisitStringAsStringView(env, str, v); +} + +/// get object member int called membername +template < typename Int_t > +void +GetObjectMemberAsInt(JNIEnv* env, jobject self, const char* membername, + Int_t& result) +{ + jclass cl = env->GetObjectClass(self); + jfieldID name = env->GetFieldID(cl, membername, "I"); + result = env->GetIntField(self, name); +} + +#endif \ No newline at end of file diff --git a/jni/lokinet_jni_vpnio.hpp b/jni/lokinet_jni_vpnio.hpp new file mode 100644 index 000000000..f0b981cc5 --- /dev/null +++ b/jni/lokinet_jni_vpnio.hpp @@ -0,0 +1,141 @@ +#ifndef LOKINET_JNI_VPNIO_HPP +#define LOKINET_JNI_VPNIO_HPP + +#include +#include +#include +#include +#include + +namespace lokinet +{ + struct VPNIO + { + static VPNIO * + Get(llarp_vpn_io *vpn) + { + return static_cast< VPNIO * >(vpn->user); + } + + virtual ~VPNIO() = default; + + llarp_vpn_io io; + llarp_vpn_ifaddr_info info{{0}, {0}, 0}; + std::unique_ptr< std::promise< void > > closeWaiter; + + void + Closed() + { + if(closeWaiter) + closeWaiter->get_future().set_value(); + } + + virtual void + InjectSuccess() = 0; + + virtual void + InjectFail() = 0; + + virtual void + Tick() = 0; + + VPNIO() + { + io.impl = nullptr; + io.user = this; + io.closed = [](llarp_vpn_io *vpn) { VPNIO::Get(vpn)->Closed(); }; + io.injected = [](llarp_vpn_io *vpn, bool good) { + VPNIO *ptr = VPNIO::Get(vpn); + if(good) + ptr->InjectSuccess(); + else + ptr->InjectFail(); + }; + io.tick = [](llarp_vpn_io *vpn) { VPNIO::Get(vpn)->Tick(); }; + } + + bool + Init(llarp_main *ptr) + { + return llarp_vpn_io_init(ptr, &io); + } + + void + Close() + { + if(io.impl == nullptr) + return; + if(closeWaiter) + return; + closerWaiter = std::make_unique< std::promise< void > >(); + llarp_vpn_io_close_async(&io); + closeWaiter->wait(); + closeWaiter.reset(); + io.impl = nullptr; + } + + llarp_vpn_pkt_reader * + Reader() + { + return llarp_vpn_io_packet_reader(&io); + } + + llarp_vpn_pkt_writer * + Writer() + { + return llarp_vpn_io_packet_writer(&io); + } + + ssize_t + ReadPacket(void *dst, size_t len) + { + if(io.impl == nullptr) + return -1; + unsigned char *buf = (unsigned char *)dst; + return llarp_vpn_io_readpkt(Reader(), buf, len); + } + + bool + WritePacket(void *pkt, size_t len) + { + if(io.impl == nullptr) + return false; + unsigned char *buf = (unsigned char *)pkt; + return llarp_vpn_io_writepkt(Writer(), buf, len); + } + + void + SetIfName(llarp::string_view val) + { + const auto sz = std::min(val.size(), sizeof(info.ifname)); + std::copy_n(val.data(), sz, info.ifname); + } + + void + SetIfAddr(llarp::string_view val) + { + const auto sz = std::min(val.size(), sizeof(info.ifaddr)); + std::copy_n(val.data(), sz, info.ifaddr); + } + }; +} // namespace lokinet + +struct lokinet_jni_vpnio : public lokinet::VPNIO +{ + void + InjectSuccess() override + { + } + + void + InjectFail() override + { + } + + void + Tick() override + { + } +}; + +#endif \ No newline at end of file diff --git a/jni/lokinet_vpn.cpp b/jni/lokinet_vpn.cpp new file mode 100644 index 000000000..8c8d39c1e --- /dev/null +++ b/jni/lokinet_vpn.cpp @@ -0,0 +1,90 @@ +#include "network_loki_lokinet_LokinetVPN.h" +#include "lokinet_jni_vpnio.hpp" +#include "lokinet_jni_common.hpp" +#include + +extern "C" +{ + JNIEXPORT jint JNICALL + Java_network_loki_lokinet_LokinetVPN_PacketSize(JNIEnv *, jclass) + { + return llarp::net::IPPacket::MaxSize; + } + + JNIEXPORT jobject JNICALL + Java_network_loki_lokinet_LokinetVPN_Alloc(JNIEnv *env, jclass) + { + lokinet_jni_vpnio *vpn = new lokinet_jni_vpnio(); + return env->NewDirectByteBuffer(vpn, sizeof(lokinet_jni_vpnio)); + } + + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetVPN_Free(JNIEnv *env, jclass, jobject buf) + { + lokinet_jni_vpnio *vpn = FromBuffer< lokinet_jni_vpnio >(env, buf); + if(vpn == nullptr) + return; + delete vpn; + } + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetVPN_Stop(JNIEnv *env, jobject self) + { + lokinet_jni_vpnio *vpn = + FromObjectMember< lokinet_jni_vpnio >(env, self, "impl"); + if(vpn) + { + vpn->Close(); + } + } + + JNIEXPORT jint JNICALL + Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv *env, jobject self, + jobject pkt) + { + lokinet_jni_vpnio *vpn = + FromObjectMember< lokinet_jni_vpnio >(env, self, "impl"); + if(vpn == nullptr) + return -1; + void *pktbuf = env->GetDirectBufferAddress(pkt); + auto pktlen = env->GetDirectBufferCapacity(pkt); + if(pktbuf == nullptr) + return -1; + return vpn->ReadPacket(pktbuf, pktlen); + } + + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetVPN_WritePkt(JNIEnv *env, jobject self, + jobject pkt) + { + lokinet_jni_vpnio *vpn = + FromObjectMember< lokinet_jni_vpnio >(env, self, "impl"); + if(vpn == nullptr) + return false; + void *pktbuf = env->GetDirectBufferAddress(pkt); + auto pktlen = env->GetDirectBufferCapacity(pkt); + if(pktbuf == nullptr) + return false; + return vpn->WritePacket(pktbuf, pktlen); + } + + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetVPN_SetInfo(JNIEnv *env, jobject self, + jobject info) + { + lokinet_jni_vpnio *vpn = + FromObjectMember< lokinet_jni_vpnio >(env, self, "impl"); + if(vpn == nullptr) + return; + VisitObjectMemberStringAsStringView< bool >( + env, info, "ifaddr", [vpn](llarp::string_view val) -> bool { + vpn->SetIfAddr(val); + return true; + }); + VisitObjectMemberStringAsStringView< bool >( + env, info, "ifname", [vpn](llarp::string_view val) -> bool { + vpn->SetIfName(val); + return true; + }); + GetObjectMemberAsInt(env, info, "netmask", vpn->info.netmask); + } +} \ No newline at end of file diff --git a/jni/network_loki_lokinet_LokinetConfig.h b/jni/network_loki_lokinet_LokinetConfig.h new file mode 100644 index 000000000..f39b87542 --- /dev/null +++ b/jni/network_loki_lokinet_LokinetConfig.h @@ -0,0 +1,38 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class network_loki_lokinet_LokinetConfig */ + +#ifndef _Included_network_loki_lokinet_LokinetConfig +#define _Included_network_loki_lokinet_LokinetConfig +#ifdef __cplusplus +extern "C" +{ +#endif + /* + * Class: network_loki_lokinet_LokinetConfig + * Method: Obtain + * Signature: ()Ljava/nio/Buffer; + */ + JNIEXPORT jobject JNICALL + Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv *, jclass); + + /* + * Class: network_loki_lokinet_LokinetConfig + * Method: Free + * Signature: (Ljava/nio/Buffer;)V + */ + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv *, jclass, jobject); + + /* + * Class: network_loki_lokinet_LokinetConfig + * Method: Load + * Signature: (Ljava/lang/String;)Z + */ + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv *, jobject, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/jni/network_loki_lokinet_LokinetDaemon.h b/jni/network_loki_lokinet_LokinetDaemon.h new file mode 100644 index 000000000..400807bb6 --- /dev/null +++ b/jni/network_loki_lokinet_LokinetDaemon.h @@ -0,0 +1,70 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class network_loki_lokinet_LokinetDaemon */ + +#ifndef _Included_network_loki_lokinet_LokinetDaemon +#define _Included_network_loki_lokinet_LokinetDaemon +#ifdef __cplusplus +extern "C" +{ +#endif + /* + * Class: network_loki_lokinet_LokinetDaemon + * Method: Obtain + * Signature: ()Ljava/nio/Buffer; + */ + JNIEXPORT jobject JNICALL + Java_network_loki_lokinet_LokinetDaemon_Obtain(JNIEnv *, jclass); + + /* + * Class: network_loki_lokinet_LokinetDaemon + * Method: Free + * Signature: (Ljava/nio/Buffer;)V + */ + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetDaemon_Free(JNIEnv *, jclass, jobject); + + /* + * Class: network_loki_lokinet_LokinetDaemon + * Method: Configure + * Signature: (Lnetwork/loki/lokinet/LokinetConfig;)Z + */ + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetDaemon_Configure(JNIEnv *, jobject, jobject); + + /* + * Class: network_loki_lokinet_LokinetDaemon + * Method: Mainloop + * Signature: ()I + */ + JNIEXPORT jint JNICALL + Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv *, jobject); + + /* + * Class: network_loki_lokinet_LokinetDaemon + * Method: IsRunning + * Signature: ()Z + */ + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetDaemon_IsRunning(JNIEnv *, jobject); + + /* + * Class: network_loki_lokinet_LokinetDaemon + * Method: Stop + * Signature: ()Z + */ + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetDaemon_Stop(JNIEnv *, jobject); + + /* + * Class: network_loki_lokinet_LokinetDaemon + * Method: InjectVPN + * Signature: (Lnetwork/loki/lokinet/LokinetVPN;)Z + */ + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetDaemon_InjectVPN(JNIEnv *, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/jni/network_loki_lokinet_LokinetVPN.h b/jni/network_loki_lokinet_LokinetVPN.h new file mode 100644 index 000000000..0aca1654f --- /dev/null +++ b/jni/network_loki_lokinet_LokinetVPN.h @@ -0,0 +1,69 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class network_loki_lokinet_LokinetVPN */ + +#ifndef _Included_network_loki_lokinet_LokinetVPN +#define _Included_network_loki_lokinet_LokinetVPN +#ifdef __cplusplus +extern "C" +{ +#endif + /* + * Class: network_loki_lokinet_LokinetVPN + * Method: PacketSize + * Signature: ()I + */ + JNIEXPORT jint JNICALL + Java_network_loki_lokinet_LokinetVPN_PacketSize(JNIEnv *, jclass); + + /* + * Class: network_loki_lokinet_LokinetVPN + * Method: Alloc + * Signature: ()Ljava/nio/Buffer; + */ + JNIEXPORT jobject JNICALL + Java_network_loki_lokinet_LokinetVPN_Alloc(JNIEnv *, jclass); + + /* + * Class: network_loki_lokinet_LokinetVPN + * Method: Free + * Signature: (Ljava/nio/Buffer;)V + */ + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetVPN_Free(JNIEnv *, jclass, jobject); + + /* + * Class: network_loki_lokinet_LokinetVPN + * Method: Stop + * Signature: ()V + */ + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetVPN_Stop(JNIEnv *, jobject); + + /* + * Class: network_loki_lokinet_LokinetVPN + * Method: ReadPkt + * Signature: (Ljava/nio/ByteBuffer;)I + */ + JNIEXPORT jint JNICALL + Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv *, jobject, jobject); + + /* + * Class: network_loki_lokinet_LokinetVPN + * Method: WritePkt + * Signature: (Ljava/nio/ByteBuffer;)Z + */ + JNIEXPORT jboolean JNICALL + Java_network_loki_lokinet_LokinetVPN_WritePkt(JNIEnv *, jobject, jobject); + + /* + * Class: network_loki_lokinet_LokinetVPN + * Method: SetInfo + * Signature: (Lnetwork/loki/lokinet/LokinetVPN/VPNInfo;)V + */ + JNIEXPORT void JNICALL + Java_network_loki_lokinet_LokinetVPN_SetInfo(JNIEnv *, jobject, jobject); +#ifdef __cplusplus +} +#endif +#endif diff --git a/jni/network_loki_lokinet_LokinetVPN_VPNInfo.h b/jni/network_loki_lokinet_LokinetVPN_VPNInfo.h new file mode 100644 index 000000000..c7937a30f --- /dev/null +++ b/jni/network_loki_lokinet_LokinetVPN_VPNInfo.h @@ -0,0 +1,14 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class network_loki_lokinet_LokinetVPN_VPNInfo */ + +#ifndef _Included_network_loki_lokinet_LokinetVPN_VPNInfo +#define _Included_network_loki_lokinet_LokinetVPN_VPNInfo +#ifdef __cplusplus +extern "C" +{ +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/llarp/context.cpp b/llarp/context.cpp index 5c47bfe98..2c7197669 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -371,43 +370,62 @@ __ ___ ____ _ _ ___ _ _ ____ } } // namespace llarp -extern "C" +struct llarp_main +{ + llarp_main(llarp_config *conf); + ~llarp_main() = default; + std::unique_ptr< llarp::Context > ctx; +}; + +struct llarp_config { - struct llarp_main + llarp::Config impl; + llarp_config() = default; + + llarp_config(const llarp_config *other) : impl(other->impl) { - llarp_main(llarp_config *conf); - ~llarp_main() = default; - std::unique_ptr< llarp::Context > ctx; - }; + } +}; - struct llarp_config +extern "C" +{ + size_t + llarp_main_size() { - llarp::Config impl; - llarp_config() = default; + return sizeof(llarp_main); + } - llarp_config(const llarp_config *other) : impl(other->impl) - { - } - }; + size_t + llarp_config_size() + { + return sizeof(llarp_config); + } struct llarp_config * llarp_default_config() { - static llarp_config conf; + llarp_config *conf = new llarp_config(); #ifdef ANDROID // put andrid config overrides here #endif #ifdef IOS // put IOS config overrides here #endif - return &conf; + return conf; + } + + void + llarp_config_free(struct llarp_config *conf) + { + if(conf) + delete conf; } struct llarp_main * llarp_main_init_from_config(struct llarp_config *conf) { if(conf == nullptr) - conf = new llarp_config(llarp_default_config()); + return nullptr; llarp_main *m = new llarp_main(conf); if(m->ctx->Configure()) return m; diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index a02071e03..cea4d0b50 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -173,7 +173,7 @@ namespace llarp } Endpoint_ptr - Context::GetEndpointByName(const std::string & name) + Context::GetEndpointByName(const std::string &name) { auto itr = m_Endpoints.find(name); if(itr != m_Endpoints.end()) From 1b0d0575caa5730be0b45ed7cffc0d5153361977 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 08:12:08 -0400 Subject: [PATCH 05/17] try making it compile --- .../src/network/loki/lokinet/NetworkStateChangeReceiver.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/android/src/network/loki/lokinet/NetworkStateChangeReceiver.java b/android/src/network/loki/lokinet/NetworkStateChangeReceiver.java index d466e75c9..c4d7764fb 100644 --- a/android/src/network/loki/lokinet/NetworkStateChangeReceiver.java +++ b/android/src/network/loki/lokinet/NetworkStateChangeReceiver.java @@ -21,8 +21,6 @@ public class NetworkStateChangeReceiver extends BroadcastReceiver { boolean isConnected = activeNetworkInfo!=null && activeNetworkInfo.isConnected(); // https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html?hl=ru // boolean isWiFi = activeNetworkInfo!=null && (activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI); - - Lokinet_JNI.onNetworkStateChanged(isConnected); } catch (Throwable tr) { Log.d(TAG,"",tr); } From 6202baf5b10ba058572ae50ce71307a40fda3340 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 08:13:04 -0400 Subject: [PATCH 06/17] fix cmakelists.txt file paths --- jni/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jni/CMakeLists.txt b/jni/CMakeLists.txt index d6cf96b53..52db0a936 100644 --- a/jni/CMakeLists.txt +++ b/jni/CMakeLists.txt @@ -1,8 +1,8 @@ set(ANDROID_SRC - jni/lokinet_config.cpp - jni/lokinet_daemon.cpp - jni/lokinet_vnp.cpp + lokinet_config.cpp + lokinet_daemon.cpp + lokinet_vnp.cpp ) add_library(${ANDROID_LIB} SHARED ${ANDROID_SRC}) set_property(TARGET ${ANDROID_LIB} PROPERTY CXX_STANDARD 14) From 7823fd508494c3c0d5210fdc15020d0c0aef7b4a Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 08:13:40 -0400 Subject: [PATCH 07/17] typofix --- jni/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jni/CMakeLists.txt b/jni/CMakeLists.txt index 52db0a936..d265d4c87 100644 --- a/jni/CMakeLists.txt +++ b/jni/CMakeLists.txt @@ -2,7 +2,7 @@ set(ANDROID_SRC lokinet_config.cpp lokinet_daemon.cpp - lokinet_vnp.cpp + lokinet_vpn.cpp ) add_library(${ANDROID_LIB} SHARED ${ANDROID_SRC}) set_property(TARGET ${ANDROID_LIB} PROPERTY CXX_STANDARD 14) From 4c584dd2da953d619e4765b82bddb2ddc562ead3 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 08:16:57 -0400 Subject: [PATCH 08/17] pass template arguments in, fix typo --- jni/lokinet_jni_common.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jni/lokinet_jni_common.hpp b/jni/lokinet_jni_common.hpp index 79e8e0b13..77dfd1d98 100644 --- a/jni/lokinet_jni_common.hpp +++ b/jni/lokinet_jni_common.hpp @@ -22,7 +22,7 @@ VisitStringAsStringView(JNIEnv* env, jobject str, V visit) const jsize length = env->GetArrayLength(stringJbytes); const jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL); - T result = visit(llarp::string_view(bBytes, length)); + T result = visit(llarp::string_view(pBytes, length)); env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); env->DeleteLocalRef(stringJbytes); @@ -60,7 +60,7 @@ VisitObjectMemberStringAsStringView(JNIEnv* env, jobject self, jclass cl = env->GetObjectClass(self); jfieldID name = env->GetFieldID(cl, membername, "Ljava/lang/String;"); jobject str = env->GetObjectField(self, name); - return VisitStringAsStringView(env, str, v); + return VisitStringAsStringView< T, V >(env, str, v); } /// get object member int called membername From bcf792d772df1a11e6c4d9fe8749dbf267fbc08e Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 08:40:40 -0400 Subject: [PATCH 09/17] more fixups --- jni/lokinet_config.cpp | 2 +- jni/lokinet_daemon.cpp | 19 ++++++++++--------- jni/lokinet_jni_common.hpp | 23 ++++++++++++++++------- jni/lokinet_jni_vpnio.hpp | 21 +++++++++++++++------ jni/lokinet_vpn.cpp | 14 +++++--------- 5 files changed, 47 insertions(+), 32 deletions(-) diff --git a/jni/lokinet_config.cpp b/jni/lokinet_config.cpp index 8cf59e10b..9738eb382 100644 --- a/jni/lokinet_config.cpp +++ b/jni/lokinet_config.cpp @@ -24,7 +24,7 @@ extern "C Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv* env, jobject self, jstring fname) { - llarp_config* conf = FromObjectMember< llarp_config >(env, self, "impl"); + llarp_config* conf = GetImpl< llarp_config >(env, self); if(conf == nullptr) return JNI_FALSE; return VisitStringAsStringView< jboolean >( diff --git a/jni/lokinet_daemon.cpp b/jni/lokinet_daemon.cpp index 8a542bbcc..22f22f2cb 100644 --- a/jni/lokinet_daemon.cpp +++ b/jni/lokinet_daemon.cpp @@ -25,8 +25,8 @@ extern "C" Java_network_loki_lokinet_LokinetDaemon_Configure(JNIEnv *env, jobject self, jobject conf) { - llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); - llarp_config *config = FromObjectMember< llarp_config >(env, conf, "impl"); + llarp_main *ptr = GetImpl< llarp_main >(env, self); + llarp_config *config = GetImpl< llarp_config >(env, conf); if(ptr == nullptr || config == nullptr) return JNI_FALSE; if(llarp_main_configure(ptr, config)) @@ -38,7 +38,7 @@ extern "C" Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv *env, jobject self) { static llarp_main_runtime_opts opts; - llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); + llarp_main *ptr = GetImpl< llarp_main >(env, self); if(ptr == nullptr) return -1; return llarp_main_run(ptr, opts); @@ -47,7 +47,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_network_loki_lokinet_LokinetDaemon_IsRunning(JNIEnv *env, jobject self) { - llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); + llarp_main *ptr = GetImpl< llarp_main >(env, self); return (ptr != nullptr && llarp_main_is_running(ptr)) ? JNI_TRUE : JNI_FALSE; } @@ -55,7 +55,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_network_loki_lokinet_LokinetDaemon_Stop(JNIEnv *env, jobject self) { - llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); + llarp_main *ptr = GetImpl< llarp_main >(env, self); if(ptr == nullptr) return JNI_FALSE; if(not llarp_main_is_running(ptr)) @@ -68,13 +68,14 @@ extern "C" Java_network_loki_lokinet_LokinetDaemon_InjectVPN(JNIEnv *env, jobject self, jobject vpn) { - llarp_main *ptr = FromObjectMember< llarp_main >(env, self, "impl"); - lokinet_jni_vpnio *impl = - FromObjectMember< lokinet_jni_vpnio >(env, vpn, "impl"); + llarp_main *ptr = GetImpl< llarp_main >(env, self); + lokinet_jni_vpnio *impl = GetImpl< lokinet_jni_vpnio >(env, vpn); if(ptr == nullptr || impl == nullptr) return JNI_FALSE; + if(impl->info.netmask == 0) + return JNI_FALSE; if(not impl->Init(ptr)) - return JNI_FASE; + return JNI_FALSE; return llarp_main_inject_default_vpn(ptr, &impl->io, impl->info) ? JNI_TRUE : JNI_FALSE; diff --git a/jni/lokinet_jni_common.hpp b/jni/lokinet_jni_common.hpp index 77dfd1d98..a70435e42 100644 --- a/jni/lokinet_jni_common.hpp +++ b/jni/lokinet_jni_common.hpp @@ -6,6 +6,7 @@ #include /// visit string as native bytes +/// jvm uses some unholy encoding internally so we convert it to utf-8 template < typename T, typename V > static T VisitStringAsStringView(JNIEnv* env, jobject str, V visit) @@ -19,10 +20,11 @@ VisitStringAsStringView(JNIEnv* env, jobject str, V visit) (jbyteArray)env->CallObjectMethod(str, getBytes, charsetName); env->DeleteLocalRef(charsetName); - const jsize length = env->GetArrayLength(stringJbytes); - const jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL); + const size_t length = env->GetArrayLength(stringJbytes); + jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL); - T result = visit(llarp::string_view(pBytes, length)); + T result = + visit(llarp::string_view(static_cast< const char* >(pBytes), length)); env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); env->DeleteLocalRef(stringJbytes); @@ -65,13 +67,20 @@ VisitObjectMemberStringAsStringView(JNIEnv* env, jobject self, /// get object member int called membername template < typename Int_t > -void -GetObjectMemberAsInt(JNIEnv* env, jobject self, const char* membername, - Int_t& result) +Int_t +GetObjectMemberAsInt(JNIEnv* env, jobject self, const char* membername) { jclass cl = env->GetObjectClass(self); jfieldID name = env->GetFieldID(cl, membername, "I"); - result = env->GetIntField(self, name); + return env->GetIntField(self, name); +} + +/// get implementation on jni type +template < typename T > +T* +GetImpl(JNIEnv* env, jobject self) +{ + return FromObjectMember< T >(env, self, "impl"); } #endif \ No newline at end of file diff --git a/jni/lokinet_jni_vpnio.hpp b/jni/lokinet_jni_vpnio.hpp index f0b981cc5..30ca9f9b6 100644 --- a/jni/lokinet_jni_vpnio.hpp +++ b/jni/lokinet_jni_vpnio.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace lokinet { @@ -27,7 +28,7 @@ namespace lokinet Closed() { if(closeWaiter) - closeWaiter->get_future().set_value(); + closeWaiter->set_value(); } virtual void @@ -57,19 +58,27 @@ namespace lokinet bool Init(llarp_main *ptr) { + if(Ready()) + return false; return llarp_vpn_io_init(ptr, &io); } + bool + Ready() const + { + return io.impl != nullptr; + } + void Close() { - if(io.impl == nullptr) + if(not Ready()) return; if(closeWaiter) return; - closerWaiter = std::make_unique< std::promise< void > >(); + closeWaiter = std::make_unique< std::promise< void > >(); llarp_vpn_io_close_async(&io); - closeWaiter->wait(); + closeWaiter->get_future().wait(); closeWaiter.reset(); io.impl = nullptr; } @@ -89,7 +98,7 @@ namespace lokinet ssize_t ReadPacket(void *dst, size_t len) { - if(io.impl == nullptr) + if(not Ready()) return -1; unsigned char *buf = (unsigned char *)dst; return llarp_vpn_io_readpkt(Reader(), buf, len); @@ -98,7 +107,7 @@ namespace lokinet bool WritePacket(void *pkt, size_t len) { - if(io.impl == nullptr) + if(not Ready()) return false; unsigned char *buf = (unsigned char *)pkt; return llarp_vpn_io_writepkt(Writer(), buf, len); diff --git a/jni/lokinet_vpn.cpp b/jni/lokinet_vpn.cpp index 8c8d39c1e..6febc606c 100644 --- a/jni/lokinet_vpn.cpp +++ b/jni/lokinet_vpn.cpp @@ -29,8 +29,7 @@ extern "C" JNIEXPORT void JNICALL Java_network_loki_lokinet_LokinetVPN_Stop(JNIEnv *env, jobject self) { - lokinet_jni_vpnio *vpn = - FromObjectMember< lokinet_jni_vpnio >(env, self, "impl"); + lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self); if(vpn) { vpn->Close(); @@ -41,8 +40,7 @@ extern "C" Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv *env, jobject self, jobject pkt) { - lokinet_jni_vpnio *vpn = - FromObjectMember< lokinet_jni_vpnio >(env, self, "impl"); + lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self); if(vpn == nullptr) return -1; void *pktbuf = env->GetDirectBufferAddress(pkt); @@ -56,8 +54,7 @@ extern "C" Java_network_loki_lokinet_LokinetVPN_WritePkt(JNIEnv *env, jobject self, jobject pkt) { - lokinet_jni_vpnio *vpn = - FromObjectMember< lokinet_jni_vpnio >(env, self, "impl"); + lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self); if(vpn == nullptr) return false; void *pktbuf = env->GetDirectBufferAddress(pkt); @@ -71,8 +68,7 @@ extern "C" Java_network_loki_lokinet_LokinetVPN_SetInfo(JNIEnv *env, jobject self, jobject info) { - lokinet_jni_vpnio *vpn = - FromObjectMember< lokinet_jni_vpnio >(env, self, "impl"); + lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self); if(vpn == nullptr) return; VisitObjectMemberStringAsStringView< bool >( @@ -85,6 +81,6 @@ extern "C" vpn->SetIfName(val); return true; }); - GetObjectMemberAsInt(env, info, "netmask", vpn->info.netmask); + vpn->info.netmask = GetObjectMemberAsInt< uint8_t >(env, info, "netmask"); } } \ No newline at end of file From 9a49c77647c3402ee9f7f7b58c9ac2fa67b5eb5b Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 08:41:34 -0400 Subject: [PATCH 10/17] cast --- jni/lokinet_jni_common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jni/lokinet_jni_common.hpp b/jni/lokinet_jni_common.hpp index a70435e42..d2753a6af 100644 --- a/jni/lokinet_jni_common.hpp +++ b/jni/lokinet_jni_common.hpp @@ -24,7 +24,7 @@ VisitStringAsStringView(JNIEnv* env, jobject str, V visit) jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL); T result = - visit(llarp::string_view(static_cast< const char* >(pBytes), length)); + visit(llarp::string_view((const char*)pBytes, length)); env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); env->DeleteLocalRef(stringJbytes); From 043bf505bcb15e54bfcda910cfff854553254fa0 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 08:42:05 -0400 Subject: [PATCH 11/17] typofix --- jni/lokinet_config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jni/lokinet_config.cpp b/jni/lokinet_config.cpp index 9738eb382..a5624f905 100644 --- a/jni/lokinet_config.cpp +++ b/jni/lokinet_config.cpp @@ -2,7 +2,7 @@ #include #include "lokinet_jni_common.hpp" -extern "C +extern "C" { JNIEXPORT jobject JNICALL Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv* env, jclass* c) From d80633a975c42f750ee9ceb59a01d6ed1d7b2ec4 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 08:43:25 -0400 Subject: [PATCH 12/17] typo fix --- jni/lokinet_config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jni/lokinet_config.cpp b/jni/lokinet_config.cpp index a5624f905..48db9be7f 100644 --- a/jni/lokinet_config.cpp +++ b/jni/lokinet_config.cpp @@ -5,7 +5,7 @@ extern "C" { JNIEXPORT jobject JNICALL - Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv* env, jclass* c) + Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv* env, jclass) { llarp_config* conf = llarp_default_config(); if(conf == nullptr) @@ -14,7 +14,7 @@ extern "C" } JNIEXPORT void JNICALL - Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv* env, jclass c, + Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv* env, jclass, jobject buf) { llarp_config_free(FromBuffer< llarp_config >(env, buf)); From 58a25602f5e806f99dd9af77f2432139ae8d3ffb Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 09:08:38 -0400 Subject: [PATCH 13/17] more fixes, implemenmt missing functions --- include/llarp.hpp | 9 +++++ jni/lokinet_config.cpp | 3 +- jni/lokinet_daemon.cpp | 2 +- jni/lokinet_jni_common.hpp | 3 +- llarp/context.cpp | 59 ++++++++++++++++++++++++++++++++- llarp/router/abstractrouter.hpp | 3 ++ llarp/router/router.cpp | 6 ++++ llarp/router/router.hpp | 3 ++ 8 files changed, 82 insertions(+), 6 deletions(-) diff --git a/include/llarp.hpp b/include/llarp.hpp index a630708e2..5f22343e4 100644 --- a/include/llarp.hpp +++ b/include/llarp.hpp @@ -87,6 +87,14 @@ namespace llarp bool Configure(); + /// close async + void + Close(); + + /// wait until closed and done + void + Wait(); + /// call a function in logic thread /// return true if queued for calling /// return false if not queued for calling @@ -117,6 +125,7 @@ namespace llarp std::string configfile; std::string pidfile; + std::unique_ptr< std::promise< void > > closeWaiter; }; } // namespace llarp diff --git a/jni/lokinet_config.cpp b/jni/lokinet_config.cpp index 48db9be7f..c73cdee3c 100644 --- a/jni/lokinet_config.cpp +++ b/jni/lokinet_config.cpp @@ -14,8 +14,7 @@ extern "C" } JNIEXPORT void JNICALL - Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv* env, jclass, - jobject buf) + Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv* env, jclass, jobject buf) { llarp_config_free(FromBuffer< llarp_config >(env, buf)); } diff --git a/jni/lokinet_daemon.cpp b/jni/lokinet_daemon.cpp index 22f22f2cb..8db0324fb 100644 --- a/jni/lokinet_daemon.cpp +++ b/jni/lokinet_daemon.cpp @@ -31,7 +31,7 @@ extern "C" return JNI_FALSE; if(llarp_main_configure(ptr, config)) return JNI_TRUE; - return JNI_FALSE; + return llarp_main_setup(ptr) == 0 ? JNI_TRUE : JNI_FALSE; } JNIEXPORT jint JNICALL diff --git a/jni/lokinet_jni_common.hpp b/jni/lokinet_jni_common.hpp index d2753a6af..4ddea9095 100644 --- a/jni/lokinet_jni_common.hpp +++ b/jni/lokinet_jni_common.hpp @@ -23,8 +23,7 @@ VisitStringAsStringView(JNIEnv* env, jobject str, V visit) const size_t length = env->GetArrayLength(stringJbytes); jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL); - T result = - visit(llarp::string_view((const char*)pBytes, length)); + T result = visit(llarp::string_view((const char*)pBytes, length)); env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); env->DeleteLocalRef(stringJbytes); diff --git a/llarp/context.cpp b/llarp/context.cpp index 2c7197669..e32f27cc5 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -240,10 +240,34 @@ __ ___ ____ _ _ ___ _ _ ____ // run net io thread llarp::LogInfo("running mainloop"); llarp_ev_loop_run_single_process(mainloop, logic); - // waits for router graceful stop + if(closeWaiter) + { + // inform promise if called by Stop + closeWaiter->set_value(); + } return 0; } + void + Context::Close() + { + /// already closing + if(closeWaiter) + return; + if(CallSafe(std::bind(&Context::HandleSignal, this, SIGINT))) + closeWaiter = std::make_unique< std::promise< void > >(); + } + + void + Context::Wait() + { + if(closeWaiter) + { + closeWaiter->get_future().wait(); + closeWaiter.reset(); + } + } + bool Context::WritePIDFile() const { @@ -433,6 +457,14 @@ extern "C" return nullptr; } + bool + llarp_config_read_file(struct llarp_config *conf, const char *fname) + { + if(conf == nullptr) + return false; + return conf->impl.Load(fname); + } + bool llarp_config_load_file(const char *fname, struct llarp_config **conf) { @@ -565,6 +597,31 @@ extern "C" { return "default"; } + + void + llarp_main_stop(struct llarp_main *ptr) + { + if(ptr == nullptr) + return; + ptr->ctx->Close(); + ptr->ctx->Wait(); + } + + bool + llarp_main_configure(struct llarp_main *ptr, struct llarp_config *conf) + { + if(ptr == nullptr || conf == nullptr) + return false; + // give new config + ptr->ctx->config.reset(new llarp::Config(conf->impl)); + return ptr->ctx->Configure(); + } + + bool + llarp_main_is_running(struct llarp_main *ptr) + { + return ptr && ptr->ctx->router && ptr->ctx->router->IsRunning(); + } } llarp_main::llarp_main(llarp_config *conf) diff --git a/llarp/router/abstractrouter.hpp b/llarp/router/abstractrouter.hpp index 08fbf449e..556ad9469 100644 --- a/llarp/router/abstractrouter.hpp +++ b/llarp/router/abstractrouter.hpp @@ -132,6 +132,9 @@ namespace llarp virtual bool Run() = 0; + virtual bool + IsRunning() const = 0; + /// stop running the router logic gracefully virtual void Stop() = 0; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 5e9f7fd58..21c48ebc3 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -1036,6 +1036,12 @@ namespace llarp return _running; } + bool + Router::IsRunning() const + { + return _running; + } + llarp_time_t Router::Uptime() const { diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index e2d94536e..4e85e5fe0 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -310,6 +310,9 @@ namespace llarp bool InitServiceNode(); + bool + IsRunning() const override; + /// return true if we are running in service node mode bool IsServiceNode() const; From 9dd73dad46bba53275aad7a4bc04c7a2ef378133 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 09:09:42 -0400 Subject: [PATCH 14/17] close -> closeasync --- include/llarp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/llarp.hpp b/include/llarp.hpp index 5f22343e4..ab0d87936 100644 --- a/include/llarp.hpp +++ b/include/llarp.hpp @@ -89,7 +89,7 @@ namespace llarp /// close async void - Close(); + CloseAsync(); /// wait until closed and done void From cdb5610d90c087bc466215db080e227d3cf8e358 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 09:10:48 -0400 Subject: [PATCH 15/17] close async --- llarp/context.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llarp/context.cpp b/llarp/context.cpp index e32f27cc5..061bdec22 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -249,7 +249,7 @@ __ ___ ____ _ _ ___ _ _ ____ } void - Context::Close() + Context::CloseAsync() { /// already closing if(closeWaiter) @@ -603,7 +603,7 @@ extern "C" { if(ptr == nullptr) return; - ptr->ctx->Close(); + ptr->ctx->CloseAsync(); ptr->ctx->Wait(); } From 2425c2ba03988dbd2f3a4afa4de80537af2fd257 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 9 Oct 2019 09:21:41 -0400 Subject: [PATCH 16/17] update comment --- llarp/context.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llarp/context.cpp b/llarp/context.cpp index 061bdec22..7f88b6107 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -242,7 +242,7 @@ __ ___ ____ _ _ ___ _ _ ____ llarp_ev_loop_run_single_process(mainloop, logic); if(closeWaiter) { - // inform promise if called by Stop + // inform promise if called by CloseAsync closeWaiter->set_value(); } return 0; @@ -254,7 +254,7 @@ __ ___ ____ _ _ ___ _ _ ____ /// already closing if(closeWaiter) return; - if(CallSafe(std::bind(&Context::HandleSignal, this, SIGINT))) + if(CallSafe(std::bind(&Context::HandleSignal, this, SIGTERM))) closeWaiter = std::make_unique< std::promise< void > >(); } From 1fbafab9b2286e856c07751f2a548eade4d86d47 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 9 Oct 2019 09:25:29 -0400 Subject: [PATCH 17/17] remove unused file --- jni/lokinet_android.cpp | 188 ---------------------------------------- 1 file changed, 188 deletions(-) delete mode 100644 jni/lokinet_android.cpp diff --git a/jni/lokinet_android.cpp b/jni/lokinet_android.cpp deleted file mode 100644 index 4c4cc0ac4..000000000 --- a/jni/lokinet_android.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -struct AndroidMain -{ - llarp_main* m_impl = nullptr; - std::thread* m_thread = nullptr; - std::string configFile; - - /// set configuration and ensure files - bool - Configure(const char* conf, const char* basedir) - { - configFile = conf; - return llarp_ensure_config(conf, basedir, false, false); - } - - /// reload config on runtime - bool - ReloadConfig() - { - if(!m_impl) - return false; - llarp_main_signal(m_impl, SIGHUP); - return true; - } - - /// start daemon thread - bool - Start() - { - if(m_impl || m_thread) - return true; - m_impl = llarp_main_default_init(); - if(m_impl == nullptr) - return false; - if(llarp_main_setup(m_impl)) - { - llarp_main_free(m_impl); - m_impl = nullptr; - return false; - } - m_thread = new std::thread(std::bind(&AndroidMain::Run, this)); - return true; - } - - /// return true if we are running - bool - Running() const - { - return m_impl != nullptr && m_thread != nullptr; - } - - /// blocking run - void - Run() - { - llarp_main_runtime_opts opts; - if(llarp_main_run(m_impl, opts)) - { - // on error - llarp::LogError("daemon run fail"); - llarp_main* ptr = m_impl; - m_impl = nullptr; - llarp_main_signal(ptr, SIGINT); - llarp_main_free(ptr); - } - } - - void - SetVPN_FD(int rfd, int wfd) - { - (void)rfd; - (void)wfd; - // if(m_impl) - // llarp_main_inject_vpn_fd(m_impl, rfd, wfd); - } - - /// stop daemon thread - void - Stop() - { - if(m_impl) - llarp_main_signal(m_impl, SIGINT); - m_thread->join(); - delete m_thread; - m_thread = nullptr; - if(m_impl) - llarp_main_free(m_impl); - m_impl = nullptr; - } - - typedef std::unique_ptr< AndroidMain > Ptr; -}; - -static AndroidMain::Ptr daemon_ptr(new AndroidMain()); - -extern "C" -{ - JNIEXPORT jstring JNICALL - Java_network_loki_lokinet_Lokinet_1JNI_getABICompiledWith(JNIEnv* env, jclass) - { - // TODO: fixme - return env->NewStringUTF("android"); - } - - JNIEXPORT jstring JNICALL - Java_network_loki_lokinet_Lokinet_1JNI_startLokinet(JNIEnv* env, jclass, - jstring configfile) - { - if(daemon_ptr->Running()) - return env->NewStringUTF("already running"); - std::string conf; - fs::path basepath; - { - const char* nativeString = env->GetStringUTFChars(configfile, JNI_FALSE); - conf += std::string(nativeString); - env->ReleaseStringUTFChars(configfile, nativeString); - basepath = fs::path(conf).parent_path(); - } - if(daemon_ptr->Configure(conf.c_str(), basepath.string().c_str())) - { - if(daemon_ptr->Start()) - return env->NewStringUTF("ok"); - else - return env->NewStringUTF("failed to start daemon"); - } - else - return env->NewStringUTF("failed to configure daemon"); - } - - JNIEXPORT void JNICALL - Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet(JNIEnv*, jclass) - { - if(daemon_ptr->Running()) - { - daemon_ptr->Stop(); - } - } - - JNIEXPORT void JNICALL - Java_network_loki_lokinet_Lokinet_1JNI_setVPNFileDescriptor(JNIEnv*, jclass, - jint rfd, - jint wfd) - { - daemon_ptr->SetVPN_FD(rfd, wfd); - } - - JNIEXPORT jstring JNICALL - Java_network_loki_lokinet_Lokinet_1JNI_getIfAddr(JNIEnv* env, jclass) - { - return env->NewStringUTF(""); - } - - JNIEXPORT jint JNICALL - Java_network_loki_lokinet_Lokinet_1JNI_getIfRange(JNIEnv*, jclass) - { - return -1; - } - - JNIEXPORT void JNICALL - Java_network_loki_lokinet_Lokinet_1JNI_onNetworkStateChanged( - JNIEnv*, jclass, jboolean isConnected) - { - if(isConnected) - { - if(!daemon_ptr->Running()) - { - if(!daemon_ptr->Start()) - { - // TODO: do some kind of callback here - } - } - } - else if(daemon_ptr->Running()) - { - daemon_ptr->Stop(); - } - } -}