mirror of https://github.com/oxen-io/lokinet
Merge pull request #869 from majestrate/vpn-api-2019-10-03
android jni shim and vpn api for mobilepull/872/head
commit
175e9f1324
@ -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");
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
|
||||
set(ANDROID_SRC
|
||||
lokinet_config.cpp
|
||||
lokinet_daemon.cpp
|
||||
lokinet_vpn.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})
|
@ -1,237 +0,0 @@
|
||||
#include <llarp.h>
|
||||
#include <config/config.hpp>
|
||||
#include <util/fs.hpp>
|
||||
#include <llarp.hpp>
|
||||
#include <router/router.hpp>
|
||||
|
||||
#include <jni.h>
|
||||
#include <signal.h>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
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_init(configFile.c_str(), true);
|
||||
if(m_impl == nullptr)
|
||||
return false;
|
||||
if(llarp_main_setup(m_impl, false))
|
||||
{
|
||||
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()
|
||||
{
|
||||
if(llarp_main_run(m_impl))
|
||||
{
|
||||
// on error
|
||||
llarp::LogError("daemon run fail");
|
||||
llarp_main* ptr = m_impl;
|
||||
m_impl = nullptr;
|
||||
llarp_main_signal(ptr, SIGINT);
|
||||
llarp_main_free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
(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)
|
||||
{
|
||||
if(daemon_ptr)
|
||||
return env->NewStringUTF(daemon_ptr->GetIfAddr());
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
#include "network_loki_lokinet_LokinetConfig.h"
|
||||
#include <llarp.hpp>
|
||||
#include "lokinet_jni_common.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv* env, jclass)
|
||||
{
|
||||
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, 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 = GetImpl< llarp_config >(env, self);
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
#include "network_loki_lokinet_LokinetDaemon.h"
|
||||
#include "lokinet_jni_common.hpp"
|
||||
#include "lokinet_jni_vpnio.hpp"
|
||||
#include <llarp.h>
|
||||
|
||||
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 = 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))
|
||||
return JNI_TRUE;
|
||||
return llarp_main_setup(ptr) == 0 ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv *env, jobject self)
|
||||
{
|
||||
static llarp_main_runtime_opts opts;
|
||||
llarp_main *ptr = GetImpl< llarp_main >(env, self);
|
||||
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 = GetImpl< llarp_main >(env, self);
|
||||
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 = GetImpl< llarp_main >(env, self);
|
||||
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 = 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_FALSE;
|
||||
return llarp_main_inject_default_vpn(ptr, &impl->io, impl->info)
|
||||
? JNI_TRUE
|
||||
: JNI_FALSE;
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
#ifndef LOKINET_JNI_COMMON_HPP
|
||||
#define LOKINET_JNI_COMMON_HPP
|
||||
|
||||
#include <jni.h>
|
||||
#include <util/string_view.hpp>
|
||||
#include <functional>
|
||||
|
||||
/// 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)
|
||||
{
|
||||
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 size_t length = env->GetArrayLength(stringJbytes);
|
||||
jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
|
||||
|
||||
T result = visit(llarp::string_view((const char*)pBytes, 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< T, V >(env, str, v);
|
||||
}
|
||||
|
||||
/// get object member int called membername
|
||||
template < typename Int_t >
|
||||
Int_t
|
||||
GetObjectMemberAsInt(JNIEnv* env, jobject self, const char* membername)
|
||||
{
|
||||
jclass cl = env->GetObjectClass(self);
|
||||
jfieldID name = env->GetFieldID(cl, membername, "I");
|
||||
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
|
@ -0,0 +1,150 @@
|
||||
#ifndef LOKINET_JNI_VPNIO_HPP
|
||||
#define LOKINET_JNI_VPNIO_HPP
|
||||
|
||||
#include <llarp.h>
|
||||
#include <memory>
|
||||
#include <future>
|
||||
#include <util/string_view.hpp>
|
||||
#include <algorithm>
|
||||
#include <jni.h>
|
||||
|
||||
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->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)
|
||||
{
|
||||
if(Ready())
|
||||
return false;
|
||||
return llarp_vpn_io_init(ptr, &io);
|
||||
}
|
||||
|
||||
bool
|
||||
Ready() const
|
||||
{
|
||||
return io.impl != nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Close()
|
||||
{
|
||||
if(not Ready())
|
||||
return;
|
||||
if(closeWaiter)
|
||||
return;
|
||||
closeWaiter = std::make_unique< std::promise< void > >();
|
||||
llarp_vpn_io_close_async(&io);
|
||||
closeWaiter->get_future().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(not Ready())
|
||||
return -1;
|
||||
unsigned char *buf = (unsigned char *)dst;
|
||||
return llarp_vpn_io_readpkt(Reader(), buf, len);
|
||||
}
|
||||
|
||||
bool
|
||||
WritePacket(void *pkt, size_t len)
|
||||
{
|
||||
if(not Ready())
|
||||
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
|
@ -0,0 +1,86 @@
|
||||
#include "network_loki_lokinet_LokinetVPN.h"
|
||||
#include "lokinet_jni_vpnio.hpp"
|
||||
#include "lokinet_jni_common.hpp"
|
||||
#include <net/ip.hpp>
|
||||
|
||||
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 = GetImpl< lokinet_jni_vpnio >(env, self);
|
||||
if(vpn)
|
||||
{
|
||||
vpn->Close();
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv *env, jobject self,
|
||||
jobject pkt)
|
||||
{
|
||||
lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self);
|
||||
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 = GetImpl< lokinet_jni_vpnio >(env, self);
|
||||
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 = GetImpl< lokinet_jni_vpnio >(env, self);
|
||||
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;
|
||||
});
|
||||
vpn->info.netmask = GetObjectMemberAsInt< uint8_t >(env, info, "netmask");
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* 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
|
@ -0,0 +1,70 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* 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
|
@ -0,0 +1,69 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* 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
|
@ -0,0 +1,14 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* 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
|
@ -0,0 +1,31 @@
|
||||
#include <ev/vpnio.hpp>
|
||||
#include <llarp.hpp>
|
||||
#include <router/abstractrouter.hpp>
|
||||
#include <util/thread/logic.hpp>
|
||||
|
||||
void
|
||||
llarp_vpn_io_impl::AsyncClose()
|
||||
{
|
||||
reader.queue.disable();
|
||||
writer.queue.disable();
|
||||
CallSafe(std::bind(&llarp_vpn_io_impl::Expunge, this));
|
||||
}
|
||||
|
||||
void
|
||||
llarp_vpn_io_impl::CallSafe(std::function< void(void) > f)
|
||||
{
|
||||
llarp::Context* ctx = llarp::Context::Get(ptr);
|
||||
if(ctx && ctx->CallSafe(f))
|
||||
return;
|
||||
else if(ctx == nullptr || ctx->logic == nullptr)
|
||||
f();
|
||||
}
|
||||
|
||||
void
|
||||
llarp_vpn_io_impl::Expunge()
|
||||
{
|
||||
parent->impl = nullptr;
|
||||
if(parent->closed)
|
||||
parent->closed(parent);
|
||||
delete this;
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
#ifndef LLARP_EV_VPNIO_HPP
|
||||
#define LLARP_EV_VPNIO_HPP
|
||||
#include <net/ip.hpp>
|
||||
#include <util/thread/queue.hpp>
|
||||
#include <functional>
|
||||
|
||||
struct llarp_main;
|
||||
struct llarp_vpn_io;
|
||||
|
||||
struct llarp_vpn_pkt_queue
|
||||
{
|
||||
using Packet_t = llarp::net::IPPacket;
|
||||
llarp::thread::Queue< Packet_t > queue;
|
||||
|
||||
llarp_vpn_pkt_queue() : queue(1024){};
|
||||
~llarp_vpn_pkt_queue() = default;
|
||||
};
|
||||
|
||||
struct llarp_vpn_pkt_writer : public llarp_vpn_pkt_queue
|
||||
{
|
||||
};
|
||||
|
||||
struct llarp_vpn_pkt_reader : public llarp_vpn_pkt_queue
|
||||
{
|
||||
};
|
||||
|
||||
struct llarp_vpn_io_impl
|
||||
{
|
||||
llarp_vpn_io_impl(llarp_main* p, llarp_vpn_io* io) : ptr(p), parent(io)
|
||||
{
|
||||
}
|
||||
~llarp_vpn_io_impl() = default;
|
||||
|
||||
llarp_main* ptr;
|
||||
llarp_vpn_io* parent;
|
||||
|
||||
llarp_vpn_pkt_writer writer;
|
||||
llarp_vpn_pkt_reader reader;
|
||||
|
||||
void
|
||||
AsyncClose();
|
||||
|
||||
private:
|
||||
void
|
||||
CallSafe(std::function< void(void) > f);
|
||||
|
||||
void
|
||||
Expunge();
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue