mirror of https://github.com/PurpleI2P/i2pd.git
unlnown542a
7 years ago
6 changed files with 351 additions and 227 deletions
@ -1,193 +1,193 @@
@@ -1,193 +1,193 @@
|
||||
#include "DaemonAndroid.h" |
||||
#include "Daemon.h" |
||||
#include <iostream> |
||||
#include <boost/exception/diagnostic_information.hpp> |
||||
#include <boost/exception_ptr.hpp> |
||||
#include <exception> |
||||
//#include "mainwindow.h"
|
||||
|
||||
#ifndef _WIN32 |
||||
namespace i2p |
||||
{ |
||||
namespace android |
||||
{ |
||||
/* Worker::Worker (DaemonAndroidImpl& daemon):
|
||||
m_Daemon (daemon) |
||||
{ |
||||
} |
||||
|
||||
#include <signal.h> |
||||
#include <stdlib.h> |
||||
#include <thread> |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include <sys/stat.h> |
||||
#include <sys/resource.h> |
||||
void Worker::startDaemon() |
||||
{ |
||||
Log.d(TAG"Performing daemon start..."); |
||||
m_Daemon.start(); |
||||
Log.d(TAG"Daemon started."); |
||||
emit resultReady(); |
||||
} |
||||
void Worker::restartDaemon() |
||||
{ |
||||
Log.d(TAG"Performing daemon restart..."); |
||||
m_Daemon.restart(); |
||||
Log.d(TAG"Daemon restarted."); |
||||
emit resultReady(); |
||||
} |
||||
void Worker::stopDaemon() { |
||||
Log.d(TAG"Performing daemon stop..."); |
||||
m_Daemon.stop(); |
||||
Log.d(TAG"Daemon stopped."); |
||||
emit resultReady(); |
||||
} |
||||
|
||||
#include "Config.h" |
||||
#include "FS.h" |
||||
#include "Log.h" |
||||
#include "Tunnel.h" |
||||
#include "RouterContext.h" |
||||
#include "ClientContext.h" |
||||
Controller::Controller(DaemonAndroidImpl& daemon): |
||||
m_Daemon (daemon) |
||||
{ |
||||
Worker *worker = new Worker (m_Daemon); |
||||
worker->moveToThread(&workerThread); |
||||
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() |
||||
{ |
||||
Log.d(TAG"Closing and waiting for daemon worker thread..."); |
||||
workerThread.quit(); |
||||
workerThread.wait(); |
||||
Log.d(TAG"Waiting for daemon worker thread finished."); |
||||
if(m_Daemon.isRunning()) |
||||
{ |
||||
Log.d(TAG"Stopping the daemon..."); |
||||
m_Daemon.stop(); |
||||
Log.d(TAG"Stopped the daemon."); |
||||
} |
||||
} |
||||
*/ |
||||
DaemonAndroidImpl::DaemonAndroidImpl () |
||||
//:
|
||||
/*mutex(nullptr), */ |
||||
//m_IsRunning(false),
|
||||
//m_RunningChangedCallback(nullptr)
|
||||
{ |
||||
} |
||||
|
||||
void handle_signal(int sig) |
||||
{ |
||||
switch (sig) |
||||
{ |
||||
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; |
||||
DaemonAndroidImpl::~DaemonAndroidImpl () |
||||
{ |
||||
//delete mutex;
|
||||
} |
||||
} |
||||
|
||||
namespace i2p |
||||
{ |
||||
namespace util |
||||
bool DaemonAndroidImpl::init(int argc, char* argv[]) |
||||
{ |
||||
bool DaemonAndroid::start() |
||||
{ |
||||
if (isDaemon) |
||||
{ |
||||
pid_t pid; |
||||
pid = fork(); |
||||
if (pid > 0) // parent
|
||||
::exit (EXIT_SUCCESS); |
||||
//mutex=new QMutex(QMutex::Recursive);
|
||||
//setRunningCallback(0);
|
||||
//m_IsRunning=false;
|
||||
return Daemon.init(argc,argv); |
||||
} |
||||
|
||||
if (pid < 0) // error
|
||||
{ |
||||
LogPrint(eLogError, "Daemon: could not fork: ", strerror(errno)); |
||||
return false; |
||||
} |
||||
void DaemonAndroidImpl::start() |
||||
{ |
||||
//QMutexLocker locker(mutex);
|
||||
//setRunning(true);
|
||||
Daemon.start(); |
||||
} |
||||
|
||||
// child
|
||||
umask(S_IWGRP | S_IRWXO); // 0027
|
||||
int sid = setsid(); |
||||
if (sid < 0) |
||||
{ |
||||
LogPrint(eLogError, "Daemon: could not create process group."); |
||||
return false; |
||||
} |
||||
std::string d = i2p::fs::GetDataDir(); |
||||
if (chdir(d.c_str()) != 0) |
||||
{ |
||||
LogPrint(eLogError, "Daemon: could not chdir: ", strerror(errno)); |
||||
return false; |
||||
} |
||||
void DaemonAndroidImpl::stop() |
||||
{ |
||||
//QMutexLocker locker(mutex);
|
||||
Daemon.stop(); |
||||
//setRunning(false);
|
||||
} |
||||
|
||||
// point std{in,out,err} descriptors to /dev/null
|
||||
freopen("/dev/null", "r", stdin); |
||||
freopen("/dev/null", "w", stdout); |
||||
freopen("/dev/null", "w", stderr); |
||||
} |
||||
void DaemonAndroidImpl::restart() |
||||
{ |
||||
//QMutexLocker locker(mutex);
|
||||
stop(); |
||||
start(); |
||||
} |
||||
/*
|
||||
void DaemonAndroidImpl::setRunningCallback(runningChangedCallback cb) |
||||
{ |
||||
m_RunningChangedCallback = cb; |
||||
} |
||||
|
||||
// set proc limits
|
||||
struct rlimit limit; |
||||
uint16_t nfiles; i2p::config::GetOption("limits.openfiles", nfiles); |
||||
getrlimit(RLIMIT_NOFILE, &limit); |
||||
if (nfiles == 0) { |
||||
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); |
||||
} |
||||
} |
||||
bool DaemonAndroidImpl::isRunning() |
||||
{ |
||||
return m_IsRunning; |
||||
} |
||||
|
||||
// Pidfile
|
||||
// this code is c-styled and a bit ugly
|
||||
std::string pidfile; i2p::config::GetOption("pidfile", pidfile); |
||||
if (pidfile == "") { |
||||
pidfile = i2p::fs::DataDirPath("i2pd.pid"); |
||||
} |
||||
if (pidfile != "") { |
||||
pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600); |
||||
if (pidFH < 0) |
||||
void DaemonAndroidImpl::setRunning(bool newValue) |
||||
{ |
||||
bool oldValue = m_IsRunning; |
||||
if(oldValue!=newValue) |
||||
{ |
||||
m_IsRunning = newValue; |
||||
if(m_RunningChangedCallback) |
||||
m_RunningChangedCallback(); |
||||
} |
||||
} |
||||
*/ |
||||
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;
|
||||
|
||||
{ |
||||
//Log.d(TAG"Initialising the daemon...");
|
||||
bool daemonInitSuccess = daemon.init(1,argv); |
||||
if(!daemonInitSuccess) |
||||
{ |
||||
LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno)); |
||||
return false; |
||||
//QMessageBox::critical(0, "Error", "Daemon init failed");
|
||||
return "Daemon init failed"; |
||||
} |
||||
char pid[10]; |
||||
sprintf(pid, "%d\n", getpid()); |
||||
ftruncate(pidFH, 0); |
||||
if (write(pidFH, pid, strlen(pid)) < 0) |
||||
//Log.d(TAG"Initialised, creating the main window...");
|
||||
//MainWindow w;
|
||||
//Log.d(TAG"Before main window.show()...");
|
||||
//w.show ();
|
||||
|
||||
{ |
||||
LogPrint(eLogError, "Daemon: could not write pidfile: ", strerror(errno)); |
||||
return false; |
||||
//i2p::qt::Controller daemonQtController(daemon);
|
||||
//Log.d(TAG"Starting the daemon...");
|
||||
//emit daemonQtController.startDaemon();
|
||||
//daemon.start ();
|
||||
//Log.d(TAG"Starting GUI event loop...");
|
||||
//result = app.exec();
|
||||
//daemon.stop ();
|
||||
daemon.start(); |
||||
} |
||||
} |
||||
gracefulShutdownInterval = 0; // not specified
|
||||
|
||||
// Signal handler
|
||||
struct sigaction sa; |
||||
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(); |
||||
//QMessageBox::information(&w, "Debug", "demon stopped");
|
||||
//Log.d(TAG"Exiting the application");
|
||||
//return result;
|
||||
} |
||||
|
||||
bool DaemonAndroid::stop() |
||||
catch (boost::exception& ex) |
||||
{ |
||||
i2p::fs::Remove(pidfile); |
||||
|
||||
return Daemon_Singleton::stop(); |
||||
std::stringstream ss; |
||||
ss << boost::diagnostic_information(ex); |
||||
return ss.str(); |
||||
} |
||||
|
||||
void DaemonAndroid::run () |
||||
catch (std::exception& ex) |
||||
{ |
||||
while (running) |
||||
{ |
||||
std::this_thread::sleep_for (std::chrono::seconds(1)); |
||||
if (gracefulShutdownInterval) |
||||
{ |
||||
gracefulShutdownInterval--; // - 1 second
|
||||
if (gracefulShutdownInterval <= 0 || i2p::tunnel::tunnels.CountTransitTunnels() <= 0) |
||||
{ |
||||
LogPrint(eLogInfo, "Graceful shutdown"); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
std::stringstream ss; |
||||
ss << ex.what(); |
||||
return ss.str(); |
||||
} |
||||
catch(...) |
||||
{ |
||||
return "unknown exception"; |
||||
} |
||||
return "ok"; |
||||
} |
||||
} |
||||
|
||||
#endif |
||||
void stop() |
||||
{ |
||||
daemon.stop(); |
||||
} |
||||
} |
||||
} |
||||
|
@ -1,60 +1,87 @@
@@ -1,60 +1,87 @@
|
||||
#ifndef DAEMON_H__ |
||||
#define DAEMON_H__ |
||||
#ifndef DAEMON_ANDROID_H |
||||
#define DAEMON_ANDROID_H |
||||
|
||||
#include <memory> |
||||
#include <string> |
||||
|
||||
namespace i2p |
||||
{ |
||||
namespace util |
||||
namespace android |
||||
{ |
||||
class Daemon_Singleton_Private; |
||||
class Daemon_Singleton |
||||
{ |
||||
public: |
||||
virtual bool init(int argc, char* argv[]); |
||||
virtual bool start(); |
||||
virtual bool stop(); |
||||
virtual void run () {}; |
||||
|
||||
bool isDaemon; |
||||
bool running; |
||||
|
||||
protected: |
||||
Daemon_Singleton(); |
||||
virtual ~Daemon_Singleton(); |
||||
|
||||
bool IsService () const; |
||||
|
||||
// d-pointer for httpServer, httpProxy, etc.
|
||||
class Daemon_Singleton_Private; |
||||
Daemon_Singleton_Private &d; |
||||
}; |
||||
|
||||
#if defined(ANDROID) |
||||
#define Daemon i2p::util::DaemonAndroid::Instance() |
||||
class DaemonAndroid : public Daemon_Singleton |
||||
{ |
||||
public: |
||||
static DaemonAndroid& Instance() |
||||
{ |
||||
static DaemonAndroid instance; |
||||
return instance; |
||||
} |
||||
|
||||
bool start(); |
||||
bool stop(); |
||||
void run (); |
||||
|
||||
private: |
||||
std::string pidfile; |
||||
int pidFH; |
||||
|
||||
public: |
||||
int gracefulShutdownInterval; // in seconds
|
||||
}; |
||||
#endif |
||||
class DaemonAndroidImpl |
||||
{ |
||||
public: |
||||
|
||||
DaemonAndroidImpl (); |
||||
~DaemonAndroidImpl (); |
||||
|
||||
//typedef void (*runningChangedCallback)();
|
||||
|
||||
/**
|
||||
* @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
|
||||
void stop(); |
||||
|
||||
/*
|
||||
class Worker : public QObject |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
|
||||
Worker (DaemonAndroidImpl& daemon); |
||||
|
||||
private: |
||||
|
||||
DaemonAndroidImpl& m_Daemon; |
||||
|
||||
public slots: |
||||
void startDaemon(); |
||||
void restartDaemon(); |
||||
void stopDaemon(); |
||||
|
||||
signals: |
||||
void resultReady(); |
||||
}; |
||||
|
||||
class Controller : public QObject |
||||
{ |
||||
Q_OBJECT |
||||
QThread workerThread; |
||||
public: |
||||
Controller(DaemonAndroidImpl& daemon); |
||||
~Controller(); |
||||
private: |
||||
DaemonAndroidImpl& m_Daemon; |
||||
|
||||
public slots: |
||||
void handleResults(){} |
||||
signals: |
||||
void startDaemon(); |
||||
void stopDaemon(); |
||||
void restartDaemon(); |
||||
}; |
||||
*/ |
||||
} |
||||
} |
||||
|
||||
#endif // DAEMON_H__
|
||||
#endif // DAEMON_ANDROID_H
|
||||
|
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
|
||||
//#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); |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
/* 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…
Reference in new issue