Browse Source

Change jni to build executable. Clone with minimal changes DaemonUnix into DaemonAndroid

pull/1160/head
unlnown542a 7 years ago
parent
commit
f11266972e
  1. 8
      android/jni/Android.mk
  2. 8
      android/jni/Application.mk
  3. 304
      android/jni/DaemonAndroid.cpp
  4. 99
      android/jni/DaemonAndroid.h
  5. 66
      android/jni/i2pd_android.cpp
  6. 33
      android/jni/org_purplei2p_i2pd_I2PD_JNI.h

8
android/jni/Android.mk

@ -12,15 +12,15 @@ LOCAL_STATIC_LIBRARIES := \
miniupnpc miniupnpc
LOCAL_LDLIBS := -lz LOCAL_LDLIBS := -lz
LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp $(IFADDRS_PATH)/ifaddrs.c \ LOCAL_SRC_FILES := DaemonAndroid.cpp $(IFADDRS_PATH)/ifaddrs.c \
$(wildcard $(LIB_SRC_PATH)/*.cpp)\ $(wildcard $(LIB_SRC_PATH)/*.cpp)\
$(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp)\ $(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp)\
$(DAEMON_SRC_PATH)/Daemon.cpp \ $(DAEMON_SRC_PATH)/Daemon.cpp \
$(DAEMON_SRC_PATH)/UPnP.cpp \ $(DAEMON_SRC_PATH)/UPnP.cpp \
$(DAEMON_SRC_PATH)/HTTPServer.cpp \ $(DAEMON_SRC_PATH)/HTTPServer.cpp \
$(DAEMON_SRC_PATH)/I2PControl.cpp $(DAEMON_SRC_PATH)/I2PControl.cpp \
$(DAEMON_SRC_PATH)/i2pd.cpp
include $(BUILD_SHARED_LIBRARY) include $(BUILD_EXECUTABLE)
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)

8
android/jni/Application.mk

@ -9,12 +9,14 @@ APP_PLATFORM := android-14
# http://stackoverflow.com/a/21386866/529442 http://stackoverflow.com/a/15616255/529442 to enable c++11 support in Eclipse # http://stackoverflow.com/a/21386866/529442 http://stackoverflow.com/a/15616255/529442 to enable c++11 support in Eclipse
NDK_TOOLCHAIN_VERSION := 4.9 NDK_TOOLCHAIN_VERSION := 4.9
# APP_STL := stlport_shared --> does not seem to contain C++11 features # APP_STL := stlport_shared --> does not seem to contain C++11 features
APP_STL := gnustl_shared #APP_STL := gnustl_shared
APP_STL := gnustl_static
# Enable c++11 extensions in source code # Enable c++11 extensions in source code
APP_CPPFLAGS += -std=c++11 APP_CPPFLAGS += -std=c++11 -fvisibility=default -fPIE
APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP
APP_LDFLAGS += -rdynamic -fPIE -pie
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
APP_CPPFLAGS += -DANDROID_ARM7A APP_CPPFLAGS += -DANDROID_ARM7A
endif endif
@ -26,7 +28,7 @@ APP_OPTIM := debug
# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git # git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
# git clone https://github.com/PurpleI2P/android-ifaddrs.git # git clone https://github.com/PurpleI2P/android-ifaddrs.git
# change to your own # change to your own
I2PD_LIBS_PATH = /path/to/libraries I2PD_LIBS_PATH = /home/u/build/i2p/daemon/static.libs
BOOST_PATH = $(I2PD_LIBS_PATH)/Boost-for-Android-Prebuilt BOOST_PATH = $(I2PD_LIBS_PATH)/Boost-for-Android-Prebuilt
OPENSSL_PATH = $(I2PD_LIBS_PATH)/OpenSSL-for-Android-Prebuilt OPENSSL_PATH = $(I2PD_LIBS_PATH)/OpenSSL-for-Android-Prebuilt
MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt

304
android/jni/DaemonAndroid.cpp

@ -1,193 +1,193 @@
#include "DaemonAndroid.h" #include "DaemonAndroid.h"
#include "Daemon.h"
#include <iostream>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception_ptr.hpp>
#include <exception>
//#include "mainwindow.h"
namespace i2p #ifndef _WIN32
{
namespace android #include <signal.h>
#include <stdlib.h>
#include <thread>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include "Config.h"
#include "FS.h"
#include "Log.h"
#include "Tunnel.h"
#include "RouterContext.h"
#include "ClientContext.h"
void handle_signal(int sig)
{ {
/* Worker::Worker (DaemonAndroidImpl& daemon): switch (sig)
m_Daemon (daemon) {
{ case SIGHUP:
LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening tunnel configuration...");
i2p::client::context.ReloadConfig();
break;
case SIGUSR1:
LogPrint(eLogInfo, "Daemon: Got SIGUSR1, reopening logs...");
i2p::log::Logger().Reopen ();
break;
case SIGINT:
if (i2p::context.AcceptsTunnels () && !Daemon.gracefulShutdownInterval)
{
i2p::context.SetAcceptsTunnels (false);
Daemon.gracefulShutdownInterval = 10*60; // 10 minutes
LogPrint(eLogInfo, "Graceful shutdown after ", Daemon.gracefulShutdownInterval, " seconds");
}
else
Daemon.running = 0;
break;
case SIGABRT:
case SIGTERM:
Daemon.running = 0; // Exit loop
break;
case SIGPIPE:
LogPrint(eLogInfo, "SIGPIPE received");
break;
} }
}
void Worker::startDaemon() namespace i2p
{
namespace util
{ {
Log.d(TAG"Performing daemon start..."); bool DaemonAndroid::start()
m_Daemon.start();
Log.d(TAG"Daemon started.");
emit resultReady();
}
void Worker::restartDaemon()
{ {
Log.d(TAG"Performing daemon restart..."); if (isDaemon)
m_Daemon.restart(); {
Log.d(TAG"Daemon restarted."); pid_t pid;
emit resultReady(); pid = fork();
} if (pid > 0) // parent
void Worker::stopDaemon() { ::exit (EXIT_SUCCESS);
Log.d(TAG"Performing daemon stop...");
m_Daemon.stop();
Log.d(TAG"Daemon stopped.");
emit resultReady();
}
Controller::Controller(DaemonAndroidImpl& daemon): if (pid < 0) // error
m_Daemon (daemon)
{ {
Worker *worker = new Worker (m_Daemon); LogPrint(eLogError, "Daemon: could not fork: ", strerror(errno));
worker->moveToThread(&workerThread); return false;
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::startDaemon, worker, &Worker::startDaemon);
connect(this, &Controller::stopDaemon, worker, &Worker::stopDaemon);
connect(this, &Controller::restartDaemon, worker, &Worker::restartDaemon);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
} }
Controller::~Controller()
{ // child
Log.d(TAG"Closing and waiting for daemon worker thread..."); umask(S_IWGRP | S_IRWXO); // 0027
workerThread.quit(); int sid = setsid();
workerThread.wait(); if (sid < 0)
Log.d(TAG"Waiting for daemon worker thread finished.");
if(m_Daemon.isRunning())
{ {
Log.d(TAG"Stopping the daemon..."); LogPrint(eLogError, "Daemon: could not create process group.");
m_Daemon.stop(); return false;
Log.d(TAG"Stopped the daemon.");
}
} }
*/ std::string d = i2p::fs::GetDataDir();
DaemonAndroidImpl::DaemonAndroidImpl () if (chdir(d.c_str()) != 0)
//:
/*mutex(nullptr), */
//m_IsRunning(false),
//m_RunningChangedCallback(nullptr)
{ {
LogPrint(eLogError, "Daemon: could not chdir: ", strerror(errno));
return false;
} }
DaemonAndroidImpl::~DaemonAndroidImpl () // point std{in,out,err} descriptors to /dev/null
{ freopen("/dev/null", "r", stdin);
//delete mutex; freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
} }
bool DaemonAndroidImpl::init(int argc, char* argv[]) // set proc limits
{ struct rlimit limit;
//mutex=new QMutex(QMutex::Recursive); uint16_t nfiles; i2p::config::GetOption("limits.openfiles", nfiles);
//setRunningCallback(0); getrlimit(RLIMIT_NOFILE, &limit);
//m_IsRunning=false; if (nfiles == 0) {
return Daemon.init(argc,argv); LogPrint(eLogInfo, "Daemon: using system limit in ", limit.rlim_cur, " max open files");
} else if (nfiles <= limit.rlim_max) {
limit.rlim_cur = nfiles;
if (setrlimit(RLIMIT_NOFILE, &limit) == 0) {
LogPrint(eLogInfo, "Daemon: set max number of open files to ",
nfiles, " (system limit is ", limit.rlim_max, ")");
} else {
LogPrint(eLogError, "Daemon: can't set max number of open files: ", strerror(errno));
}
} else {
LogPrint(eLogError, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max);
}
uint32_t cfsize; i2p::config::GetOption("limits.coresize", cfsize);
if (cfsize) // core file size set
{
cfsize *= 1024;
getrlimit(RLIMIT_CORE, &limit);
if (cfsize <= limit.rlim_max) {
limit.rlim_cur = cfsize;
if (setrlimit(RLIMIT_CORE, &limit) != 0) {
LogPrint(eLogError, "Daemon: can't set max size of coredump: ", strerror(errno));
} else if (cfsize == 0) {
LogPrint(eLogInfo, "Daemon: coredumps disabled");
} else {
LogPrint(eLogInfo, "Daemon: set max size of core files to ", cfsize / 1024, "Kb");
}
} else {
LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max);
} }
void DaemonAndroidImpl::start()
{
//QMutexLocker locker(mutex);
//setRunning(true);
Daemon.start();
} }
void DaemonAndroidImpl::stop() // Pidfile
{ // this code is c-styled and a bit ugly
//QMutexLocker locker(mutex); std::string pidfile; i2p::config::GetOption("pidfile", pidfile);
Daemon.stop(); if (pidfile == "") {
//setRunning(false); pidfile = i2p::fs::DataDirPath("i2pd.pid");
} }
if (pidfile != "") {
void DaemonAndroidImpl::restart() pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600);
if (pidFH < 0)
{ {
//QMutexLocker locker(mutex); LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno));
stop(); return false;
start();
} }
/* char pid[10];
void DaemonAndroidImpl::setRunningCallback(runningChangedCallback cb) sprintf(pid, "%d\n", getpid());
ftruncate(pidFH, 0);
if (write(pidFH, pid, strlen(pid)) < 0)
{ {
m_RunningChangedCallback = cb; LogPrint(eLogError, "Daemon: could not write pidfile: ", strerror(errno));
return false;
}
} }
gracefulShutdownInterval = 0; // not specified
bool DaemonAndroidImpl::isRunning() // Signal handler
{ struct sigaction sa;
return m_IsRunning; sa.sa_handler = handle_signal;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGHUP, &sa, 0);
sigaction(SIGUSR1, &sa, 0);
sigaction(SIGABRT, &sa, 0);
sigaction(SIGTERM, &sa, 0);
sigaction(SIGINT, &sa, 0);
sigaction(SIGPIPE, &sa, 0);
return Daemon_Singleton::start();
} }
void DaemonAndroidImpl::setRunning(bool newValue) bool DaemonAndroid::stop()
{
bool oldValue = m_IsRunning;
if(oldValue!=newValue)
{ {
m_IsRunning = newValue; i2p::fs::Remove(pidfile);
if(m_RunningChangedCallback)
m_RunningChangedCallback(); return Daemon_Singleton::stop();
}
} }
*/
static DaemonAndroidImpl daemon;
static char* argv[1]={strdup("tmp")};
/**
* returns error details if failed
* returns "ok" if daemon initialized and started okay
*/
std::string start(/*int argc, char* argv[]*/)
{
try
{
//int result;
void DaemonAndroid::run ()
{ {
//Log.d(TAG"Initialising the daemon..."); while (running)
bool daemonInitSuccess = daemon.init(1,argv);
if(!daemonInitSuccess)
{ {
//QMessageBox::critical(0, "Error", "Daemon init failed"); std::this_thread::sleep_for (std::chrono::seconds(1));
return "Daemon init failed"; if (gracefulShutdownInterval)
}
//Log.d(TAG"Initialised, creating the main window...");
//MainWindow w;
//Log.d(TAG"Before main window.show()...");
//w.show ();
{ {
//i2p::qt::Controller daemonQtController(daemon); gracefulShutdownInterval--; // - 1 second
//Log.d(TAG"Starting the daemon..."); if (gracefulShutdownInterval <= 0 || i2p::tunnel::tunnels.CountTransitTunnels() <= 0)
//emit daemonQtController.startDaemon();
//daemon.start ();
//Log.d(TAG"Starting GUI event loop...");
//result = app.exec();
//daemon.stop ();
daemon.start();
}
}
//QMessageBox::information(&w, "Debug", "demon stopped");
//Log.d(TAG"Exiting the application");
//return result;
}
catch (boost::exception& ex)
{ {
std::stringstream ss; LogPrint(eLogInfo, "Graceful shutdown");
ss << boost::diagnostic_information(ex); return;
return ss.str();
} }
catch (std::exception& ex)
{
std::stringstream ss;
ss << ex.what();
return ss.str();
} }
catch(...)
{
return "unknown exception";
} }
return "ok";
} }
void stop()
{
daemon.stop();
} }
} }
}
#endif

99
android/jni/DaemonAndroid.h

@ -1,87 +1,60 @@
#ifndef DAEMON_ANDROID_H #ifndef DAEMON_H__
#define DAEMON_ANDROID_H #define DAEMON_H__
#include <memory>
#include <string> #include <string>
namespace i2p namespace i2p
{ {
namespace android namespace util
{ {
class DaemonAndroidImpl class Daemon_Singleton_Private;
class Daemon_Singleton
{ {
public: public:
virtual bool init(int argc, char* argv[]);
virtual bool start();
virtual bool stop();
virtual void run () {};
DaemonAndroidImpl (); bool isDaemon;
~DaemonAndroidImpl (); bool running;
//typedef void (*runningChangedCallback)(); protected:
Daemon_Singleton();
virtual ~Daemon_Singleton();
/** bool IsService () const;
* @return success
*/
bool init(int argc, char* argv[]);
void start();
void stop();
void restart();
//void setRunningCallback(runningChangedCallback cb);
//bool isRunning();
private:
//void setRunning(bool running);
private:
//QMutex* mutex;
//bool m_IsRunning;
//runningChangedCallback m_RunningChangedCallback;
};
/**
* returns "ok" if daemon init failed
* returns errinfo if daemon initialized and started okay
*/
std::string start();
// stops the daemon // d-pointer for httpServer, httpProxy, etc.
void stop(); class Daemon_Singleton_Private;
Daemon_Singleton_Private &d;
};
/* #if defined(ANDROID)
class Worker : public QObject #define Daemon i2p::util::DaemonAndroid::Instance()
class DaemonAndroid : public Daemon_Singleton
{ {
Q_OBJECT
public: public:
static DaemonAndroid& Instance()
{
static DaemonAndroid instance;
return instance;
}
Worker (DaemonAndroidImpl& daemon); bool start();
bool stop();
void run ();
private: private:
std::string pidfile;
int pidFH;
DaemonAndroidImpl& m_Daemon;
public slots:
void startDaemon();
void restartDaemon();
void stopDaemon();
signals:
void resultReady();
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public: public:
Controller(DaemonAndroidImpl& daemon); int gracefulShutdownInterval; // in seconds
~Controller();
private:
DaemonAndroidImpl& m_Daemon;
public slots:
void handleResults(){}
signals:
void startDaemon();
void stopDaemon();
void restartDaemon();
}; };
*/ #endif
} }
} }
#endif // DAEMON_ANDROID_H #endif // DAEMON_H__

66
android/jni/i2pd_android.cpp

@ -1,66 +0,0 @@
//#include <string.h>
#include <jni.h>
#include "org_purplei2p_i2pd_I2PD_JNI.h"
#include "DaemonAndroid.h"
#include "RouterContext.h"
#include "Transports.h"
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
(JNIEnv * env, jclass clazz) {
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a/NEON (hard-float)"
#else
#define ABI "armeabi-v7a/NEON"
#endif
#else
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a (hard-float)"
#else
#define ABI "armeabi-v7a"
#endif
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#elif defined(__x86_64__)
#define ABI "x86_64"
#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */
#define ABI "mips64"
#elif defined(__mips__)
#define ABI "mips"
#elif defined(__aarch64__)
#define ABI "arm64-v8a"
#else
#define ABI "unknown"
#endif
return env->NewStringUTF(ABI);
}
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
(JNIEnv * env, jclass clazz) {
return env->NewStringUTF(i2p::android::start().c_str());
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
(JNIEnv * env, jclass clazz) {
i2p::android::stop();
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
(JNIEnv * env, jclass clazz) {
i2p::context.SetAcceptsTunnels (false);
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
(JNIEnv * env, jclass clazz, jboolean isConnected)
{
bool isConnectedBool = (bool) isConnected;
i2p::transport::transports.SetOnline (isConnectedBool);
}

33
android/jni/org_purplei2p_i2pd_I2PD_JNI.h

@ -1,33 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_purplei2p_i2pd_I2PD_JNI */
#ifndef _Included_org_purplei2p_i2pd_I2PD_JNI
#define _Included_org_purplei2p_i2pd_I2PD_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_purplei2p_i2pd_I2PD_JNI
* Method: stringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
(JNIEnv *, jclass);
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
(JNIEnv * env, jclass clazz, jboolean isConnected);
#ifdef __cplusplus
}
#endif
#endif
Loading…
Cancel
Save