From faac35cd1e868d888bba722164b7b3037af0ce46 Mon Sep 17 00:00:00 2001
From: unlnown542a <unknown542a@i2pmail.org>
Date: Sat, 21 Apr 2018 21:55:45 +0300
Subject: [PATCH] Revert "Change jni to build executable. Clone with minimal
 changes DaemonUnix into DaemonAndroid"

This reverts commit f11266972e81a6db65aeecc3f77fe2b47418385c.
---
 android/jni/Android.mk                    |   8 +-
 android/jni/Application.mk                |   8 +-
 android/jni/DaemonAndroid.cpp             | 366 +++++++++++-----------
 android/jni/DaemonAndroid.h               | 113 ++++---
 android/jni/i2pd_android.cpp              |  66 ++++
 android/jni/org_purplei2p_i2pd_I2PD_JNI.h |  33 ++
 6 files changed, 359 insertions(+), 235 deletions(-)
 create mode 100755 android/jni/i2pd_android.cpp
 create mode 100644 android/jni/org_purplei2p_i2pd_I2PD_JNI.h

diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index 90284995..d5a8f05f 100755
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -12,15 +12,15 @@ LOCAL_STATIC_LIBRARIES := \
 	miniupnpc
 LOCAL_LDLIBS := -lz
 
-LOCAL_SRC_FILES := DaemonAndroid.cpp $(IFADDRS_PATH)/ifaddrs.c \
+LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp $(IFADDRS_PATH)/ifaddrs.c \
 	$(wildcard $(LIB_SRC_PATH)/*.cpp)\
 	$(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp)\
 	$(DAEMON_SRC_PATH)/Daemon.cpp \
 	$(DAEMON_SRC_PATH)/UPnP.cpp \
 	$(DAEMON_SRC_PATH)/HTTPServer.cpp \
-	$(DAEMON_SRC_PATH)/I2PControl.cpp \
-	$(DAEMON_SRC_PATH)/i2pd.cpp
-include $(BUILD_EXECUTABLE)
+	$(DAEMON_SRC_PATH)/I2PControl.cpp
+
+include $(BUILD_SHARED_LIBRARY)
 
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
diff --git a/android/jni/Application.mk b/android/jni/Application.mk
index acc6f895..0fa116c2 100755
--- a/android/jni/Application.mk
+++ b/android/jni/Application.mk
@@ -9,14 +9,12 @@ APP_PLATFORM := android-14
 # http://stackoverflow.com/a/21386866/529442 http://stackoverflow.com/a/15616255/529442 to enable c++11 support in Eclipse
 NDK_TOOLCHAIN_VERSION := 4.9
 # APP_STL := stlport_shared  --> does not seem to contain C++11 features
-#APP_STL := gnustl_shared
-APP_STL := gnustl_static
+APP_STL := gnustl_shared
 
 # Enable c++11 extensions in source code
-APP_CPPFLAGS += -std=c++11 -fvisibility=default -fPIE
+APP_CPPFLAGS += -std=c++11
 
 APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP
-APP_LDFLAGS += -rdynamic -fPIE -pie
 ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
 APP_CPPFLAGS += -DANDROID_ARM7A
 endif
@@ -28,7 +26,7 @@ APP_OPTIM  := debug
 # git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
 # git clone https://github.com/PurpleI2P/android-ifaddrs.git
 # change to your own
-I2PD_LIBS_PATH = /home/u/build/i2p/daemon/static.libs
+I2PD_LIBS_PATH = /path/to/libraries
 BOOST_PATH = $(I2PD_LIBS_PATH)/Boost-for-Android-Prebuilt
 OPENSSL_PATH = $(I2PD_LIBS_PATH)/OpenSSL-for-Android-Prebuilt
 MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt
diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp
index 94c679be..75584740 100644
--- a/android/jni/DaemonAndroid.cpp
+++ b/android/jni/DaemonAndroid.cpp
@@ -1,193 +1,193 @@
 #include "DaemonAndroid.h"
-
-#ifndef _WIN32
-
-#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)
-{
-	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;
-	}
-}
+#include "Daemon.h"
+#include <iostream>
+#include <boost/exception/diagnostic_information.hpp>
+#include <boost/exception_ptr.hpp>
+#include <exception>
+//#include "mainwindow.h"
 
 namespace i2p
 {
-	namespace util
+namespace android
+{
+/*	Worker::Worker (DaemonAndroidImpl& daemon):
+		m_Daemon (daemon)
 	{
-		bool DaemonAndroid::start()
-		{
-			if (isDaemon)
-			{
-				pid_t pid;
-				pid = fork();
-				if (pid > 0) // parent
-					::exit (EXIT_SUCCESS);
+	}
 
-				if (pid < 0) // error
-				{
-					LogPrint(eLogError, "Daemon: could not fork: ", strerror(errno));
-					return false;
-				}
+	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();
+	}
 
-				// 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;
-				}
-
-				// point std{in,out,err} descriptors to /dev/null
-				freopen("/dev/null", "r", stdin);
-				freopen("/dev/null", "w", stdout);
-				freopen("/dev/null", "w", stderr);
-			}
-
-			// 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);
-				}
-			}
-
-			// 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)
-				{
-					LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno));
-					return false;
-				}
-				char pid[10];
-				sprintf(pid, "%d\n", getpid());
-				ftruncate(pidFH, 0);
-				if (write(pidFH, pid, strlen(pid)) < 0)
-				{
-					LogPrint(eLogError, "Daemon: could not write pidfile: ", strerror(errno));
-					return false;
-				}
-			}
-			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();
-		}
-
-		bool DaemonAndroid::stop()
-		{
-			i2p::fs::Remove(pidfile);
-
-			return Daemon_Singleton::stop();
-		}
-
-		void DaemonAndroid::run ()
-		{
-			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;
-					}
-				}
-			}
+    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)
+	{
+	}
 
-#endif
+	DaemonAndroidImpl::~DaemonAndroidImpl ()
+	{
+		//delete mutex;
+	}
+
+	bool DaemonAndroidImpl::init(int argc, char* argv[])
+	{
+		//mutex=new QMutex(QMutex::Recursive);
+		//setRunningCallback(0);
+        //m_IsRunning=false;
+		return Daemon.init(argc,argv);
+	}
+
+	void DaemonAndroidImpl::start()
+	{
+		//QMutexLocker locker(mutex);
+		//setRunning(true);
+		Daemon.start();
+	}
+
+	void DaemonAndroidImpl::stop()
+	{
+		//QMutexLocker locker(mutex);
+		Daemon.stop();
+		//setRunning(false);
+	}
+
+	void DaemonAndroidImpl::restart()
+	{
+		//QMutexLocker locker(mutex);
+		stop();
+		start();
+	}
+	/*
+	void DaemonAndroidImpl::setRunningCallback(runningChangedCallback cb)
+	{
+		m_RunningChangedCallback = cb;
+	}
+
+	bool DaemonAndroidImpl::isRunning()
+	{
+        return m_IsRunning;
+	}
+
+	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)
+				{
+					//QMessageBox::critical(0, "Error", "Daemon init failed");
+					return "Daemon init failed";
+				}
+				//Log.d(TAG"Initialised, creating the main window...");
+				//MainWindow w;
+				//Log.d(TAG"Before main window.show()...");
+				//w.show ();
+
+				{
+					//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();
+				}
+			}
+
+			//QMessageBox::information(&w, "Debug", "demon stopped");
+			//Log.d(TAG"Exiting the application");
+			//return result;
+		}
+		catch (boost::exception& ex)
+		{
+			std::stringstream ss;
+		    ss << boost::diagnostic_information(ex);
+		    return ss.str();
+		}
+		catch (std::exception& ex)
+		{
+			std::stringstream ss;
+		    ss << ex.what();
+		    return ss.str();
+		}
+		catch(...)
+		{
+			return "unknown exception";
+		}
+		return "ok";
+	}
+
+	void stop()
+	{
+		daemon.stop();
+	}
+}
+}
diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h
index c62d7c76..9cc8219b 100644
--- a/android/jni/DaemonAndroid.h
+++ b/android/jni/DaemonAndroid.h
@@ -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 () {};
+    class DaemonAndroidImpl
+    {
+    public:
 
-			bool isDaemon;
-			bool running;
+		DaemonAndroidImpl ();
+		~DaemonAndroidImpl ();
 
-		protected:
-			Daemon_Singleton();
-			virtual ~Daemon_Singleton();
+        //typedef void (*runningChangedCallback)();
 
-			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;
+    };
 
-			// d-pointer for httpServer, httpProxy, etc.
-			class Daemon_Singleton_Private;
-			Daemon_Singleton_Private &d;
-	};
+	/**
+	 * returns "ok" if daemon init failed
+	 * returns errinfo if daemon initialized and started okay
+	 */
+    std::string start();
 
-#if defined(ANDROID)
-#define Daemon i2p::util::DaemonAndroid::Instance()
-	class DaemonAndroid : public Daemon_Singleton
-	{
-		public:
-			static DaemonAndroid& Instance()
-			{
-				static DaemonAndroid instance;
-				return instance;
-			}
+    // stops the daemon
+    void stop();
 
-			bool start();
-			bool stop();
-			void run ();
+    /*
+	class Worker : public QObject
+    {
+        Q_OBJECT
+	public:
 
-		private:
-			std::string pidfile;
-			int pidFH;
+		Worker (DaemonAndroidImpl& daemon);
 
-		public:
-			int gracefulShutdownInterval; // in seconds
-	};
-#endif
+	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
diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp
new file mode 100755
index 00000000..8791c90b
--- /dev/null
+++ b/android/jni/i2pd_android.cpp
@@ -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);
+}
diff --git a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h
new file mode 100644
index 00000000..04923d22
--- /dev/null
+++ b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h
@@ -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