diff --git a/ChangeLog b/ChangeLog index 9013ede8..4b735f3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,26 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.23.0] - 2019-01-21 +### Added +- Standard LeaseSet2 support +- Ability to adjust timestamps through the NTP +- Ability to disable peer profile persist +- Request permission for android >= 6 +- Initial addressbook to android assets +- Cancel graceful shutdown for android +- Russian translation for android +### Changed +- Chacha20 and Poly1305 implementation +- Eliminate extra copy of NTCP2 send buffers +- Extract content of tunnel.d from assets on android +- Removed name resolvers from transports +- Update reseed certificates +### Fixed +- LeaseSet published content verification +- Exclude invalid LeaseSets from the list on a floodfill +- Build for OpenWrt with openssl 1.1.1 + ## [2.22.0] - 2018-11-09 ### Added - Multiple tunnel config files from tunnels.d folder diff --git a/Makefile b/Makefile index ce1ad51f..3dfaaade 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS))) DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp include Makefile.mingw else # not supported -$(error Not supported platform) + $(error Not supported platform) endif ifeq ($(USE_MESHNET),yes) diff --git a/Makefile.mingw b/Makefile.mingw index 5f3292d1..e2f9e857 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -3,10 +3,12 @@ CXX = g++ WINDRES = windres CXXFLAGS := ${CXX_DEBUG} -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN NEEDED_CXXFLAGS = -std=c++11 -BOOST_SUFFIX = -mt INCFLAGS = -Idaemon -I. LDFLAGS := ${LD_DEBUG} -Wl,-Bstatic -static-libgcc -static-libstdc++ +# Boost libraries suffix +BOOST_SUFFIX = -mt + # UPNP Support ifeq ($(USE_UPNP),yes) CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB diff --git a/Win32/installer.iss b/Win32/installer.iss index 787eebeb..00a93e6e 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.22.0" +#define I2Pd_ver "2.23.0" #define I2Pd_Publisher "PurpleI2P" [Setup] diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 5ad3834e..4d26dbbb 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,13 +1,7 @@ - - + android:installLocation="auto"> @@ -15,6 +9,7 @@ + does not seem to contain C++11 features -APP_STL := gnustl_shared +# ABI arm64-v8a and x86_64 supported only from platform-21 +#APP_ABI := arm64-v8a x86_64 +#APP_PLATFORM := android-21 + +NDK_TOOLCHAIN_VERSION := clang +#APP_STL := c++_shared +APP_STL := c++_static # Enable c++11 extensions in source code -APP_CPPFLAGS += -std=c++11 +APP_CPPFLAGS += -std=c++11 -fexceptions -frtti APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) APP_CPPFLAGS += -DANDROID_ARM7A endif -# Forcing debug optimization. Use `ndk-build NDK_DEBUG=1` instead. -#APP_OPTIM := debug - # git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git # git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git # git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp index 5ea5e495..7ff83d1f 100644 --- a/android/jni/DaemonAndroid.cpp +++ b/android/jni/DaemonAndroid.cpp @@ -39,7 +39,7 @@ namespace android emit resultReady(); } - Controller::Controller(DaemonAndroidImpl& daemon): + Controller::Controller(DaemonAndroidImpl& daemon): m_Daemon (daemon) { Worker *worker = new Worker (m_Daemon); @@ -57,19 +57,19 @@ namespace android 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."); + 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) + /*mutex(nullptr), */ + //m_IsRunning(false), + //m_RunningChangedCallback(nullptr) { } @@ -82,9 +82,9 @@ namespace android { //mutex=new QMutex(QMutex::Recursive); //setRunningCallback(0); - //m_IsRunning=false; - - // make sure assets are ready before proceed + //m_IsRunning=false; + + // make sure assets are ready before proceed i2p::fs::DetectDataDir("", false); int numAttempts = 0; do @@ -93,7 +93,7 @@ namespace android numAttempts++; std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second } - while (numAttempts <= 10); // 10 seconds max + while (numAttempts <= 10); // 10 seconds max return Daemon.init(argc,argv); } @@ -125,16 +125,16 @@ namespace android bool DaemonAndroidImpl::isRunning() { - return m_IsRunning; + return m_IsRunning; } void DaemonAndroidImpl::setRunning(bool newValue) { - bool oldValue = m_IsRunning; + bool oldValue = m_IsRunning; if(oldValue!=newValue) { - m_IsRunning = newValue; - if(m_RunningChangedCallback) + m_IsRunning = newValue; + if(m_RunningChangedCallback) m_RunningChangedCallback(); } } @@ -183,14 +183,14 @@ namespace android catch (boost::exception& ex) { std::stringstream ss; - ss << boost::diagnostic_information(ex); - return ss.str(); + ss << boost::diagnostic_information(ex); + return ss.str(); } catch (std::exception& ex) { std::stringstream ss; - ss << ex.what(); - return ss.str(); + ss << ex.what(); + return ss.str(); } catch(...) { diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h index 9cc8219b..396a4578 100644 --- a/android/jni/DaemonAndroid.h +++ b/android/jni/DaemonAndroid.h @@ -7,45 +7,45 @@ namespace i2p { namespace android { - class DaemonAndroidImpl - { - public: + class DaemonAndroidImpl + { + public: DaemonAndroidImpl (); ~DaemonAndroidImpl (); - //typedef void (*runningChangedCallback)(); + //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); + /** + * @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; + //bool m_IsRunning; //runningChangedCallback m_RunningChangedCallback; - }; + }; /** * returns "ok" if daemon init failed * returns errinfo if daemon initialized and started okay */ - std::string start(); + std::string start(); - // stops the daemon - void stop(); + // stops the daemon + void stop(); - /* + /* class Worker : public QObject - { - Q_OBJECT + { + Q_OBJECT public: Worker (DaemonAndroidImpl& daemon); @@ -54,33 +54,33 @@ namespace android DaemonAndroidImpl& m_Daemon; - public slots: - void startDaemon(); - void restartDaemon(); - void stopDaemon(); + public slots: + void startDaemon(); + void restartDaemon(); + void stopDaemon(); - signals: - void resultReady(); - }; + signals: + void resultReady(); + }; - class Controller : public QObject - { - Q_OBJECT - QThread workerThread; - public: - Controller(DaemonAndroidImpl& daemon); - ~Controller(); + 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(); - }; - */ + public slots: + void handleResults(){} + signals: + void startDaemon(); + void stopDaemon(); + void restartDaemon(); + }; + */ } } diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index ac968fd3..c258733f 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -1,5 +1,3 @@ - -//#include #include #include "org_purplei2p_i2pd_I2PD_JNI.h" #include "DaemonAndroid.h" @@ -7,65 +5,64 @@ #include "Transports.h" JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith - (JNIEnv * env, jclass clazz) { + (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" + #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); + return env->NewStringUTF(ABI); } JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv * env, jclass clazz) { + (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) { + (JNIEnv * env, jclass clazz) { i2p::android::stop(); } JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels - (JNIEnv * env, jclass clazz) { + (JNIEnv * env, jclass clazz) { i2p::context.SetAcceptsTunnels (false); } JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels - (JNIEnv * env, jclass clazz) { + (JNIEnv * env, jclass clazz) { i2p::context.SetAcceptsTunnels (true); } JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged - (JNIEnv * env, jclass clazz, jboolean isConnected) -{ + (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 index 7beb1284..28b9118b 100644 --- a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h +++ b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h @@ -13,22 +13,22 @@ extern "C" { * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith - (JNIEnv *, jclass); + (JNIEnv *, jclass); JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv *, jclass); + (JNIEnv *, jclass); JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon - (JNIEnv *, jclass); + (JNIEnv *, jclass); JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels - (JNIEnv *, jclass); + (JNIEnv *, jclass); JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels - (JNIEnv *, jclass); + (JNIEnv *, jclass); JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged - (JNIEnv * env, jclass clazz, jboolean isConnected); + (JNIEnv * env, jclass clazz, jboolean isConnected); #ifdef __cplusplus } diff --git a/android/res/values-ru/strings.xml b/android/res/values-ru/strings.xml new file mode 100755 index 00000000..c3d1a24f --- /dev/null +++ b/android/res/values-ru/strings.xml @@ -0,0 +1,19 @@ + + + i2pd + Остановить + Корректная остановка + Отменить корректную остановку + Корректная остановка уже запущена + Корректная остановка запущена + Уже остановлено + Приложение инициализируется + Приложение запускается + Загружены JNI библиотеки + Приложение запущено + Запуск не удался + Корректная остановка запущена + Приложение было остановлено + осталось + Запрос + diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 18aef3b1..b7f556c8 100755 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -1,19 +1,19 @@ - + i2pd Stop Graceful Stop - Cancel Graceful Stop + Cancel Graceful Stop Graceful stop is already in progress Graceful stop is in progress Already stopped - i2pd initializing - i2pd is starting - i2pd: loaded JNI libraries - i2pd started - i2pd start failed - i2pd: graceful shutdown in progress - i2pd has stopped + Application initializing + Application starting + Loaded JNI libraries + Application Started + Start failed + Graceful shutdown in progress + Application stopped remaining Prompt diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index 4c3d5f44..bfcd4152 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -2,8 +2,8 @@ package org.purplei2p.i2pd; import java.util.HashSet; import java.util.Set; - import android.util.Log; +import org.purplei2p.i2pd.R; public class DaemonSingleton { private static final String TAG="i2pd"; @@ -43,24 +43,24 @@ public class DaemonSingleton { private volatile boolean startedOkay; public enum State { - uninitialized(R.string.uninitialized), - starting(R.string.starting), - jniLibraryLoaded(R.string.jniLibraryLoaded), - startedOkay(R.string.startedOkay), - startFailed(R.string.startFailed), - gracefulShutdownInProgress(R.string.gracefulShutdownInProgress), - stopped(R.string.stopped); + uninitialized(R.string.uninitialized), + starting(R.string.starting), + jniLibraryLoaded(R.string.jniLibraryLoaded), + startedOkay(R.string.startedOkay), + startFailed(R.string.startFailed), + gracefulShutdownInProgress(R.string.gracefulShutdownInProgress), + stopped(R.string.stopped); - State(int statusStringResourceId) { - this.statusStringResourceId = statusStringResourceId; - } + State(int statusStringResourceId) { + this.statusStringResourceId = statusStringResourceId; + } - private final int statusStringResourceId; + private final int statusStringResourceId; - public int getStatusStringResourceId() { - return statusStringResourceId; - } - }; + public int getStatusStringResourceId() { + return statusStringResourceId; + } + }; private volatile State state = State.uninitialized; diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index 49b602b0..2ba30c8a 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -16,134 +16,133 @@ import android.util.Log; import android.widget.Toast; public class ForegroundService extends Service { - private static final String TAG="FgService"; + private static final String TAG="FgService"; - private volatile boolean shown; + private volatile boolean shown; - private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = - new DaemonSingleton.StateUpdateListener() { + private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = + new DaemonSingleton.StateUpdateListener() { - @Override - public void daemonStateUpdate() { - try { - synchronized (ForegroundService.this) { - if (shown) cancelNotification(); - showNotification(); - } - } catch (Throwable tr) { - Log.e(TAG,"error ignored",tr); - } - } - }; + @Override + public void daemonStateUpdate() { + try { + synchronized (ForegroundService.this) { + if (shown) cancelNotification(); + showNotification(); + } + } catch (Throwable tr) { + Log.e(TAG,"error ignored",tr); + } + } + }; - private NotificationManager notificationManager; + private NotificationManager notificationManager; - // Unique Identification Number for the Notification. - // We use it on Notification start, and to cancel it. - private int NOTIFICATION = 1; + // Unique Identification Number for the Notification. + // We use it on Notification start, and to cancel it. + private int NOTIFICATION = 1; - /** - * Class for clients to access. Because we know this service always - * runs in the same process as its clients, we don't need to deal with - * IPC. - */ - public class LocalBinder extends Binder { - ForegroundService getService() { - return ForegroundService.this; - } - } + /** + * Class for clients to access. Because we know this service always + * runs in the same process as its clients, we don't need to deal with + * IPC. + */ + public class LocalBinder extends Binder { + ForegroundService getService() { + return ForegroundService.this; + } + } - @Override - public void onCreate() { - notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + @Override + public void onCreate() { + notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - synchronized (this) { - DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); - if (!shown) daemonStateUpdatedListener.daemonStateUpdate(); - } - // Tell the user we started. -// Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); - } + synchronized (this) { + DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); + if (!shown) daemonStateUpdatedListener.daemonStateUpdate(); + } + // Tell the user we started. +// Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); + } - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Log.i("ForegroundService", "Received start id " + startId + ": " + intent); - return START_STICKY; - } + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.i("ForegroundService", "Received start id " + startId + ": " + intent); + return START_STICKY; + } - @Override - public void onDestroy() { - DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener); - cancelNotification(); - } + @Override + public void onDestroy() { + DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener); + cancelNotification(); + } - private synchronized void cancelNotification() { - // Cancel the persistent notification. - notificationManager.cancel(NOTIFICATION); + private synchronized void cancelNotification() { + // Cancel the persistent notification. + notificationManager.cancel(NOTIFICATION); - stopForeground(true); + stopForeground(true); - // Tell the user we stopped. -// Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show(); - shown=false; - } + // Tell the user we stopped. + //Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show(); + shown=false; + } - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } - // This is the object that receives interactions from clients. See - // RemoteService for a more complete example. - private final IBinder mBinder = new LocalBinder(); + // This is the object that receives interactions from clients. See + // RemoteService for a more complete example. + private final IBinder mBinder = new LocalBinder(); - /** - * Show a notification while this service is running. - */ - private synchronized void showNotification() { - // In this sample, we'll use the same text for the ticker and the expanded notification - CharSequence text = getText(DaemonSingleton.getInstance().getState().getStatusStringResourceId()); + /** + * Show a notification while this service is running. + */ + private synchronized void showNotification() { + // In this sample, we'll use the same text for the ticker and the expanded notification + CharSequence text = getText(DaemonSingleton.getInstance().getState().getStatusStringResourceId()); - // The PendingIntent to launch our activity if the user selects this notification - PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - new Intent(this, I2PDActivity.class), 0); + // The PendingIntent to launch our activity if the user selects this notification + PendingIntent contentIntent = PendingIntent.getActivity(this, 0, + new Intent(this, I2PDActivity.class), 0); - // If earlier version channel ID is not used - // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context) - String channelId = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? createNotificationChannel() : ""; + // If earlier version channel ID is not used + // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context) + String channelId = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? createNotificationChannel() : ""; - // Set the info for the views that show in the notification panel. - Notification notification = new NotificationCompat.Builder(this, channelId) - .setOngoing(true) - .setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon - .setPriority(Notification.PRIORITY_DEFAULT) - .setCategory(Notification.CATEGORY_SERVICE) - .setTicker(text) // the status text - .setWhen(System.currentTimeMillis()) // the time stamp - .setContentTitle(getText(R.string.app_name)) // the label of the entry - .setContentText(text) // the contents of the entry - .setContentIntent(contentIntent) // The intent to send when the entry is clicked - .build(); + // Set the info for the views that show in the notification panel. + Notification notification = new NotificationCompat.Builder(this, channelId) + .setOngoing(true) + .setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon + .setPriority(Notification.PRIORITY_DEFAULT) + .setCategory(Notification.CATEGORY_SERVICE) + .setTicker(text) // the status text + .setWhen(System.currentTimeMillis()) // the time stamp + .setContentTitle(getText(R.string.app_name)) // the label of the entry + .setContentText(text) // the contents of the entry + .setContentIntent(contentIntent) // The intent to send when the entry is clicked + .build(); - // Send the notification. - //mNM.notify(NOTIFICATION, notification); - startForeground(NOTIFICATION, notification); - shown = true; - } + // Send the notification. + //mNM.notify(NOTIFICATION, notification); + startForeground(NOTIFICATION, notification); + shown = true; + } - @RequiresApi(Build.VERSION_CODES.O) - private synchronized String createNotificationChannel() { - String channelId = getString(R.string.app_name); - CharSequence channelName = "I2Pd service"; - NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW); - //chan.setLightColor(Color.PURPLE); - chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); - NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); - service.createNotificationChannel(chan); - return channelId; - } + @RequiresApi(Build.VERSION_CODES.O) + private synchronized String createNotificationChannel() { + String channelId = getString(R.string.app_name); + CharSequence channelName = "I2Pd service"; + NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW); + //chan.setLightColor(Color.PURPLE); + chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); + NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); + service.createNotificationChannel(chan); + return channelId; + } - private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); + private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); } - diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 3c95a832..b5f85c5b 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -66,9 +66,9 @@ public class I2PDActivity extends Activity { } DaemonSingleton.State state = daemon.getState(); textView.setText( - String.valueOf(state)+ - (DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")+ - (DaemonSingleton.State.gracefulShutdownInProgress.equals(state)?": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining):"") + String.valueOf(getText(state.getStatusStringResourceId()))+ + (DaemonSingleton.State.startFailed.equals(state) ? ": "+daemon.getDaemonStartResult() : "")+ + (DaemonSingleton.State.gracefulShutdownInProgress.equals(state) ? ": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining) : "") ); } catch (Throwable tr) { Log.e(TAG,"error ignored",tr); @@ -100,14 +100,14 @@ public class I2PDActivity extends Activity { daemonStateUpdatedListener.daemonStateUpdate(); // request permissions - if (Build.VERSION.SDK_INT >= 23) + if (Build.VERSION.SDK_INT >= 23) { - if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); - } + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); + } } // set the app be foreground @@ -139,19 +139,19 @@ public class I2PDActivity extends Activity { @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - switch (requestCode) + switch (requestCode) { - case MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE: + case MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE: { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) - Log.e(TAG, "Memory permission granted"); + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) + Log.e(TAG, "Memory permission granted"); else - Log.e(TAG, "Memory permission declined"); + Log.e(TAG, "Memory permission declined"); // TODO: terminate - return; + return; } - default: ; - } + default: ; + } } private static void cancelGracefulStop() { @@ -249,7 +249,7 @@ public class I2PDActivity extends Activity { { item.setTitle(R.string.action_cancel_graceful_stop); i2pdGracefulStop(); - } + } return true; } @@ -292,7 +292,7 @@ public class I2PDActivity extends Activity { @Override public void run() { - try{ + try { Log.d(TAG, "grac stopping"); if(daemon.isStartedOkay()) { daemon.stopAcceptingTunnels(); @@ -302,10 +302,10 @@ public class I2PDActivity extends Activity { gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS; } rescheduleGraceStop(null,gracefulStopAtMillis); - }else{ + } else { i2pdStop(); } - } catch(Throwable tr) { + } catch(Throwable tr) { Log.e(TAG,"",tr); } } @@ -329,7 +329,7 @@ public class I2PDActivity extends Activity { daemon.startAcceptingTunnels(); else i2pdStop(); - } + } catch(Throwable tr) { Log.e(TAG,"",tr); @@ -470,7 +470,9 @@ public class I2PDActivity extends Activity { } // copy assets. If processed file exists, it won't be overwrited + copyAsset("addressbook"); copyAsset("certificates"); + copyAsset("tunnels.d"); copyAsset("i2pd.conf"); copyAsset("subscriptions.txt"); copyAsset("tunnels.conf"); diff --git a/android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java b/android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java index 3e364949..aa2ff301 100644 --- a/android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java @@ -15,157 +15,157 @@ import java.lang.reflect.Method; //android.permission.WRITE_EXTERNAL_STORAGE public class I2PDPermsAskerActivity extends Activity { - private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0; + private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0; - private Button button_request_write_ext_storage_perms; - private TextView textview_retry; + private Button button_request_write_ext_storage_perms; + private TextView textview_retry; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - //if less than Android 6, no runtime perms req system present - if (android.os.Build.VERSION.SDK_INT < 23) { - startMainActivity(); - return; - } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + //if less than Android 6, no runtime perms req system present + if (android.os.Build.VERSION.SDK_INT < 23) { + startMainActivity(); + return; + } - setContentView(R.layout.activity_perms_asker); - button_request_write_ext_storage_perms = (Button) findViewById(R.id.button_request_write_ext_storage_perms); - textview_retry = (TextView) findViewById(R.id.textview_retry); + setContentView(R.layout.activity_perms_asker); + button_request_write_ext_storage_perms = (Button) findViewById(R.id.button_request_write_ext_storage_perms); + textview_retry = (TextView) findViewById(R.id.textview_retry); - button_request_write_ext_storage_perms.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - request_write_ext_storage_perms(); - } - }); - request_write_ext_storage_perms(); - } + button_request_write_ext_storage_perms.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + request_write_ext_storage_perms(); + } + }); + request_write_ext_storage_perms(); + } - private void request_write_ext_storage_perms() { + private void request_write_ext_storage_perms() { - textview_retry.setVisibility(TextView.GONE); - button_request_write_ext_storage_perms.setVisibility(Button.GONE); + textview_retry.setVisibility(TextView.GONE); + button_request_write_ext_storage_perms.setVisibility(Button.GONE); - Method methodCheckPermission; - Method method_shouldShowRequestPermissionRationale; - Method method_requestPermissions; - try { - methodCheckPermission = getClass().getMethod("checkSelfPermission", String.class); - method_shouldShowRequestPermissionRationale = - getClass().getMethod("shouldShowRequestPermissionRationale", String.class); - method_requestPermissions = - getClass().getMethod("requestPermissions", String[].class, int.class); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - Integer resultObj; - try { - resultObj = (Integer) methodCheckPermission.invoke( - this, Manifest.permission.WRITE_EXTERNAL_STORAGE); - } catch (Throwable e) { - throw new RuntimeException(e); - } + Method methodCheckPermission; + Method method_shouldShowRequestPermissionRationale; + Method method_requestPermissions; + try { + methodCheckPermission = getClass().getMethod("checkSelfPermission", String.class); + method_shouldShowRequestPermissionRationale = + getClass().getMethod("shouldShowRequestPermissionRationale", String.class); + method_requestPermissions = + getClass().getMethod("requestPermissions", String[].class, int.class); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + Integer resultObj; + try { + resultObj = (Integer) methodCheckPermission.invoke( + this, Manifest.permission.WRITE_EXTERNAL_STORAGE); + } catch (Throwable e) { + throw new RuntimeException(e); + } - if (resultObj != PackageManager.PERMISSION_GRANTED) { + if (resultObj != PackageManager.PERMISSION_GRANTED) { - // Should we show an explanation? - Boolean aBoolean; - try { - aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this, - Manifest.permission.WRITE_EXTERNAL_STORAGE); - } catch (Exception e) { - throw new RuntimeException(e); - } - if (aBoolean) { + // Should we show an explanation? + Boolean aBoolean; + try { + aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this, + Manifest.permission.WRITE_EXTERNAL_STORAGE); + } catch (Exception e) { + throw new RuntimeException(e); + } + if (aBoolean) { - // Show an explanation to the user *asynchronously* -- don't block - // this thread waiting for the user's response! After the user - // sees the explanation, try again to request the permission. + // Show an explanation to the user *asynchronously* -- don't block + // this thread waiting for the user's response! After the user + // sees the explanation, try again to request the permission. - showExplanation(); + showExplanation(); - } else { + } else { - // No explanation needed, we can request the permission. + // No explanation needed, we can request the permission. - try { - method_requestPermissions.invoke(this, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - PERMISSION_WRITE_EXTERNAL_STORAGE); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } else startMainActivity(); - } + try { + method_requestPermissions.invoke(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + PERMISSION_WRITE_EXTERNAL_STORAGE); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } else startMainActivity(); + } - @Override - public void onRequestPermissionsResult(int requestCode, - String permissions[], int[] grantResults) { - switch (requestCode) { - case PERMISSION_WRITE_EXTERNAL_STORAGE: { - // If request is cancelled, the result arrays are empty. - if (grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + @Override + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + switch (requestCode) { + case PERMISSION_WRITE_EXTERNAL_STORAGE: { + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - // permission was granted, yay! Do the - // contacts-related task you need to do. + // permission was granted, yay! Do the + // contacts-related task you need to do. - startMainActivity(); + startMainActivity(); - } else { + } else { - // permission denied, boo! Disable the - // functionality that depends on this permission. - textview_retry.setText("SD card write permission denied, you need to allow this to continue"); - textview_retry.setVisibility(TextView.VISIBLE); - button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE); - } - return; - } + // permission denied, boo! Disable the + // functionality that depends on this permission. + textview_retry.setText("SD card write permission denied, you need to allow this to continue"); + textview_retry.setVisibility(TextView.VISIBLE); + button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE); + } + return; + } - // other 'case' lines to check for other - // permissions this app might request. - } - } + // other 'case' lines to check for other + // permissions this app might request. + } + } - private void startMainActivity() { - startActivity(new Intent(this, I2PDActivity.class)); - finish(); - } + private void startMainActivity() { + startActivity(new Intent(this, I2PDActivity.class)); + finish(); + } - private static final int SHOW_EXPLANATION_REQUEST = 1; // The request code - private void showExplanation() { - Intent intent = new Intent(this, I2PDPermsExplanationActivity.class); - startActivityForResult(intent, SHOW_EXPLANATION_REQUEST); - } + private static final int SHOW_EXPLANATION_REQUEST = 1; // The request code + private void showExplanation() { + Intent intent = new Intent(this, I2PDPermsExplanationActivity.class); + startActivityForResult(intent, SHOW_EXPLANATION_REQUEST); + } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - // Check which request we're responding to - if (requestCode == SHOW_EXPLANATION_REQUEST) { - // Make sure the request was successful - if (resultCode == RESULT_OK) { - // Request the permission - Method method_requestPermissions; - try { - method_requestPermissions = - getClass().getMethod("requestPermissions", String[].class, int.class); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - try { - method_requestPermissions.invoke(this, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - PERMISSION_WRITE_EXTERNAL_STORAGE); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - finish(); //close the app - } - } - } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // Check which request we're responding to + if (requestCode == SHOW_EXPLANATION_REQUEST) { + // Make sure the request was successful + if (resultCode == RESULT_OK) { + // Request the permission + Method method_requestPermissions; + try { + method_requestPermissions = + getClass().getMethod("requestPermissions", String[].class, int.class); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + try { + method_requestPermissions.invoke(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + PERMISSION_WRITE_EXTERNAL_STORAGE); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + finish(); //close the app + } + } + } } diff --git a/android/src/org/purplei2p/i2pd/I2PDPermsExplanationActivity.java b/android/src/org/purplei2p/i2pd/I2PDPermsExplanationActivity.java index d1641e78..885df75c 100644 --- a/android/src/org/purplei2p/i2pd/I2PDPermsExplanationActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDPermsExplanationActivity.java @@ -9,30 +9,30 @@ import android.widget.Button; public class I2PDPermsExplanationActivity extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_perms_explanation); - ActionBar actionBar = getActionBar(); - if(actionBar!=null)actionBar.setHomeButtonEnabled(false); - Button button_ok = (Button) findViewById(R.id.button_ok); - button_ok.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - returnFromActivity(); - } - }); - } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_perms_explanation); + ActionBar actionBar = getActionBar(); + if(actionBar!=null)actionBar.setHomeButtonEnabled(false); + Button button_ok = (Button) findViewById(R.id.button_ok); + button_ok.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + returnFromActivity(); + } + }); + } - private void returnFromActivity() { - Intent data = new Intent(); - Activity parent = getParent(); - if (parent == null) { - setResult(Activity.RESULT_OK, data); - } else { - parent.setResult(Activity.RESULT_OK, data); - } - finish(); - } + private void returnFromActivity() { + Intent data = new Intent(); + Activity parent = getParent(); + if (parent == null) { + setResult(Activity.RESULT_OK, data); + } else { + parent.setResult(Activity.RESULT_OK, data); + } + finish(); + } } diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java index 63867273..a929b703 100644 --- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java +++ b/android/src/org/purplei2p/i2pd/I2PD_JNI.java @@ -1,23 +1,25 @@ package org.purplei2p.i2pd; public class I2PD_JNI { - public static native String getABICompiledWith(); + public static native String getABICompiledWith(); + /** * returns error info if failed * returns "ok" if daemon initialized and started okay */ - public static native String startDaemon(); - //should only be called after startDaemon() success - public static native void stopDaemon(); + public static native String startDaemon(); - public static native void stopAcceptingTunnels(); + //should only be called after startDaemon() success + public static native void stopDaemon(); + + public static native void stopAcceptingTunnels(); public static native void startAcceptingTunnels(); public static native void onNetworkStateChanged(boolean isConnected); public static void loadLibraries() { - System.loadLibrary("gnustl_shared"); - System.loadLibrary("i2pd"); - } + //System.loadLibrary("c++_shared"); + System.loadLibrary("i2pd"); + } } diff --git a/android/src/org/purplei2p/i2pd/NetworkStateChangeReceiver.java b/android/src/org/purplei2p/i2pd/NetworkStateChangeReceiver.java index e2f284b0..437debe8 100644 --- a/android/src/org/purplei2p/i2pd/NetworkStateChangeReceiver.java +++ b/android/src/org/purplei2p/i2pd/NetworkStateChangeReceiver.java @@ -9,12 +9,12 @@ import android.net.NetworkInfo; public class NetworkStateChangeReceiver extends BroadcastReceiver { - private static final String TAG = "i2pd"; + private static final String TAG = "i2pd"; //api level 1 - @Override - public void onReceive(final Context context, final Intent intent) { - Log.d(TAG,"Network state change"); + @Override + public void onReceive(final Context context, final Intent intent) { + Log.d(TAG,"Network state change"); try { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo(); @@ -26,5 +26,5 @@ public class NetworkStateChangeReceiver extends BroadcastReceiver { } catch (Throwable tr) { Log.d(TAG,"",tr); } - } + } } diff --git a/android_binary_only/jni/Android.mk b/android_binary_only/jni/Android.mk index 645651a5..7e73b23d 100755 --- a/android_binary_only/jni/Android.mk +++ b/android_binary_only/jni/Android.mk @@ -26,43 +26,43 @@ include $(BUILD_EXECUTABLE) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_system -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_system.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_date_time -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_filesystem -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_program_options -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := crypto -LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libcrypto.a -LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include +LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a +LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := ssl -LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libssl.a -LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include +LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libssl.a +LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include LOCAL_STATIC_LIBRARIES := crypto include $(PREBUILT_STATIC_LIBRARY) diff --git a/android_binary_only/jni/Application.mk b/android_binary_only/jni/Application.mk index b8cdc2ab..9b437f6a 100755 --- a/android_binary_only/jni/Application.mk +++ b/android_binary_only/jni/Application.mk @@ -6,11 +6,8 @@ APP_ABI := armeabi-v7a #can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there. 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 +NDK_TOOLCHAIN_VERSION := clang +APP_STL := c++_static # Enable c++11 extensions in source code APP_CPPFLAGS += -std=c++11 -fvisibility=default -fPIE diff --git a/appveyor.yml b/appveyor.yml index bb9be2ec..138f93a8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.22.0.{build} +version: 2.23.0.{build} pull_requests: do_not_increment_build_number: true branches: diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 5876a0f7..fa92da05 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -364,8 +364,8 @@ if (NOT ZLIB_FOUND ) set( ZLIB_EXTRA -DASM686=ON "-DCMAKE_ASM_MASM_FLAGS=/W0 /safeseh" ) endif() ExternalProject_Add(zlib-project - URL http://zlib.net/zlib-1.2.8.tar.gz - URL_MD5 44d667c142d7cda120332623eab69f40 + URL https://zlib.net/zlib-1.2.11.tar.gz + URL_HASH SHA256=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 PREFIX ${CMAKE_CURRENT_BINARY_DIR}/zlib PATCH_COMMAND "${PATCH}" -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/cmake-zlib-static.patch && "${PATCH}" -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/cmake-zlib-amd64.patch diff --git a/contrib/certificates/reseed/reseedi2pnetin_at_mail.i2p.crt b/contrib/certificates/reseed/reseedi2pnetin_at_mail.i2p.crt new file mode 100644 index 00000000..b71696a3 --- /dev/null +++ b/contrib/certificates/reseed/reseedi2pnetin_at_mail.i2p.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF3DCCA8SgAwIBAgIQPxUlcrbHX/xdyJ09E36rJzANBgkqhkiG9w0BAQsFADB3 +MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK +ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEgMB4GA1UEAwwX +cmVzZWVkaTJwbmV0aW5AbWFpbC5pMnAwHhcNMTgxMjA3MTYzNDIxWhcNMjgxMjA3 +MTYzNDIxWjB3MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhY +MR4wHAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEg +MB4GA1UEAwwXcmVzZWVkaTJwbmV0aW5AbWFpbC5pMnAwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQC912NDk6x85uqB4gyQQcded0RVrbWehWOanDRv7kC3 +92jeziPbeMtqrLsfU1MdDtQiGijpNkQ/IIitPw+6vJAIh82gyOUZvsn2XOyb/Fz0 +Fu8OrDghwl39yK8kwtqCFw3VAgafgKxz2oRge9mxFBECi50vYEPIBwNhr4yc/opu +wWUmzmRyX4gD7vKmRU6ZTwX4LXnwdl+5VbW3updcZKsDuTnKvC9FGhDRR9kIk2G9 +43sLN263nCYPykP7DaB1cUdi1vDEMw5dot+eu16qTIbuypEvYNvbB/9FyCQllm1h +vBbSku3IYpcnRPmoeyhoR/MmCySRbK5R4SrSsVD1YBpwxgn0Q4+fzEgFzT9P4oez +HkDGKVP2HdgmXx9j36fEqqvjqzRleWDwEWwIZVRLCFO+hhhT3JAjnNGJTWv1SQGB +8tz9nyYTJuhvyHE/CO5owFeCdeOGMq2KPge9w34T+mvewTEEhGU8yRAt8Xp8s5Y9 +RCUGvuQ79+edRtj7FJg7yVB8pAQ+VB9msNQvzrTnPYC9Wo7chJhBiraMiIabzIhC +f34Gg9lkX1N0dVND5rnZWwzBM6JhNG1iZZCRHVPnXdZRixUlqmFpCP/eekshksj/ +6UP/WeGA6X4HyEsC6QEf7eMhcHYjyyTzYagKrwCHg77fmIjF8rmpP2LqWSQW8bDD +uQIDAQABo2QwYjAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIG +CCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wIAYDVR0OBBkEF3Jlc2VlZGkycG5l +dGluQG1haWwuaTJwMA0GCSqGSIb3DQEBCwUAA4ICAQCWpXs6iuTy/w2R7q7Ua6vl +JYZwbQ+czk5ydzkBgcNkMMMNRT7sZR9xYvV+ftiL4bFQP/3ZJyo7cYz2Q6+M3oAm +YDcZWBkLUVihSlMxhWwmeFTKV2EL+bzwY1V/cy7wgukKnFIes75dLP/v25jgjdlw +Xe6R+fQM0EoHeVzzrWk/qYp6oEwtQXfZnUu/Bf45hRnnHBzzh1wCql41vbEs3Niq ++SVwY1wLT0yC1L8HqjCLX1/L5PAXxbvEGzwnXSkLKK4bPxdmVDZvS9uzXrWmTbNi +HpKIFnOif16zSgyeaOM7HETIJuVzgooUMtt+Vsr1VGdtm6K7I9J5C+rX/ckU8oaX +UjmzhWXudN0VTslogsKUCV6xG2CskeE3wnuT8HYXz9NMw6c/kIGH4hY7LcfU8Teu +QjSy2RRvy6InmZNV5sY9lzzO6romEycSoUlpCa3Ltb/5KKoYZFTsXr8suqJk89lC +e+TVMHqOZdLK/usqQDcafLypHpw9SH2Tg4jrzV/zLqacbjx6bZD5IrpY0Gf7BXg/ +pikwyA9c490G6ZcWrSEP8bzh6LL2rA2AwxaeJJNVyLHCSLrn/7DezM5J/qhd90Qg +kcZGJrUOCSWl6mDvUZn5XiQ955XwOnZQ+wsM85B3CVX22x5bp0SYWHCQBPnthPwP +Q5DD3jExbpwG5n35HEcHYw== +-----END CERTIFICATE----- diff --git a/contrib/certificates/reseed/zmx_at_mail.i2p.crt b/contrib/certificates/reseed/zmx_at_mail.i2p.crt deleted file mode 100644 index 41f4cc75..00000000 --- a/contrib/certificates/reseed/zmx_at_mail.i2p.crt +++ /dev/null @@ -1,34 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIF1TCCA72gAwIBAgIRAJBHySZnvNg3lU00//fwny4wDQYJKoZIhvcNAQELBQAw -bDELMAkGA1UEBhMCWFgxHjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEM -MAoGA1UECxMDSTJQMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxFTATBgNVBAMM -DHpteEBtYWlsLmkycDAeFw0xNjAxMDExNzE5MTlaFw0yNjAxMDExNzE5MTlaMGwx -CzAJBgNVBAYTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAK -BgNVBAsTA0kyUDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMRUwEwYDVQQDDAx6 -bXhAbWFpbC5pMnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnDGVU -iC6pNJ3mfqZRQYACUbQ6SQI05yh3PawHqQrmiW3rD05SXBCF+6b2EpA4U0ThFhtm -cGyUObtBL749x03SUYcWhknZNq+zrvb9AypaKFpIx2DjFT8vQadn0l71cNaiwxX1 -Wzk1Au6mh9SFPvH5gDF9SQol7dYYKnn9L61V7hvH9fDiZyoi9Cz3ifE3SAWoM2PJ -lBzbu16tyQE94HvIdZhp8cE/6/kiW1wjSqvT9dfZ4gMuZHOF5E8lkq/bg8tPa/oj -rglY7ozT/9/IWtJ7ERcDyepmKjq7+Xx4sNXTvc+B7D4XfMjhaxFLtV/kLQ9mqx8R -UPvPy+atw7mlfUf822YFSft2jBAxNJwCPdhXuuFkTUTIk9YXcChUCSPyv17gej/P -A++/hdhYI/kIs8AVsaJjytTqwU3A2Pt1QogM8VLsSJ2NY7gSzj868nzIZ4OuoWbz -KzpnS/3bQkYHrqMtDIjRr1bOudxbu2/ben5v8Qg9wE9uV/8YNhhaKAcfJOV6OXfF -MYec9DOEVVvECOfYUX35Vtn/w7E6SSL7Gu6QEWviA4Bf2XBh1YFX0ZpBUMY9awNz -7PDf+z+YGkrQ6ifvLPW9vHW3lmouRWzo5NgJIIvLYBJKmxkf08p94s8YailjiGzA -dJWXg3HDWgwMe7BY7AJQbU/o35Vv+0CroUsR3wIDAQABo3IwcDAOBgNVHQ8BAf8E -BAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA8GA1UdEwEB/wQF -MAMBAf8wFQYDVR0OBA4EDHpteEBtYWlsLmkycDAXBgNVHSMEEDAOgAx6bXhAbWFp -bC5pMnAwDQYJKoZIhvcNAQELBQADggIBAATXH/PNdF40DjD9DcF4W5Ot7CWGskDY -cR4ywtvU2EcDNEwv4q0FPEpxy5LPaUmTKQ6fsRXUZizjaPLpgCLbv9qYc5xRLrSi -yk9mrAbJ1iEU+DfHHBcS1VQWtc7+9LA0W3ZIA+pygjPjTxwQqQAcjn4BdfaIQpVa -VJ2kl5JtbTuYHL80GAQFYnzCCa5GKM7zgcLsyO1mQwnpDvFeSlKJJ6rx1QjhlJu+ -90Ig8IOBCIgokfUv9OdYBl6rmDq9i9pvqJU+H4VepqE1jnDAO+YqQ4laZj7LVVM8 -I9uia+8RKntUOBkUkLB3ouGdVJUmp3kGrkExxUdDHYP9VNJG6ZMwyKO8HXGtoTsR -TFWIEIbq/biBL9obM/d8fRV5xpfZNbPi6cRzw8REY9UIKECKr7B2B6PnDVVQIQw0 -7SCVjmSYWexOqoJPZ1L7/AZDP/tFvx32cWwCszj5jqUaPo9ZNPb6DxQJDdNaZrFH -3CA+PbiaeEz9IH0yBY/6wQgO0k3qOyFQrlkC+YRoYUQNc+6xS38l5ZnYUtBAy8ms -N43eODQ/OhsLzy6PwwXdzvR/0g18SrQyTLfbn2b/kwvbC8Qe40QFfkOf5lPXjdnP -Ii/lcMuvDMlMhoWGFwWm5bkkXE81TKnFXu2/IMsW6HYb3oiTjkaCap22fCr9l0jj -fNr8P7NIRyZ8 ------END CERTIFICATE----- diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 7888878d..fa2e6094 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.22.0 +Version: 2.23.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -47,8 +47,13 @@ cd build -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ +%if 0%{?fedora} > 29 + -DBUILD_SHARED_LIBS:BOOL=OFF \ + . +%else -DBUILD_SHARED_LIBS:BOOL=OFF %endif +%endif make %{?_smp_mflags} @@ -105,6 +110,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Jan 21 2019 orignal - 2.23.0 +- update to 2.23.0 + * Fri Nov 09 2018 r4sas - 2.22.0 - add support of tunnelsdir option diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index f7577f0e..12f11175 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.22.0 +Version: 2.23.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -45,8 +45,13 @@ cd build -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ +%if 0%{?fedora} > 29 + -DBUILD_SHARED_LIBS:BOOL=OFF \ + . +%else -DBUILD_SHARED_LIBS:BOOL=OFF %endif +%endif make %{?_smp_mflags} @@ -103,6 +108,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Jan 21 2019 orignal - 2.23.0 +- update to 2.23.0 + * Fri Nov 09 2018 r4sas - 2.22.0 - update to 2.22.0 - add support of tunnelsdir option diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index ccf2640c..a9bdd3f6 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -358,7 +358,7 @@ namespace http { { s << "
\r\n\r\n

\r\n"; for(auto& it: dest->GetLeaseSets ()) - s << it.second->GetIdentHash ().ToBase32 () << "
\r\n"; + s << it.second->GetIdentHash ().ToBase32 () << " " << (int)it.second->GetStoreType () << "
\r\n"; s << "

\r\n
\r\n"; } else s << "LeaseSets: 0
\r\n"; @@ -462,24 +462,35 @@ namespace http { [&s, &counter](const i2p::data::IdentHash dest, std::shared_ptr leaseSet) { // create copy of lease set so we extract leases - i2p::data::LeaseSet ls(leaseSet->GetBuffer(), leaseSet->GetBufferLen()); + auto storeType = leaseSet->GetStoreType (); + std::unique_ptr ls; + if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET) + ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen())); + else + ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen())); + if (!ls) return; s << "
\r\n"; - if (!ls.IsValid()) + if (!ls->IsValid()) s << "
!! Invalid !!
\r\n"; s << "
\r\n"; s << "\r\n

\r\n"; - s << "Expires: " << ConvertTime(ls.GetExpirationTime()) << "
\r\n"; - auto leases = ls.GetNonExpiredLeases(); - s << "Non Expired Leases: " << leases.size() << "
\r\n"; - for ( auto & l : leases ) - { - s << "Gateway: " << l->tunnelGateway.ToBase64() << "
\r\n"; - s << "TunnelID: " << l->tunnelID << "
\r\n"; - s << "EndDate: " << ConvertTime(l->endDate) << "
\r\n"; - } + s << "Store type: " << (int)storeType << "
\r\n"; + s << "Expires: " << ConvertTime(ls->GetExpirationTime()) << "
\r\n"; + if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET || storeType == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2) + { + // leases information is available + auto leases = ls->GetNonExpiredLeases(); + s << "Non Expired Leases: " << leases.size() << "
\r\n"; + for ( auto & l : leases ) + { + s << "Gateway: " << l->tunnelGateway.ToBase64() << "
\r\n"; + s << "TunnelID: " << l->tunnelID << "
\r\n"; + s << "EndDate: " << ConvertTime(l->endDate) << "
\r\n"; + } + } s << "

\r\n
\r\n
\r\n"; } ); @@ -851,22 +862,8 @@ namespace http { auto provided = req.GetHeader ("Authorization"); if (provided.length () > 0) { - bool result = false; - - std::string expected = user + ":" + pass; - size_t b64_sz = i2p::data::Base64EncodingBufferSize(expected.length()) + 1; - char * b64_creds = new char[b64_sz]; - std::size_t len = 0; - len = i2p::data::ByteStreamToBase64((unsigned char *)expected.c_str(), expected.length(), b64_creds, b64_sz); - /* if we decoded properly then check credentials */ - if(len) { - b64_creds[len] = '\0'; - expected = "Basic "; - expected += b64_creds; - result = expected == provided; - } - delete [] b64_creds; - return result; + std::string expected = "Basic " + i2p::data::ToBase64Standard (user + ":" + pass); + if (expected == provided) return true; } LogPrint(eLogWarning, "HTTPServer: auth failure from ", m_Socket->remote_endpoint().address ()); diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index 6ac87cbb..572292ee 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -569,8 +569,8 @@ namespace client EVP_PKEY_assign_RSA (pkey, rsa); X509 * x509 = X509_new (); ASN1_INTEGER_set (X509_get_serialNumber (x509), 1); - X509_gmtime_adj (X509_get_notBefore (x509), 0); - X509_gmtime_adj (X509_get_notAfter (x509), I2P_CONTROL_CERTIFICATE_VALIDITY*24*60*60); // expiration + X509_gmtime_adj (X509_getm_notBefore (x509), 0); + X509_gmtime_adj (X509_getm_notAfter (x509), I2P_CONTROL_CERTIFICATE_VALIDITY*24*60*60); // expiration X509_set_pubkey (x509, pkey); // public key X509_NAME * name = X509_get_subject_name (x509); X509_NAME_add_entry_by_txt (name, "C", MBSTRING_ASC, (unsigned char *)"A1", -1, -1, 0); // country (Anonymous proxy) diff --git a/debian/changelog b/debian/changelog index eb48dbdf..0538427d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +i2pd (2.23.0-1) unstable; urgency=medium + + * updated to version 2.23.0/0.9.38 + * update docs, dirs, install, links files + + -- orignal Mon, 21 Jan 2019 16:00:00 +0000 + i2pd (2.22.0-1) unstable; urgency=medium * updated to version 2.22.0/0.9.37 diff --git a/libi2pd/ChaCha20.cpp b/libi2pd/ChaCha20.cpp index 30e02f42..91a1fbd5 100644 --- a/libi2pd/ChaCha20.cpp +++ b/libi2pd/ChaCha20.cpp @@ -11,7 +11,7 @@ #include "ChaCha20.h" -#if LEGACY_OPENSSL +#if !OPENSSL_AEAD_CHACHA20_POLY1305 namespace i2p { namespace crypto @@ -111,7 +111,8 @@ void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz) buf[i] ^= state.block.data[state.offset + i]; buf += s; sz -= s; - state.offset = 0; + state.offset += s; + if (state.offset >= chacha::blocksize) state.offset = 0; } for (size_t i = 0; i < sz; i += chacha::blocksize) { diff --git a/libi2pd/ChaCha20.h b/libi2pd/ChaCha20.h index a5a8aafc..b2eec320 100644 --- a/libi2pd/ChaCha20.h +++ b/libi2pd/ChaCha20.h @@ -16,7 +16,7 @@ #include #include "Crypto.h" -#if LEGACY_OPENSSL +#if !OPENSSL_AEAD_CHACHA20_POLY1305 namespace i2p { namespace crypto diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 0403275f..89531f5a 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -192,7 +192,7 @@ namespace config { "https://netdb.i2p2.no/," // "https://us.reseed.i2p2.no:444/," // mamoth's shit // "https://uk.reseed.i2p2.no:444/," // mamoth's shit - "https://i2p-0.manas.ca:8443/," + "https://reseed.i2p.net.in/," "https://download.xxlspeed.com/," "https://reseed-fr.i2pd.xyz/," "https://reseed.atomike.ninja/," diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 28df1399..0630091a 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -9,7 +9,7 @@ #include "TunnelBase.h" #include #include "Crypto.h" -#if LEGACY_OPENSSL +#if !OPENSSL_AEAD_CHACHA20_POLY1305 #include "ChaCha20.h" #include "Poly1305.h" #endif @@ -282,6 +282,7 @@ namespace crypto { #if OPENSSL_X25519 m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL); + m_Pkey = nullptr; #else m_Ctx = BN_CTX_new (); #endif @@ -304,8 +305,7 @@ namespace crypto { #if OPENSSL_X25519 EVP_PKEY_CTX_free (m_Ctx); - if (m_Pkey) - EVP_PKEY_free (m_Pkey); + if (m_Pkey) EVP_PKEY_free (m_Pkey); #else BN_CTX_free (m_Ctx); #endif @@ -314,7 +314,11 @@ namespace crypto void X25519Keys::GenerateKeys () { #if OPENSSL_X25519 - m_Pkey = nullptr; + if (m_Pkey) + { + EVP_PKEY_free (m_Pkey); + m_Pkey = nullptr; + } EVP_PKEY_keygen_init (m_Ctx); EVP_PKEY_keygen (m_Ctx, &m_Pkey); EVP_PKEY_CTX_free (m_Ctx); @@ -1086,7 +1090,32 @@ namespace crypto if (len < msgLen) return false; if (encrypt && len < msgLen + 16) return false; bool ret = true; -#if LEGACY_OPENSSL +#if OPENSSL_AEAD_CHACHA20_POLY1305 + int outlen = 0; + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new (); + if (encrypt) + { + EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0); + EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce); + EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen); + EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen); + EVP_EncryptFinal_ex(ctx, buf, &outlen); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen); + } + else + { + EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (uint8_t *)(msg + msgLen)); + EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce); + EVP_DecryptUpdate(ctx, NULL, &outlen, ad, adLen); + EVP_DecryptUpdate(ctx, buf, &outlen, msg, msgLen); + ret = EVP_DecryptFinal_ex(ctx, buf + outlen, &outlen) > 0; + } + + EVP_CIPHER_CTX_free (ctx); +#else chacha::Chacha20State state; // generate one time poly key chacha::Chacha20Init (state, nonce, key, 0); @@ -1145,39 +1174,25 @@ namespace crypto polyHash.Finish (tag); if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided } -#else - int outlen = 0; - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new (); - if (encrypt) - { - EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0); - EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce); - EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen); - EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen); - EVP_EncryptFinal_ex(ctx, buf, &outlen); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen); - } - else - { - EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (uint8_t *)(msg + msgLen)); - EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce); - EVP_DecryptUpdate(ctx, NULL, &outlen, ad, adLen); - EVP_DecryptUpdate(ctx, buf, &outlen, msg, msgLen); - ret = EVP_DecryptFinal_ex(ctx, buf + outlen, &outlen) > 0; - } - - EVP_CIPHER_CTX_free (ctx); #endif return ret; } - void AEADChaCha20Poly1305Encrypt (std::vector >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac) + void AEADChaCha20Poly1305Encrypt (const std::vector >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac) { if (bufs.empty ()) return; -#if LEGACY_OPENSSL +#if OPENSSL_AEAD_CHACHA20_POLY1305 + int outlen = 0; + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new (); + EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0); + EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce); + for (const auto& it: bufs) + EVP_EncryptUpdate(ctx, it.first, &outlen, it.first, it.second); + EVP_EncryptFinal_ex(ctx, NULL, &outlen); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac); + EVP_CIPHER_CTX_free (ctx); +#else chacha::Chacha20State state; // generate one time poly key chacha::Chacha20Init (state, nonce, key, 0); @@ -1188,10 +1203,10 @@ namespace crypto // encrypt buffers Chacha20SetCounter (state, 1); size_t size = 0; - for (auto& it: bufs) + for (const auto& it: bufs) { - chacha::Chacha20Encrypt (state, (uint8_t *)it.first, it.second); - polyHash.Update ((uint8_t *)it.first, it.second); // after encryption + chacha::Chacha20Encrypt (state, it.first, it.second); + polyHash.Update (it.first, it.second); // after encryption size += it.second; } // padding @@ -1209,18 +1224,7 @@ namespace crypto htole64buf (padding + 8, size); polyHash.Update (padding, 16); // MAC - polyHash.Finish ((uint64_t *)mac); -#else - int outlen = 0; - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new (); - EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0); - EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce); - for (auto& it: bufs) - EVP_EncryptUpdate(ctx, (uint8_t *)it.first, &outlen, (uint8_t *)it.first, it.second); - EVP_EncryptFinal_ex(ctx, NULL, &outlen); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac); - EVP_CIPHER_CTX_free (ctx); + polyHash.Finish ((uint64_t *)mac); #endif } @@ -1238,11 +1242,13 @@ namespace crypto } }*/ - + void InitCrypto (bool precomputation) { - i2p::cpu::Detect (); + i2p::cpu::Detect (); +#if LEGACY_OPENSSL SSL_library_init (); +#endif /* auto numLocks = CRYPTO_num_locks(); for (int i = 0; i < numLocks; i++) m_OpenSSLMutexes.emplace_back (new std::mutex); @@ -1277,3 +1283,4 @@ namespace crypto } } } + diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 79d16e50..46baf095 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -23,6 +23,8 @@ // recognize openssl version and features #if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL # define LEGACY_OPENSSL 1 +# define X509_getm_notBefore X509_get_notBefore +# define X509_getm_notAfter X509_get_notAfter #else # define LEGACY_OPENSSL 0 # if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 @@ -30,6 +32,9 @@ # define OPENSSL_X25519 1 # define OPENSSL_SIPHASH 1 # endif +# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them +# define OPENSSL_AEAD_CHACHA20_POLY1305 1 +# endif #endif namespace i2p @@ -283,7 +288,7 @@ namespace crypto // AEAD/ChaCha20/Poly1305 bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt); // msgLen is len without tag - void AEADChaCha20Poly1305Encrypt (std::vector >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad + void AEADChaCha20Poly1305Encrypt (const std::vector >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad // init and terminate void InitCrypto (bool precomputation); diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 0dff7584..5584b687 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -22,6 +22,7 @@ namespace crypto virtual ~CryptoKeyDecryptor () {}; virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding) = 0; // 512/514 bytes encrypted, 222 bytes data + virtual size_t GetPublicKeyLen () const = 0; // we need it to set key in LS2 }; // ElGamal @@ -43,7 +44,8 @@ namespace crypto ElGamalDecryptor (const uint8_t * priv); bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding); - + size_t GetPublicKeyLen () const { return 256; }; + private: uint8_t m_PrivateKey[256]; @@ -73,7 +75,8 @@ namespace crypto ECIESP256Decryptor (const uint8_t * priv); ~ECIESP256Decryptor (); bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding); - + size_t GetPublicKeyLen () const { return 64; }; + private: EC_GROUP * m_Curve; @@ -105,7 +108,8 @@ namespace crypto ECIESGOSTR3410Decryptor (const uint8_t * priv); ~ECIESGOSTR3410Decryptor (); bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding); - + size_t GetPublicKeyLen () const { return 64; }; + private: BIGNUM * m_PrivateKey; diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index ad7725fc..6f7ef8f0 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -16,7 +16,8 @@ namespace client LeaseSetDestination::LeaseSetDestination (bool isPublic, const std::map * params): m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic), m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), - m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service) + m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service), + m_LeaseSetType (DEFAULT_LEASESET_TYPE) { int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH; int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY; @@ -66,6 +67,9 @@ namespace client if (it != params->end ()) m_Nickname = it->second; // otherwise we set default nickname in Start when we know local address } + it = params->find (I2CP_PARAM_LEASESET_TYPE); + if (it != params->end ()) + m_LeaseSetType = std::stoi(it->second); } } catch (std::exception & ex) @@ -357,7 +361,8 @@ namespace client } i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET); std::shared_ptr leaseSet; - if (buf[DATABASE_STORE_TYPE_OFFSET] == 1) // LeaseSet + if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET || // 1 + buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2) // 3 { LogPrint (eLogDebug, "Destination: Remote LeaseSet"); std::lock_guard lock(m_RemoteLeaseSetsMutex); @@ -382,7 +387,10 @@ namespace client } else { - leaseSet = std::make_shared (buf + offset, len - offset); + if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET) + leaseSet = std::make_shared (buf + offset, len - offset); // LeaseSet + else + leaseSet = std::make_shared (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset); // LeaseSet2 if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key) { if (leaseSet->GetIdentHash () != GetIdentHash ()) @@ -769,12 +777,20 @@ namespace client m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(GetService()) { - if (isPublic) + m_EncryptionKeyType = GetIdentity ()->GetCryptoKeyType (); + // extract encryption type params for LS2 + if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 && params) + { + auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE); + if (it != params->end ()) + m_EncryptionKeyType = std::stoi(it->second); + } + + if (isPublic && m_EncryptionKeyType == GetIdentity ()->GetCryptoKeyType ()) // TODO: presist key type PersistTemporaryKeys (); else - i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), - m_EncryptionPrivateKey, m_EncryptionPublicKey); - m_Decryptor = m_Keys.CreateDecryptor (m_EncryptionPrivateKey); + i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey); + m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_EncryptionKeyType, m_EncryptionPrivateKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); @@ -1004,9 +1020,10 @@ namespace client return; } - LogPrint (eLogInfo, "Destination: Creating new temporary keys for address ", ident, ".b32.i2p"); - i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), - m_EncryptionPrivateKey, m_EncryptionPublicKey); + LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p"); + memset (m_EncryptionPrivateKey, 0, 256); + memset (m_EncryptionPublicKey, 0, 256); + i2p::data::PrivateKeys::GenerateCryptoKeyPair (GetIdentity ()->GetCryptoKeyType (), m_EncryptionPrivateKey, m_EncryptionPublicKey); std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); if (f1) { @@ -1019,9 +1036,22 @@ namespace client void ClientDestination::CreateNewLeaseSet (std::vector > tunnels) { - auto leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), m_EncryptionPublicKey, tunnels); - // sign - Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO + i2p::data::LocalLeaseSet * leaseSet = nullptr; + if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) + { + leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), m_EncryptionPublicKey, tunnels); + // sign + Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); + } + else + { + // standard LS2 (type 3) assumed for now. TODO: implement others + auto keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256; + leaseSet = new i2p::data::LocalLeaseSet2 (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2, + GetIdentity (), m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels); + // sign + Sign (leaseSet->GetBuffer () - 1, leaseSet->GetBufferLen () - leaseSet->GetSignatureLen () + 1, leaseSet->GetSignature ()); // + leading store type + } SetLeaseSet (leaseSet); } diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 3f261bc9..847ecb1a 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -52,6 +52,9 @@ namespace client const int DEFAULT_TAGS_TO_SEND = 40; const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname"; const char I2CP_PARAM_OUTBOUND_NICKNAME[] = "outbound.nickname"; + const char I2CP_PARAM_LEASESET_TYPE[] = "i2cp.leaseSetType"; + const int DEFAULT_LEASESET_TYPE = 1; + const char I2CP_PARAM_LEASESET_ENCRYPTION_TYPE[] = "i2cp.leaseSetEncType"; // latency const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min"; @@ -122,6 +125,7 @@ namespace client protected: void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet); + int GetLeaseSetType () const { return m_LeaseSetType; }; virtual void CleanupDestination () {}; // additional clean up in derived classes // I2CP virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0; @@ -165,6 +169,7 @@ namespace client boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_PublishDelayTimer, m_CleanupTimer; std::string m_Nickname; + int m_LeaseSetType; public: @@ -238,6 +243,7 @@ namespace client i2p::data::PrivateKeys m_Keys; uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256]; + i2p::data::CryptoKeyType m_EncryptionKeyType; std::shared_ptr m_Decryptor; int m_StreamingAckDelay; diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index 3fb5d862..b7cbf7d4 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -64,7 +64,8 @@ namespace data i2p::crypto::bn2buf (x, signingKey, 32); i2p::crypto::bn2buf (y, signingKey + 32, 32); BN_free (x); BN_free (y); - verifier = std::make_shared(signingKey); + verifier = std::make_shared(); + verifier->SetPublicKey (signingKey); } else LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); diff --git a/libi2pd/Gost.cpp b/libi2pd/Gost.cpp index 5773fe15..c401f8be 100644 --- a/libi2pd/Gost.cpp +++ b/libi2pd/Gost.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include "I2PEndian.h" diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 7f4d1ca3..2fc1df3b 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -264,7 +264,7 @@ namespace i2p auto m = NewI2NPShortMessage (); uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32); - payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet + payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); size_t size = DATABASE_STORE_HEADER_SIZE; memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ()); @@ -280,7 +280,7 @@ namespace i2p auto m = NewI2NPShortMessage (); uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32); - payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet + payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // LeaseSet or LeaseSet2 htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, replyToken); size_t size = DATABASE_STORE_HEADER_SIZE; if (replyToken && replyTunnel) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 0e49b8ad..02658ecc 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -318,62 +318,56 @@ namespace data return CRYPTO_KEY_TYPE_ELGAMAL; } - void IdentityEx::CreateVerifier () const + i2p::crypto::Verifier * IdentityEx::CreateVerifier (SigningKeyType keyType) { - if (m_Verifier) return; // don't create again - auto keyType = GetSigningKeyType (); switch (keyType) { case SIGNING_KEY_TYPE_DSA_SHA1: - UpdateVerifier (new i2p::crypto::DSAVerifier (m_StandardIdentity.signingKey)); - break; + return new i2p::crypto::DSAVerifier (); case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: - { - size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64 - UpdateVerifier (new i2p::crypto::ECDSAP256Verifier (m_StandardIdentity.signingKey + padding)); - break; - } + return new i2p::crypto::ECDSAP256Verifier (); case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: - { - size_t padding = 128 - i2p::crypto::ECDSAP384_KEY_LENGTH; // 32 = 128 - 96 - UpdateVerifier (new i2p::crypto::ECDSAP384Verifier (m_StandardIdentity.signingKey + padding)); - break; - } + return new i2p::crypto::ECDSAP384Verifier (); case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: - { - uint8_t signingKey[i2p::crypto::ECDSAP521_KEY_LENGTH]; - memcpy (signingKey, m_StandardIdentity.signingKey, 128); - size_t excessLen = i2p::crypto::ECDSAP521_KEY_LENGTH - 128; // 4 = 132- 128 - memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types - UpdateVerifier (new i2p::crypto::ECDSAP521Verifier (signingKey)); - break; - } + return new i2p::crypto::ECDSAP521Verifier (); + case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: + return new i2p::crypto::EDDSA25519Verifier (); + case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: + return new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA); + case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: + return new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512); case SIGNING_KEY_TYPE_RSA_SHA256_2048: case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA512_4096: LogPrint (eLogError, "Identity: RSA signing key type ", (int)keyType, " is not supported"); break; - case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: - { - size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32 - UpdateVerifier (new i2p::crypto::EDDSA25519Verifier (m_StandardIdentity.signingKey + padding)); - break; - } - case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: - { - size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64 - UpdateVerifier (new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA, m_StandardIdentity.signingKey + padding)); - break; - } - case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: - { - // zero padding - UpdateVerifier (new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512, m_StandardIdentity.signingKey)); - break; - } default: LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported"); } + return nullptr; + } + + void IdentityEx::CreateVerifier () const + { + if (m_Verifier) return; // don't create again + auto verifier = CreateVerifier (GetSigningKeyType ()); + if (verifier) + { + auto keyLen = verifier->GetPublicKeyLen (); + if (keyLen <= 128) + verifier->SetPublicKey (m_StandardIdentity.signingKey + 128 - keyLen); + else + { + // for P521 + uint8_t * signingKey = new uint8_t[keyLen]; + memcpy (signingKey, m_StandardIdentity.signingKey, 128); + size_t excessLen = keyLen - 128; + memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types + verifier->SetPublicKey (signingKey); + delete[] signingKey; + } + } + UpdateVerifier (verifier); } void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const @@ -407,10 +401,9 @@ namespace data m_Verifier = nullptr; } - std::shared_ptr IdentityEx::CreateEncryptor (const uint8_t * key) const + std::shared_ptr IdentityEx::CreateEncryptor (CryptoKeyType keyType, const uint8_t * key) { - if (!key) key = GetEncryptionPublicKey (); // use publicKey - switch (GetCryptoKeyType ()) + switch (keyType) { case CRYPTO_KEY_TYPE_ELGAMAL: return std::make_shared(key); @@ -423,9 +416,15 @@ namespace data return std::make_shared(key); break; default: - LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)GetCryptoKeyType ()); + LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)keyType); }; return nullptr; + } + + std::shared_ptr IdentityEx::CreateEncryptor (const uint8_t * key) const + { + if (!key) key = GetEncryptionPublicKey (); // use publicKey + return CreateEncryptor (GetCryptoKeyType (), key); } PrivateKeys& PrivateKeys::operator=(const Keys& keys) diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 584e6475..2a91ef48 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -91,11 +91,11 @@ namespace data size_t ToBuffer (uint8_t * buf, size_t len) const; size_t FromBase64(const std::string& s); std::string ToBase64 () const; - const Identity& GetStandardIdentity () const { return m_StandardIdentity; }; + const Identity& GetStandardIdentity () const { return m_StandardIdentity; }; const IdentHash& GetIdentHash () const { return m_IdentHash; }; - const uint8_t * GetEncryptionPublicKey () const { return m_StandardIdentity.publicKey; }; - uint8_t * GetEncryptionPublicKeyBuffer () { return m_StandardIdentity.publicKey; }; + const uint8_t * GetEncryptionPublicKey () const { return m_StandardIdentity.publicKey; }; + uint8_t * GetEncryptionPublicKeyBuffer () { return m_StandardIdentity.publicKey; }; std::shared_ptr CreateEncryptor (const uint8_t * key) const; size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; }; size_t GetSigningPublicKeyLen () const; @@ -107,9 +107,11 @@ namespace data CryptoKeyType GetCryptoKeyType () const; void DropVerifier () const; // to save memory - bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); } + bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); } + void RecalculateIdentHash(uint8_t * buff=nullptr); - void RecalculateIdentHash(uint8_t * buff=nullptr); + static i2p::crypto::Verifier * CreateVerifier (SigningKeyType keyType); + static std::shared_ptr CreateEncryptor (CryptoKeyType keyType, const uint8_t * key); private: diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 8b6063fc..3d72401d 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -12,8 +12,14 @@ namespace i2p namespace data { + LeaseSet::LeaseSet (bool storeLeases): + m_IsValid (false), m_StoreLeases (storeLeases), m_ExpirationTime (0), m_EncryptionKey (nullptr), + m_Buffer (nullptr), m_BufferLen (0) + { + } + LeaseSet::LeaseSet (const uint8_t * buf, size_t len, bool storeLeases): - m_IsValid (true), m_StoreLeases (storeLeases), m_ExpirationTime (0) + m_IsValid (true), m_StoreLeases (storeLeases), m_ExpirationTime (0), m_EncryptionKey (nullptr) { m_Buffer = new uint8_t[len]; memcpy (m_Buffer, buf, len); @@ -51,7 +57,11 @@ namespace data m_IsValid = false; return; } - memcpy (m_EncryptionKey, m_Buffer + size, 256); + if (m_StoreLeases) + { + if (!m_EncryptionKey) m_EncryptionKey = new uint8_t[256]; + memcpy (m_EncryptionKey, m_Buffer + size, 256); + } size += 256; // encryption key size += m_Identity->GetSigningPublicKeyLen (); // unused signing key uint8_t num = m_Buffer[size]; @@ -64,12 +74,7 @@ namespace data return; } - // reset existing leases - if (m_StoreLeases) - for (auto& it: m_Leases) - it->isUpdated = false; - else - m_Leases.clear (); + UpdateLeasesBegin (); // process leases m_ExpirationTime = 0; @@ -84,26 +89,7 @@ namespace data leases += 4; // tunnel ID lease.endDate = bufbe64toh (leases); leases += 8; // end date - if (ts < lease.endDate + LEASE_ENDDATE_THRESHOLD) - { - if (lease.endDate > m_ExpirationTime) - m_ExpirationTime = lease.endDate; - if (m_StoreLeases) - { - auto ret = m_Leases.insert (std::make_shared(lease)); - if (!ret.second) (*ret.first)->endDate = lease.endDate; // update existing - (*ret.first)->isUpdated = true; - // check if lease's gateway is in our netDb - if (!netdb.FindRouter (lease.tunnelGateway)) - { - // if not found request it - LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting"); - netdb.RequestDestination (lease.tunnelGateway); - } - } - } - else - LogPrint (eLogWarning, "LeaseSet: Lease is expired already "); + UpdateLease (lease, ts); } if (!m_ExpirationTime) { @@ -112,6 +98,29 @@ namespace data return; } m_ExpirationTime += LEASE_ENDDATE_THRESHOLD; + + UpdateLeasesEnd (); + + // verify + if (verifySignature && !m_Identity->Verify (m_Buffer, leases - m_Buffer, leases)) + { + LogPrint (eLogWarning, "LeaseSet: verification failed"); + m_IsValid = false; + } + } + + void LeaseSet::UpdateLeasesBegin () + { + // reset existing leases + if (m_StoreLeases) + for (auto& it: m_Leases) + it->isUpdated = false; + else + m_Leases.clear (); + } + + void LeaseSet::UpdateLeasesEnd () + { // delete old leases if (m_StoreLeases) { @@ -126,13 +135,30 @@ namespace data ++it; } } + } - // verify - if (verifySignature && !m_Identity->Verify (m_Buffer, leases - m_Buffer, leases)) + void LeaseSet::UpdateLease (const Lease& lease, uint64_t ts) + { + if (ts < lease.endDate + LEASE_ENDDATE_THRESHOLD) { - LogPrint (eLogWarning, "LeaseSet: verification failed"); - m_IsValid = false; + if (lease.endDate > m_ExpirationTime) + m_ExpirationTime = lease.endDate; + if (m_StoreLeases) + { + auto ret = m_Leases.insert (std::make_shared(lease)); + if (!ret.second) (*ret.first)->endDate = lease.endDate; // update existing + (*ret.first)->isUpdated = true; + // check if lease's gateway is in our netDb + if (!netdb.FindRouter (lease.tunnelGateway)) + { + // if not found request it + LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting"); + netdb.RequestDestination (lease.tunnelGateway); + } + } } + else + LogPrint (eLogWarning, "LeaseSet: Lease is expired already "); } uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const @@ -210,11 +236,263 @@ namespace data void LeaseSet::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const { + if (!m_EncryptionKey) return; auto encryptor = m_Identity->CreateEncryptor (m_EncryptionKey); if (encryptor) encryptor->Encrypt (data, encrypted, ctx, true); } + void LeaseSet::SetBuffer (const uint8_t * buf, size_t len) + { + if (m_Buffer) delete[] m_Buffer; + m_Buffer = new uint8_t[len]; + m_BufferLen = len; + memcpy (m_Buffer, buf, len); + } + + LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases): + LeaseSet (storeLeases), m_StoreType (storeType) + { + SetBuffer (buf, len); + if (storeType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) + ReadFromBufferEncrypted (buf, len); + else + ReadFromBuffer (buf, len); + } + + void LeaseSet2::Update (const uint8_t * buf, size_t len, bool verifySignature) + { + // shouldn't be called for now. Must be called from NetDb::AddLeaseSet later + SetBuffer (buf, len); + // TODO:verify signature if requested + } + + void LeaseSet2::ReadFromBuffer (const uint8_t * buf, size_t len) + { + // standard LS2 header + auto identity = std::make_shared(buf, len); + SetIdentity (identity); + size_t offset = identity->GetFullLen (); + if (offset + 8 >= len) return; + uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; // published timestamp (seconds) + uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds) + SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds + uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags + std::unique_ptr transientVerifier; + if (flags & 0x0001) + { + // transient key + if (offset + 6 >= len) return; + const uint8_t * signedData = buf + offset; + uint32_t expiresTimestamp = bufbe32toh (buf + offset); offset += 4; // expires timestamp + if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ()) + { + LogPrint (eLogWarning, "LeaseSet2: transient key expired"); + return; + } + uint16_t keyType = bufbe16toh (buf + offset); offset += 2; + transientVerifier.reset (i2p::data::IdentityEx::CreateVerifier (keyType)); + if (!transientVerifier) return; + auto keyLen = transientVerifier->GetPublicKeyLen (); + if (offset + keyLen >= len) return; + transientVerifier->SetPublicKey (buf + offset); offset += keyLen; + if (offset + identity->GetSignatureLen () >= len) return; + if (!identity->Verify (signedData, keyLen + 6, buf + offset)) return; + offset += identity->GetSignatureLen (); + } + // type specific part + size_t s = 0; + switch (m_StoreType) + { + case NETDB_STORE_TYPE_STANDARD_LEASESET2: + s = ReadStandardLS2TypeSpecificPart (buf + offset, len - offset); + break; + case NETDB_STORE_TYPE_META_LEASESET2: + s = ReadMetaLS2TypeSpecificPart (buf + offset, len - offset); + break; + default: + LogPrint (eLogWarning, "LeaseSet2: Unexpected store type ", (int)m_StoreType); + } + if (!s) return; + offset += s; + // verify signature + bool verified = transientVerifier ? VerifySignature (transientVerifier, buf, len, offset) : + VerifySignature (identity, buf, len, offset); + SetIsValid (verified); + } + + template + bool LeaseSet2::VerifySignature (Verifier& verifier, const uint8_t * buf, size_t len, size_t signatureOffset) + { + if (signatureOffset + verifier->GetSignatureLen () > len) return false; + // we assume buf inside DatabaseStore message, so buf[-1] is valid memory + // change it for signature verification, and restore back + uint8_t c = buf[-1]; + const_cast(buf)[-1] = m_StoreType; + bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset); + const_cast(buf)[-1] = c; + if (!verified) + LogPrint (eLogWarning, "LeaseSet2: verification failed"); + return verified; + } + + size_t LeaseSet2::ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len) + { + size_t offset = 0; + // properties + uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2; + offset += propertiesLen; // skip for now. TODO: implement properties + if (offset + 1 >= len) return 0; + // key sections + int numKeySections = buf[offset]; offset++; + for (int i = 0; i < numKeySections; i++) + { + uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption key type + if (offset + 2 >= len) return 0; + uint16_t encryptionKeyLen = bufbe16toh (buf + offset); offset += 2; + if (offset + encryptionKeyLen >= len) return 0; + if (!m_Encryptor && IsStoreLeases ()) // create encryptor with leases only, first key + { + auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); + m_Encryptor = encryptor; // TODO: atomic + } + offset += encryptionKeyLen; + } + // leases + if (offset + 1 >= len) return 0; + int numLeases = buf[offset]; offset++; + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + if (IsStoreLeases ()) + { + UpdateLeasesBegin (); + for (int i = 0; i < numLeases; i++) + { + if (offset + LEASE2_SIZE > len) return 0; + Lease lease; + lease.tunnelGateway = buf + offset; offset += 32; // gateway + lease.tunnelID = bufbe32toh (buf + offset); offset += 4; // tunnel ID + lease.endDate = bufbe32toh (buf + offset)*1000LL; offset += 4; // end date + UpdateLease (lease, ts); + } + UpdateLeasesEnd (); + } + else + offset += numLeases*LEASE2_SIZE; // 40 bytes per lease + return offset; + } + + size_t LeaseSet2::ReadMetaLS2TypeSpecificPart (const uint8_t * buf, size_t len) + { + size_t offset = 0; + // properties + uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2; + offset += propertiesLen; // skip for now. TODO: implement properties + // entries + if (offset + 1 >= len) return 0; + int numEntries = buf[offset]; offset++; + for (int i = 0; i < numEntries; i++) + { + if (offset + 40 >= len) return 0; + offset += 32; // hash + offset += 3; // flags + offset += 1; // cost + offset += 4; // expires + } + // revocations + if (offset + 1 >= len) return 0; + int numRevocations = buf[offset]; offset++; + for (int i = 0; i < numRevocations; i++) + { + if (offset + 32 > len) return 0; + offset += 32; // hash + } + return offset; + } + + void LeaseSet2::ReadFromBufferEncrypted (const uint8_t * buf, size_t len) + { + size_t offset = 0; + // blinded key + if (len < 2) return; + uint16_t blindedKeyType = bufbe16toh (buf + offset); offset += 2; + std::unique_ptr blindedVerifier (i2p::data::IdentityEx::CreateVerifier (blindedKeyType)); + if (!blindedVerifier) return; + auto blindedKeyLen = blindedVerifier->GetPublicKeyLen (); + if (offset + blindedKeyLen >= len) return; + blindedVerifier->SetPublicKey (buf + offset); offset += blindedKeyLen; + // expiration + if (offset + 8 >= len) return; + uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; // published timestamp (seconds) + uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds) + SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds + uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags + std::unique_ptr transientVerifier; + if (flags & 0x0001) + { + // transient key + if (offset + 6 >= len) return; + const uint8_t * signedData = buf + offset; + uint32_t expiresTimestamp = bufbe32toh (buf + offset); offset += 4; // expires timestamp + if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ()) + { + LogPrint (eLogWarning, "LeaseSet2: transient key expired"); + return; + } + uint16_t keyType = bufbe16toh (buf + offset); offset += 2; + transientVerifier.reset (i2p::data::IdentityEx::CreateVerifier (keyType)); + if (!transientVerifier) return; + auto keyLen = transientVerifier->GetPublicKeyLen (); + if (offset + keyLen >= len) return; + transientVerifier->SetPublicKey (buf + offset); offset += keyLen; + if (offset + blindedVerifier->GetSignatureLen () >= len) return; + if (!blindedVerifier->Verify (signedData, keyLen + 6, buf + offset)) return; + offset += blindedVerifier->GetSignatureLen (); + } + // outer ciphertext + if (offset + 2 > len) return; + uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2 + lenOuterCiphertext; + // verify signature + bool verified = transientVerifier ? VerifySignature (transientVerifier, buf, len, offset) : + VerifySignature (blindedVerifier, buf, len, offset); + SetIsValid (verified); + } + + void LeaseSet2::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const + { + auto encryptor = m_Encryptor; // TODO: atomic + if (encryptor) + encryptor->Encrypt (data, encrypted, ctx, true); + } + + uint64_t LeaseSet2::ExtractTimestamp (const uint8_t * buf, size_t len) const + { + if (len < 8) return 0; + if (m_StoreType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) + { + // encrypted LS2 + size_t offset = 0; + uint16_t blindedKeyType = bufbe16toh (buf + offset); offset += 2; + std::unique_ptr blindedVerifier (i2p::data::IdentityEx::CreateVerifier (blindedKeyType)); + if (!blindedVerifier) return 0 ; + auto blindedKeyLen = blindedVerifier->GetPublicKeyLen (); + if (offset + blindedKeyLen + 6 >= len) return 0; + offset += blindedKeyLen; + uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; + uint16_t expires = bufbe16toh (buf + offset); offset += 2; + return (timestamp + expires)* 1000LL; + } + else + { + auto identity = GetIdentity (); + if (!identity) return 0; + size_t offset = identity->GetFullLen (); + if (offset + 6 >= len) return 0; + uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; + uint16_t expires = bufbe16toh (buf + offset); offset += 2; + return (timestamp + expires)* 1000LL; + } + } + LocalLeaseSet::LocalLeaseSet (std::shared_ptr identity, const uint8_t * encryptionPublicKey, std::vector > tunnels): m_ExpirationTime (0), m_Identity (identity) { @@ -255,9 +533,17 @@ namespace data LocalLeaseSet::LocalLeaseSet (std::shared_ptr identity, const uint8_t * buf, size_t len): m_ExpirationTime (0), m_Identity (identity) { - m_BufferLen = len; - m_Buffer = new uint8_t[m_BufferLen]; - memcpy (m_Buffer, buf, len); + if (buf) + { + m_BufferLen = len; + m_Buffer = new uint8_t[m_BufferLen]; + memcpy (m_Buffer, buf, len); + } + else + { + m_Buffer = nullptr; + m_BufferLen = 0; + } } bool LocalLeaseSet::IsExpired () const @@ -299,5 +585,50 @@ namespace data } return ident.Verify(ptr, leases - ptr, leases); } + + LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, + uint16_t keyType, uint16_t keyLen, const uint8_t * encryptionPublicKey, + std::vector > tunnels): + LocalLeaseSet (identity, nullptr, 0) + { + // assume standard LS2 + int num = tunnels.size (); + if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES; + m_BufferLen = identity->GetFullLen () + 4/*published*/ + 2/*expires*/ + 2/*flag*/ + 2/*properties len*/ + + 1/*num keys*/ + 2/*key type*/ + 2/*key len*/ + keyLen/*key*/ + 1/*num leases*/ + num*LEASE2_SIZE + identity->GetSignatureLen (); + m_Buffer = new uint8_t[m_BufferLen + 1]; + m_Buffer[0] = storeType; + // LS2 header + auto offset = identity->ToBuffer (m_Buffer + 1, m_BufferLen) + 1; + auto timestamp = i2p::util::GetSecondsSinceEpoch (); + htobe32buf (m_Buffer + offset, timestamp); offset += 4; // published timestamp (seconds) + uint8_t * expiresBuf = m_Buffer + offset; offset += 2; // expires, fill later + htobe16buf (m_Buffer + offset, 0); offset += 2; // flags + htobe16buf (m_Buffer + offset, 0); offset += 2; // properties len + // keys + m_Buffer[offset] = 1; offset++; // 1 key + htobe16buf (m_Buffer + offset, keyType); offset += 2; // key type + htobe16buf (m_Buffer + offset, keyLen); offset += 2; // key len + memcpy (m_Buffer + offset, encryptionPublicKey, keyLen); offset += keyLen; // key + // leases + uint32_t expirationTime = 0; // in seconds + m_Buffer[offset] = num; offset++; // num leases + for (int i = 0; i < num; i++) + { + memcpy (m_Buffer + offset, tunnels[i]->GetNextIdentHash (), 32); + offset += 32; // gateway id + htobe32buf (m_Buffer + offset, tunnels[i]->GetNextTunnelID ()); + offset += 4; // tunnel id + auto ts = tunnels[i]->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // in seconds, 1 minute before expiration + if (ts > expirationTime) expirationTime = ts; + htobe32buf (m_Buffer + offset, ts); + offset += 4; // end date + } + // update expiration + SetExpirationTime (expirationTime*1000LL); + auto expires = expirationTime - timestamp; + htobe16buf (expiresBuf, expires > 0 ? expires : 0); + // we don't sign it yet. must be signed later on + } } } diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index fa24df2f..10e60c4a 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -50,14 +50,17 @@ namespace data const size_t MAX_LS_BUFFER_SIZE = 3072; const size_t LEASE_SIZE = 44; // 32 + 4 + 8 + const size_t LEASE2_SIZE = 40; // 32 + 4 + 4 const uint8_t MAX_NUM_LEASES = 16; + + const uint8_t NETDB_STORE_TYPE_LEASESET = 1; class LeaseSet: public RoutingDestination { public: LeaseSet (const uint8_t * buf, size_t len, bool storeLeases = true); - ~LeaseSet () { delete[] m_Buffer; }; - void Update (const uint8_t * buf, size_t len, bool verifySignature = true); + virtual ~LeaseSet () { delete[] m_EncryptionKey; delete[] m_Buffer; }; + virtual void Update (const uint8_t * buf, size_t len, bool verifySignature = true); bool IsNewer (const uint8_t * buf, size_t len) const; void PopulateLeases (); // from buffer @@ -73,16 +76,31 @@ namespace data bool ExpiresSoon(const uint64_t dlt=1000 * 5, const uint64_t fudge = 0) const ; bool operator== (const LeaseSet& other) const { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; - + virtual uint8_t GetStoreType () const { return NETDB_STORE_TYPE_LEASESET; }; + // implements RoutingDestination std::shared_ptr GetIdentity () const { return m_Identity; }; void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const; bool IsDestination () const { return true; }; + protected: + + void UpdateLeasesBegin (); + void UpdateLeasesEnd (); + void UpdateLease (const Lease& lease, uint64_t ts); + + // called from LeaseSet2 + LeaseSet (bool storeLeases); + void SetBuffer (const uint8_t * buf, size_t len); + void SetIdentity (std::shared_ptr identity) { m_Identity = identity; }; + void SetExpirationTime (uint64_t t) { m_ExpirationTime = t; }; + void SetIsValid (bool isValid) { m_IsValid = isValid; }; + bool IsStoreLeases () const { return m_StoreLeases; }; + private: void ReadFromBuffer (bool readIdentity = true, bool verifySignature = true); - uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // returns max expiration time + virtual uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // returns max expiration time private: @@ -90,7 +108,7 @@ namespace data std::set, LeaseCmp> m_Leases; uint64_t m_ExpirationTime; // in milliseconds std::shared_ptr m_Identity; - uint8_t m_EncryptionKey[256]; + uint8_t * m_EncryptionKey; uint8_t * m_Buffer; size_t m_BufferLen; }; @@ -101,17 +119,49 @@ namespace data */ bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires); + const uint8_t NETDB_STORE_TYPE_STANDARD_LEASESET2 = 3; + const uint8_t NETDB_STORE_TYPE_ENCRYPTED_LEASESET2 = 5; + const uint8_t NETDB_STORE_TYPE_META_LEASESET2 = 7; + class LeaseSet2: public LeaseSet + { + public: + + LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true); + uint8_t GetStoreType () const { return m_StoreType; }; + void Update (const uint8_t * buf, size_t len, bool verifySignature); + + // implements RoutingDestination + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const; + + private: + + void ReadFromBuffer (const uint8_t * buf, size_t len); + void ReadFromBufferEncrypted (const uint8_t * buf, size_t len); + size_t ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len); + size_t ReadMetaLS2TypeSpecificPart (const uint8_t * buf, size_t len); + + template + bool VerifySignature (Verifier& verifier, const uint8_t * buf, size_t len, size_t signatureOffset); + + uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; + + private: + + uint8_t m_StoreType; + std::shared_ptr m_Encryptor; // for standardLS2 + }; + class LocalLeaseSet { public: LocalLeaseSet (std::shared_ptr identity, const uint8_t * encryptionPublicKey, std::vector > tunnels); LocalLeaseSet (std::shared_ptr identity, const uint8_t * buf, size_t len); - ~LocalLeaseSet () { delete[] m_Buffer; }; + virtual ~LocalLeaseSet () { delete[] m_Buffer; }; - const uint8_t * GetBuffer () const { return m_Buffer; }; - uint8_t * GetSignature () { return m_Buffer + m_BufferLen - GetSignatureLen (); }; - size_t GetBufferLen () const { return m_BufferLen; }; + virtual uint8_t * GetBuffer () const { return m_Buffer; }; + uint8_t * GetSignature () { return GetBuffer () + GetBufferLen () - GetSignatureLen (); }; + virtual size_t GetBufferLen () const { return m_BufferLen; }; size_t GetSignatureLen () const { return m_Identity->GetSignatureLen (); }; uint8_t * GetLeases () { return m_Leases; }; @@ -120,8 +170,9 @@ namespace data uint64_t GetExpirationTime () const { return m_ExpirationTime; }; void SetExpirationTime (uint64_t expirationTime) { m_ExpirationTime = expirationTime; }; bool operator== (const LeaseSet& other) const - { return m_BufferLen == other.GetBufferLen () && !memcmp (other.GetBuffer (), other.GetBuffer (), m_BufferLen); }; + { return GetBufferLen () == other.GetBufferLen () && !memcmp (GetBuffer (), other.GetBuffer (), GetBufferLen ()); }; + virtual uint8_t GetStoreType () const { return NETDB_STORE_TYPE_LEASESET; }; private: @@ -130,6 +181,26 @@ namespace data uint8_t * m_Buffer, * m_Leases; size_t m_BufferLen; }; + + class LocalLeaseSet2: public LocalLeaseSet + { + public: + + LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, + uint16_t keyType, uint16_t keyLen, const uint8_t * encryptionPublicKey, + std::vector > tunnels); + virtual ~LocalLeaseSet2 () { delete[] m_Buffer; }; + + uint8_t * GetBuffer () const { return m_Buffer + 1; }; + size_t GetBufferLen () const { return m_BufferLen; }; + + uint8_t GetStoreType () const { return m_Buffer[0]; }; + + private: + + uint8_t * m_Buffer; // 1 byte store type + actual buffer + size_t m_BufferLen; + }; } } diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 513aad08..2c84f9f6 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -30,7 +30,6 @@ namespace transport NTCP2Establisher::NTCP2Establisher (): m_SessionRequestBuffer (nullptr), m_SessionCreatedBuffer (nullptr), m_SessionConfirmedBuffer (nullptr) { - CreateEphemeralKey (); } NTCP2Establisher::~NTCP2Establisher () @@ -357,6 +356,7 @@ namespace transport TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT), m_Server (server), m_Socket (m_Server.GetService ()), m_IsEstablished (false), m_IsTerminated (false), + m_Establisher (new NTCP2Establisher), m_SendSipKey (nullptr), m_ReceiveSipKey (nullptr), #if OPENSSL_SIPHASH m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr), @@ -364,7 +364,6 @@ namespace transport m_NextReceivedLen (0), m_NextReceivedBuffer (nullptr), m_NextSendBuffer (nullptr), m_ReceiveSequenceNumber (0), m_SendSequenceNumber (0), m_IsSending (false) { - m_Establisher.reset (new NTCP2Establisher); if (in_RemoteRouter) // Alice { m_Establisher->m_RemoteIdentHash = GetRemoteIdentity ()->GetIdentHash (); @@ -735,11 +734,13 @@ namespace transport void NTCP2Session::ClientLogin () { + m_Establisher->CreateEphemeralKey (); SendSessionRequest (); } void NTCP2Session::ServerLogin () { + m_Establisher->CreateEphemeralKey (); m_Establisher->m_SessionRequestBuffer = new uint8_t[287]; // 287 bytes max for now boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (), @@ -899,14 +900,9 @@ namespace transport m_Handler.Flush (); } - void NTCP2Session::SendNextFrame (const uint8_t * payload, size_t len) + void NTCP2Session::SetNextSentFrameLength (size_t frameLen, uint8_t * lengthBuf) { - if (IsTerminated ()) return; - uint8_t nonce[12]; - CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; - m_NextSendBuffer = new uint8_t[len + 16 + 2]; - i2p::crypto::AEADChaCha20Poly1305 (payload, len, nullptr, 0, m_SendKey, nonce, m_NextSendBuffer + 2, len + 16, true); -#if OPENSSL_SIPHASH + #if OPENSSL_SIPHASH EVP_DigestSignInit (m_SendMDCtx, nullptr, nullptr, nullptr, nullptr); EVP_DigestSignUpdate (m_SendMDCtx, m_SendIV.buf, 8); size_t l = 8; @@ -915,12 +911,101 @@ namespace transport i2p::crypto::Siphash<8> (m_SendIV.buf, m_SendIV.buf, 8, m_SendSipKey); #endif // length must be in BigEndian - htobe16buf (m_NextSendBuffer, (len + 16) ^ le16toh (m_SendIV.key)); - LogPrint (eLogDebug, "NTCP2: sent length ", len + 16); + htobe16buf (lengthBuf, frameLen ^ le16toh (m_SendIV.key)); + LogPrint (eLogDebug, "NTCP2: sent length ", frameLen); + } - // send message + void NTCP2Session::SendI2NPMsgs (std::vector >& msgs) + { + if (msgs.empty () || IsTerminated ()) return; + + size_t totalLen = 0; + std::vector > encryptBufs; + std::vector bufs; + std::shared_ptr first; + uint8_t * macBuf = nullptr; + for (auto& it: msgs) + { + it->ToNTCP2 (); + auto buf = it->GetNTCP2Header (); + auto len = it->GetNTCP2Length (); + // block header + buf -= 3; + buf[0] = eNTCP2BlkI2NPMessage; // blk + htobe16buf (buf + 1, len); // size + len += 3; + totalLen += len; + encryptBufs.push_back (std::make_pair (buf, len)); + if (&it == &msgs.front ()) // first message + { + // allocate two bytes for length + buf -= 2; len += 2; + first = it; + } + if (&it == &msgs.back () && it->len + 16 < it->maxLen) // last message + { + // if it's long enough we add padding and MAC to it + // create padding block + auto paddingLen = CreatePaddingBlock (totalLen, buf + len, it->maxLen - it->len - 16); + if (paddingLen) + { + encryptBufs.push_back (std::make_pair (buf + len, paddingLen)); + len += paddingLen; + totalLen += paddingLen; + } + macBuf = buf + len; + // allocate 16 bytes for MAC + len += 16; + } + + bufs.push_back (boost::asio::buffer (buf, len)); + } + + if (!macBuf) // last block was not enough for MAC + { + // allocate send buffer + m_NextSendBuffer = new uint8_t[287]; // can be any size > 16, we just allocate 287 frequently + // crate padding block + auto paddingLen = CreatePaddingBlock (totalLen, m_NextSendBuffer, 287 - 16); + // and padding block to encrypt and send + if (paddingLen) + encryptBufs.push_back (std::make_pair (m_NextSendBuffer, paddingLen)); + bufs.push_back (boost::asio::buffer (m_NextSendBuffer, paddingLen + 16)); + macBuf = m_NextSendBuffer + paddingLen; + totalLen += paddingLen; + } + uint8_t nonce[12]; + CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; + i2p::crypto::AEADChaCha20Poly1305Encrypt (encryptBufs, m_SendKey, nonce, macBuf); // encrypt buffers + SetNextSentFrameLength (totalLen + 16, first->GetNTCP2Header () - 5); // frame length right before first block + + // send buffers m_IsSending = true; - boost::asio::async_write (m_Socket, boost::asio::buffer (m_NextSendBuffer, len + 16 + 2), boost::asio::transfer_all (), + boost::asio::async_write (m_Socket, bufs, boost::asio::transfer_all (), + std::bind(&NTCP2Session::HandleI2NPMsgsSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, msgs)); + } + + void NTCP2Session::HandleI2NPMsgsSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector > msgs) + { + HandleNextFrameSent (ecode, bytes_transferred); + // msgs get destroyed here + } + + void NTCP2Session::EncryptAndSendNextBuffer (size_t payloadLen) + { + if (IsTerminated ()) + { + delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr; + return; + } + // encrypt + uint8_t nonce[12]; + CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; + i2p::crypto::AEADChaCha20Poly1305Encrypt ({std::make_pair (m_NextSendBuffer + 2, payloadLen)}, m_SendKey, nonce, m_NextSendBuffer + payloadLen + 2); + SetNextSentFrameLength (payloadLen + 16, m_NextSendBuffer); + // send + m_IsSending = true; + boost::asio::async_write (m_Socket, boost::asio::buffer (m_NextSendBuffer, payloadLen + 16 + 2), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleNextFrameSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -938,31 +1023,25 @@ namespace transport m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_NumSentBytes += bytes_transferred; i2p::transport::transports.UpdateSentBytes (bytes_transferred); - LogPrint (eLogDebug, "NTCP2: Next frame sent"); + LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred); SendQueue (); } } - + void NTCP2Session::SendQueue () { if (!m_SendQueue.empty ()) { - auto buf = m_Server.NewNTCP2FrameBuffer (); - uint8_t * payload = buf->data (); + std::vector > msgs; size_t s = 0; - // add I2NP blocks while (!m_SendQueue.empty ()) { auto msg = m_SendQueue.front (); size_t len = msg->GetNTCP2Length (); if (s + len + 3 <= NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) // 3 bytes block header { - payload[s] = eNTCP2BlkI2NPMessage; // blk - htobe16buf (payload + s + 1, len); // size - s += 3; - msg->ToNTCP2 (); - memcpy (payload + s, msg->GetNTCP2Header (), len); - s += len; + msgs.push_back (msg); + s += (len + 3); m_SendQueue.pop_front (); } else if (len + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) @@ -973,46 +1052,55 @@ namespace transport else break; } - // add padding block - int paddingSize = (s*NTCP2_MAX_PADDING_RATIO)/100; - if (s + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - s -3; - if (paddingSize) paddingSize = rand () % paddingSize; - payload[s] = eNTCP2BlkPadding; // blk - htobe16buf (payload + s + 1, paddingSize); // size - s += 3; - memset (payload + s, 0, paddingSize); - s += paddingSize; - // send - SendNextFrame (payload, s); - m_Server.DeleteNTCP2FrameBuffer (buf); + SendI2NPMsgs (msgs); } } + size_t NTCP2Session::CreatePaddingBlock (size_t msgLen, uint8_t * buf, size_t len) + { + if (len < 3) return 0; + len -= 3; + if (msgLen < 256) msgLen = 256; // for short message padding should not be always zero + size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100; + if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; + if (paddingSize > len) paddingSize = len; + if (paddingSize) paddingSize = rand () % paddingSize; + buf[0] = eNTCP2BlkPadding; // blk + htobe16buf (buf + 1, paddingSize); // size + memset (buf + 3, 0, paddingSize); + return paddingSize + 3; + } + void NTCP2Session::SendRouterInfo () { if (!IsEstablished ()) return; auto riLen = i2p::context.GetRouterInfo ().GetBufferLen (); - int paddingSize = (riLen*NTCP2_MAX_PADDING_RATIO)/100; - size_t payloadLen = riLen + paddingSize + 7; // 7 = 2*3 bytes header + 1 byte RI flag - uint8_t * payload = new uint8_t[payloadLen]; - payload[0] = eNTCP2BlkRouterInfo; - htobe16buf (payload + 1, riLen + 1); // size - payload[3] = 0; // flag - memcpy (payload + 4, i2p::context.GetRouterInfo ().GetBuffer (), riLen); - payload[riLen + 4] = eNTCP2BlkPadding; - htobe16buf (payload + riLen + 5, paddingSize); - RAND_bytes (payload + riLen + 7, paddingSize); - SendNextFrame (payload, payloadLen); - delete[] payload; + size_t payloadLen = riLen + 4; // 3 bytes block header + 1 byte RI flag + m_NextSendBuffer = new uint8_t[payloadLen + 16 + 2 + 64]; // up to 64 bytes padding + m_NextSendBuffer[2] = eNTCP2BlkRouterInfo; + htobe16buf (m_NextSendBuffer + 3, riLen + 1); // size + m_NextSendBuffer[5] = 0; // flag + memcpy (m_NextSendBuffer + 6, i2p::context.GetRouterInfo ().GetBuffer (), riLen); + // padding block + auto paddingSize = CreatePaddingBlock (payloadLen, m_NextSendBuffer + 2 + payloadLen, 64); + payloadLen += paddingSize; + // encrypt and send + EncryptAndSendNextBuffer (payloadLen); } void NTCP2Session::SendTermination (NTCP2TerminationReason reason) { if (!m_SendKey || !m_SendSipKey) return; - uint8_t payload[12] = { eNTCP2BlkTermination, 0, 9 }; - htobe64buf (payload + 3, m_ReceiveSequenceNumber); - payload[11] = (uint8_t)reason; - SendNextFrame (payload, 12); + m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block + // termination block + m_NextSendBuffer[2] = eNTCP2BlkTermination; + m_NextSendBuffer[3] = 0; m_NextSendBuffer[4] = 9; // 9 bytes block size + htobe64buf (m_NextSendBuffer + 5, m_ReceiveSequenceNumber); + m_NextSendBuffer[13] = (uint8_t)reason; + // padding block + auto paddingSize = CreatePaddingBlock (12, m_NextSendBuffer + 14, 19); + // encrypt and send + EncryptAndSendNextBuffer (paddingSize + 12); } void NTCP2Session::SendTerminationAndTerminate (NTCP2TerminationReason reason) diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index eb46b2f8..2bfc72b9 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -76,7 +76,6 @@ namespace transport // RouterInfo flags const uint8_t NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01; - typedef std::array NTCP2FrameBuffer; struct NTCP2Establisher { NTCP2Establisher (); @@ -175,8 +174,12 @@ namespace transport void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); void ProcessNextFrame (const uint8_t * frame, size_t len); - void SendNextFrame (const uint8_t * payload, size_t len); + void SetNextSentFrameLength (size_t frameLen, uint8_t * lengthBuf); + void SendI2NPMsgs (std::vector >& msgs); + void HandleI2NPMsgsSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector > msgs); + void EncryptAndSendNextBuffer (size_t payloadLen); void HandleNextFrameSent (const boost::system::error_code& ecode, std::size_t bytes_transferred); + size_t CreatePaddingBlock (size_t msgLen, uint8_t * buf, size_t len); void SendQueue (); void SendRouterInfo (); void SendTermination (NTCP2TerminationReason reason); @@ -232,9 +235,6 @@ namespace transport void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr conn); - NTCP2FrameBuffer * NewNTCP2FrameBuffer () { return m_NTCP2FrameBuffersPool.Acquire(); } - void DeleteNTCP2FrameBuffer (NTCP2FrameBuffer * buf) { return m_NTCP2FrameBuffersPool.Release(buf); } - private: void Run (); @@ -258,8 +258,6 @@ namespace transport std::map > m_NTCP2Sessions; std::list > m_PendingIncomingSessions; - i2p::util::MemoryPool m_NTCP2FrameBuffersPool; - public: // for HTTP/I2PControl diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 2e5c3a23..1ab246e1 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -250,47 +250,53 @@ namespace data return r; } - bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, - std::shared_ptr from) + bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len) { std::unique_lock lock(m_LeaseSetsMutex); bool updated = false; - if (!from) // unsolicited LS must be received directly + auto it = m_LeaseSets.find(ident); + if (it != m_LeaseSets.end () && it->second->GetStoreType () == i2p::data::NETDB_STORE_TYPE_LEASESET) { - auto it = m_LeaseSets.find(ident); - if (it != m_LeaseSets.end ()) + // we update only is existing LeaseSet is not LeaseSet2 + uint64_t expires; + if(LeaseSetBufferValidate(buf, len, expires)) { - uint64_t expires; - if(LeaseSetBufferValidate(buf, len, expires)) + if(it->second->GetExpirationTime() < expires) { - if(it->second->GetExpirationTime() < expires) - { - it->second->Update (buf, len, false); // signature is verified already - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); - updated = true; - } - else - LogPrint(eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); - } - else - LogPrint(eLogError, "NetDb: LeaseSet is invalid: ", ident.ToBase32()); - } - else - { - auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb - if (leaseSet->IsValid ()) - { - LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32()); - m_LeaseSets[ident] = leaseSet; + it->second->Update (buf, len, false); // signature is verified already + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); updated = true; } else - LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase32()); + LogPrint(eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); } + else + LogPrint(eLogError, "NetDb: LeaseSet is invalid: ", ident.ToBase32()); + } + else + { + auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb + if (leaseSet->IsValid ()) + { + LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32()); + m_LeaseSets[ident] = leaseSet; + updated = true; + } + else + LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase32()); } return updated; } + bool NetDb::AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType) + { + std::unique_lock lock(m_LeaseSetsMutex); + // always new LS2 for now. TODO: implement update + auto leaseSet = std::make_shared (storeType, buf, len, false); // we don't need leases in netdb + m_LeaseSets[ident] = leaseSet; + return true; + } + std::shared_ptr NetDb::FindRouter (const IdentHash& ident) const { std::unique_lock l(m_RouterInfosMutex); @@ -645,12 +651,24 @@ namespace data size_t payloadOffset = offset; bool updated = false; - if (buf[DATABASE_STORE_TYPE_OFFSET]) // type + uint8_t storeType = buf[DATABASE_STORE_TYPE_OFFSET]; + if (storeType) // LeaseSet or LeaseSet2 { - LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32()); - updated = AddLeaseSet (ident, buf + offset, len - offset, m->from); + if (!m->from) // unsolicited LS must be received directly + { + if (storeType == NETDB_STORE_TYPE_LEASESET) // 1 + { + LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32()); + updated = AddLeaseSet (ident, buf + offset, len - offset); + } + else // all others are considered as LeaseSet2 + { + LogPrint (eLogDebug, "NetDb: store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32()); + updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType); + } + } } - else + else // RouterInfo { LogPrint (eLogDebug, "NetDb: store request: RouterInfo"); size_t size = bufbe16toh (buf + offset); @@ -1198,9 +1216,9 @@ namespace data auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it = m_LeaseSets.begin (); it != m_LeaseSets.end ();) { - if (ts > it->second->GetExpirationTime () - LEASE_ENDDATE_THRESHOLD) + if (!it->second->IsValid () || ts > it->second->GetExpirationTime () - LEASE_ENDDATE_THRESHOLD) { - LogPrint (eLogInfo, "NetDb: LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); + LogPrint (eLogInfo, "NetDb: LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired or invalid"); it = m_LeaseSets.erase (it); } else diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index b34458fb..93e9e48f 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -54,7 +54,8 @@ namespace data bool AddRouterInfo (const uint8_t * buf, int len); bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); - bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from); + bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len); + bool AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType); std::shared_ptr FindRouter (const IdentHash& ident) const; std::shared_ptr FindLeaseSet (const IdentHash& destination) const; std::shared_ptr FindRouterProfile (const IdentHash& ident) const; diff --git a/libi2pd/Poly1305.cpp b/libi2pd/Poly1305.cpp index 4ce67d39..bf94c9a9 100644 --- a/libi2pd/Poly1305.cpp +++ b/libi2pd/Poly1305.cpp @@ -7,7 +7,7 @@ */ -#if LEGACY_OPENSSL +#if !OPENSSL_AEAD_CHACHA20_POLY1305 namespace i2p { namespace crypto diff --git a/libi2pd/Poly1305.h b/libi2pd/Poly1305.h index d9529c81..800fbfd9 100644 --- a/libi2pd/Poly1305.h +++ b/libi2pd/Poly1305.h @@ -11,7 +11,7 @@ #include #include "Crypto.h" -#if LEGACY_OPENSSL +#if !OPENSSL_AEAD_CHACHA20_POLY1305 namespace i2p { namespace crypto diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 6b5053a8..7efeadde 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -47,7 +47,10 @@ namespace i2p routerInfo.SetRouterIdentity (GetIdentity ()); uint16_t port; i2p::config::GetOption("port", port); if (!port) + { port = rand () % (30777 - 9111) + 9111; // I2P network ports range + if (port == 9150) port = 9151; // Tor browser + } bool ipv4; i2p::config::GetOption("ipv4", ipv4); bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool ssu; i2p::config::GetOption("ssu", ssu); @@ -166,7 +169,10 @@ namespace i2p { if (!m_NTCP2Keys) return; if (!port) + { port = rand () % (30777 - 9111) + 9111; // I2P network ports range + if (port == 9150) port = 9151; // Tor browser + } bool updated = false; for (auto& address : m_RouterInfo.GetAddresses ()) { diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index 1facccbc..c82c85df 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -7,35 +7,43 @@ namespace i2p namespace crypto { #if OPENSSL_EDDSA - EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey) + EDDSA25519Verifier::EDDSA25519Verifier () { - m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32); m_MDCtx = EVP_MD_CTX_create (); - EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); } EDDSA25519Verifier::~EDDSA25519Verifier () { EVP_MD_CTX_destroy (m_MDCtx); - EVP_PKEY_free (m_Pkey); + if (m_Pkey) EVP_PKEY_free (m_Pkey); } + void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey) + { + m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32); + EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); + } + bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len); } #else - EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey) + EDDSA25519Verifier::EDDSA25519Verifier () + { + } + + EDDSA25519Verifier::~EDDSA25519Verifier () + { + } + + void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey) { memcpy (m_PublicKeyEncoded, signingKey, EDDSA25519_PUBLIC_KEY_LENGTH); BN_CTX * ctx = BN_CTX_new (); m_PublicKey = GetEd25519 ()->DecodePublicKey (m_PublicKeyEncoded, ctx); BN_CTX_free (ctx); - } - - EDDSA25519Verifier::~EDDSA25519Verifier () - { } bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index a51f8955..84d4b0aa 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -24,6 +24,7 @@ namespace crypto virtual size_t GetPublicKeyLen () const = 0; virtual size_t GetSignatureLen () const = 0; virtual size_t GetPrivateKeyLen () const { return GetSignatureLen ()/2; }; + virtual void SetPublicKey (const uint8_t * signingKey) = 0; }; class Signer @@ -41,9 +42,13 @@ namespace crypto { public: - DSAVerifier (const uint8_t * signingKey) + DSAVerifier () { m_PublicKey = CreateDSA (); + } + + void SetPublicKey (const uint8_t * signingKey) + { DSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL), NULL); } @@ -154,9 +159,13 @@ namespace crypto { public: - ECDSAVerifier (const uint8_t * signingKey) + ECDSAVerifier () { m_PublicKey = EC_KEY_new_by_curve_name (curve); + } + + void SetPublicKey (const uint8_t * signingKey) + { BIGNUM * x = BN_bin2bn (signingKey, keyLen/2, NULL); BIGNUM * y = BN_bin2bn (signingKey + keyLen/2, keyLen/2, NULL); EC_KEY_set_public_key_affine_coordinates (m_PublicKey, x, y); @@ -275,7 +284,8 @@ namespace crypto { public: - EDDSA25519Verifier (const uint8_t * signingKey); + EDDSA25519Verifier (); + void SetPublicKey (const uint8_t * signingKey); ~EDDSA25519Verifier (); bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const; @@ -386,15 +396,22 @@ namespace crypto enum { keyLen = Hash::hashLen }; - GOSTR3410Verifier (GOSTR3410ParamSet paramSet, const uint8_t * signingKey): - m_ParamSet (paramSet) + GOSTR3410Verifier (GOSTR3410ParamSet paramSet): + m_ParamSet (paramSet), m_PublicKey (nullptr) + { + } + + void SetPublicKey (const uint8_t * signingKey) { BIGNUM * x = BN_bin2bn (signingKey, GetPublicKeyLen ()/2, NULL); BIGNUM * y = BN_bin2bn (signingKey + GetPublicKeyLen ()/2, GetPublicKeyLen ()/2, NULL); m_PublicKey = GetGOSTR3410Curve (m_ParamSet)->CreatePoint (x, y); BN_free (x); BN_free (y); } - ~GOSTR3410Verifier () { EC_POINT_free (m_PublicKey); } + ~GOSTR3410Verifier () + { + if (m_PublicKey) EC_POINT_free (m_PublicKey); + } bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 64f41afd..f2fc5c12 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -459,23 +459,6 @@ namespace transport } } } - else // we don't have address - { - if (address->addressString.length () > 0) // trying to resolve - { - if(m_NTCPServer->UsingProxy()) - { - auto s = std::make_shared (*m_NTCPServer, peer.router); - m_NTCPServer->ConnectWithProxy(address->addressString, address->port, NTCPServer::eHostname, s); - } - else - { - LogPrint (eLogDebug, "Transports: Resolving NTCP ", address->addressString); - NTCPResolve (address->addressString, ident); - } - return true; - } - } } else LogPrint (eLogDebug, "Transports: NTCP address is not present for ", i2p::data::GetIdentHashAbbreviation (ident), ", trying SSU"); @@ -497,15 +480,6 @@ namespace transport m_SSUServer->CreateSession (peer.router, address->host, address->port); return true; } - else // we don't have address - { - if (address->addressString.length () > 0) // trying to resolve - { - LogPrint (eLogDebug, "Transports: Resolving SSU ", address->addressString); - SSUResolve (address->addressString, ident); - return true; - } - } } } LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available"); @@ -547,92 +521,7 @@ namespace transport } } } - - void Transports::NTCPResolve (const std::string& addr, const i2p::data::IdentHash& ident) - { - auto resolver = std::make_shared(*m_Service); - resolver->async_resolve (boost::asio::ip::tcp::resolver::query (addr, ""), - std::bind (&Transports::HandleNTCPResolve, this, - std::placeholders::_1, std::placeholders::_2, ident, resolver)); - } - - void Transports::HandleNTCPResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, - i2p::data::IdentHash ident, std::shared_ptr resolver) - { - auto it1 = m_Peers.find (ident); - if (it1 != m_Peers.end ()) - { - auto& peer = it1->second; - if (!ecode && peer.router) - { - while (it != boost::asio::ip::tcp::resolver::iterator()) - { - auto address = (*it).endpoint ().address (); - LogPrint (eLogDebug, "Transports: ", (*it).host_name (), " has been resolved to ", address); - if (address.is_v4 () || context.SupportsV6 ()) - { - auto addr = peer.router->GetNTCPAddress (); // TODO: take one we requested - if (addr) - { - auto s = std::make_shared (*m_NTCPServer, peer.router); - m_NTCPServer->Connect (address, addr->port, s); - return; - } - break; - } - else - LogPrint (eLogInfo, "Transports: NTCP ", address, " is not supported"); - it++; - } - } - LogPrint (eLogError, "Transports: Unable to resolve NTCP address: ", ecode.message ()); - std::unique_lock l(m_PeersMutex); - m_Peers.erase (it1); - } - } - - void Transports::SSUResolve (const std::string& addr, const i2p::data::IdentHash& ident) - { - auto resolver = std::make_shared(*m_Service); - resolver->async_resolve (boost::asio::ip::tcp::resolver::query (addr, ""), - std::bind (&Transports::HandleSSUResolve, this, - std::placeholders::_1, std::placeholders::_2, ident, resolver)); - } - - void Transports::HandleSSUResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, - i2p::data::IdentHash ident, std::shared_ptr resolver) - { - auto it1 = m_Peers.find (ident); - if (it1 != m_Peers.end ()) - { - auto& peer = it1->second; - if (!ecode && peer.router) - { - while (it != boost::asio::ip::tcp::resolver::iterator()) - { - auto address = (*it).endpoint ().address (); - LogPrint (eLogDebug, "Transports: ", (*it).host_name (), " has been resolved to ", address); - if (address.is_v4 () || context.SupportsV6 ()) - { - auto addr = peer.router->GetSSUAddress (); // TODO: take one we requested - if (addr) - { - m_SSUServer->CreateSession (peer.router, address, addr->port); - return; - } - break; - } - else - LogPrint (eLogInfo, "Transports: SSU ", address, " is not supported"); - it++; - } - } - LogPrint (eLogError, "Transports: Unable to resolve SSU address: ", ecode.message ()); - std::unique_lock l(m_PeersMutex); - m_Peers.erase (it1); - } - } - + void Transports::CloseSession (std::shared_ptr router) { if (!router) return; diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index cb523545..798c90a9 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -136,13 +136,6 @@ namespace transport void HandlePeerCleanupTimer (const boost::system::error_code& ecode); void HandlePeerTestTimer (const boost::system::error_code& ecode); - void NTCPResolve (const std::string& addr, const i2p::data::IdentHash& ident); - void HandleNTCPResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, - i2p::data::IdentHash ident, std::shared_ptr resolver); - void SSUResolve (const std::string& addr, const i2p::data::IdentHash& ident); - void HandleSSUResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, - i2p::data::IdentHash ident, std::shared_ptr resolver); - void UpdateBandwidth (); void DetectExternalIP (); diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index 415118ff..ca72ae49 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -28,14 +28,11 @@ namespace api i2p::fs::DetectDataDir(datadir, false); i2p::fs::Init(); -#if defined(__x86_64__) - i2p::crypto::InitCrypto (false); -#else - i2p::crypto::InitCrypto (true); -#endif + bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); + i2p::crypto::InitCrypto (precomputation); - int netID; i2p::config::GetOption("netid", netID); - i2p::context.SetNetID (netID); + int netID; i2p::config::GetOption("netid", netID); + i2p::context.SetNetID (netID); i2p::context.Init (); } diff --git a/libi2pd/util.h b/libi2pd/util.h index e31e7b3f..6da20ad6 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -9,21 +9,23 @@ #include #ifdef ANDROID +#ifndef __clang__ #include namespace std { -template -std::string to_string(T value) -{ - return boost::lexical_cast(value); -} + template + std::string to_string(T value) + { + return boost::lexical_cast(value); + } -inline int stoi(const std::string& str) -{ - return boost::lexical_cast(str); -} + inline int stoi(const std::string& str) + { + return boost::lexical_cast(str); + } } #endif +#endif namespace i2p { diff --git a/libi2pd/version.h b/libi2pd/version.h index 22990219..73ab2206 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -7,7 +7,7 @@ #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 22 +#define I2PD_VERSION_MINOR 23 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) @@ -21,7 +21,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 37 +#define I2P_VERSION_MICRO 38 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 257087ee..c69e419e 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -345,11 +345,8 @@ namespace client { LogPrint (eLogWarning, "Clients: Local destination ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " exists"); if (!it->second->IsRunning ()) - { it->second->Start (); - return it->second; - } - return nullptr; + return it->second; } auto localDestination = std::make_shared (keys, isPublic, params); std::unique_lock l(m_DestinationsMutex); @@ -360,7 +357,7 @@ namespace client void ClientContext::CreateNewSharedLocalDestination () { - m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA + m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, EDDSA m_SharedLocalDestination->Acquire (); } @@ -378,6 +375,12 @@ namespace client return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value)); } + template + std::string ClientContext::GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const + { + return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value); + } + template void ClientContext::ReadI2CPOptions (const Section& section, std::map& options) const { @@ -388,7 +391,10 @@ namespace client options[I2CP_PARAM_TAGS_TO_SEND] = GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND); options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY); options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY); - options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY); + options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY); + options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); + std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, ""); + if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType; } void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const @@ -480,7 +486,7 @@ namespace client std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "transient"); std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); - i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); + i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); // I2CP std::map options; @@ -593,7 +599,7 @@ namespace client std::string hostOverride = section.second.get (I2P_SERVER_TUNNEL_HOST_OVERRIDE, ""); std::string webircpass = section.second.get (I2P_SERVER_TUNNEL_WEBIRC_PASSWORD, ""); bool gzip = section.second.get (I2P_SERVER_TUNNEL_GZIP, true); - i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); + i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); std::string address = section.second.get (I2P_SERVER_TUNNEL_ADDRESS, "127.0.0.1"); @@ -719,7 +725,7 @@ namespace client std::map params; ReadI2CPOptionsFromConfig ("httpproxy.", params); localDestination = CreateNewLocalDestination (keys, false, ¶ms); - localDestination->Acquire (); + if (localDestination) localDestination->Acquire (); } else LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); @@ -758,7 +764,7 @@ namespace client std::map params; ReadI2CPOptionsFromConfig ("socksproxy.", params); localDestination = CreateNewLocalDestination (keys, false, ¶ms); - localDestination->Acquire (); + if (localDestination) localDestination->Acquire (); } else LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key"); diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index a0c92045..71e052c3 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -65,7 +65,7 @@ namespace client std::shared_ptr GetSharedLocalDestination () const { return m_SharedLocalDestination; }; std::shared_ptr CreateNewLocalDestination (bool isPublic = false, // transient - i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1, + i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519, i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, const std::map * params = nullptr); // used by SAM only std::shared_ptr CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, @@ -74,7 +74,7 @@ namespace client void DeleteLocalDestination (std::shared_ptr destination); std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, - i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, + i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519, i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); AddressBook& GetAddressBook () { return m_AddressBook; }; @@ -93,6 +93,8 @@ namespace client template std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const; template + std::string GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const; // GetI2CPOption with string default value + template void ReadI2CPOptions (const Section& section, std::map& options) const; // for tunnels void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const; // for HTTP and SOCKS proxy diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index da8dd65a..40df0161 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -8,7 +8,7 @@ namespace i2p { namespace client { - static const i2p::data::SigningKeyType I2P_SERVICE_DEFAULT_KEY_TYPE = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256; + static const i2p::data::SigningKeyType I2P_SERVICE_DEFAULT_KEY_TYPE = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519; I2PService::I2PService (std::shared_ptr localDestination): m_LocalDestination (localDestination ? localDestination : @@ -64,7 +64,7 @@ namespace client void I2PService::TriggerReadyCheckTimer() { m_ReadyTimer.expires_from_now(boost::posix_time::seconds (1)); - m_ReadyTimer.async_wait(std::bind(&I2PService::HandleReadyCheckTimer, this, std::placeholders::_1)); + m_ReadyTimer.async_wait(std::bind(&I2PService::HandleReadyCheckTimer, shared_from_this (), std::placeholders::_1)); m_ReadyTimerTriggered = true; } diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index b7bf6002..9fdf08aa 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -558,11 +558,22 @@ namespace client i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; auto it = params.find (SAM_PARAM_SIGNATURE_TYPE); if (it != params.end ()) - // TODO: extract string values - signatureType = std::stoi(it->second); + { + if (!m_Owner.ResolveSignatureType (it->second, signatureType)) + LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", it->second); + } it = params.find (SAM_PARAM_CRYPTO_TYPE); if (it != params.end ()) - cryptoType = std::stoi(it->second); + { + try + { + cryptoType = std::stoi(it->second); + } + catch (const std::exception& ex) + { + LogPrint (eLogWarning, "SAM: ", SAM_PARAM_CRYPTO_TYPE, "error: ", ex.what ()); + } + } auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType); #ifdef _MSC_VER size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, @@ -921,7 +932,17 @@ namespace client SAMBridge::SAMBridge (const std::string& address, int port): m_IsRunning (false), m_Thread (nullptr), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)), - m_DatagramEndpoint (boost::asio::ip::address::from_string(address), port-1), m_DatagramSocket (m_Service, m_DatagramEndpoint) + m_DatagramEndpoint (boost::asio::ip::address::from_string(address), port-1), m_DatagramSocket (m_Service, m_DatagramEndpoint), + m_SignatureTypes + { + {"DSA_SHA1", i2p::data::SIGNING_KEY_TYPE_DSA_SHA1}, + {"ECDSA_SHA256_P256", i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256}, + {"ECDSA_SHA256_P384", i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384}, + {"ECDSA_SHA256_P521", i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521}, + {"EdDSA_SHA512_Ed25519", i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519}, + {"GOST_GOSTR3411256_GOSTR3410CRYPTOPROA", i2p::data::SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256}, + {"GOST_GOSTR3411512_GOSTR3410TC26A512", i2p::data::SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512} + } { } @@ -1028,15 +1049,8 @@ namespace client auto it = params->find (SAM_PARAM_SIGNATURE_TYPE); if (it != params->end ()) { - // TODO: extract string values - try - { - signatureType = std::stoi(it->second); - } - catch (const std::exception& ex) - { - LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, "error: ", ex.what ()); - } + if (!ResolveSignatureType (it->second, signatureType)) + LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", it->second); } it = params->find (SAM_PARAM_CRYPTO_TYPE); if (it != params->end ()) @@ -1166,5 +1180,28 @@ namespace client else LogPrint (eLogError, "SAM: datagram receive error: ", ecode.message ()); } + + bool SAMBridge::ResolveSignatureType (const std::string& name, i2p::data::SigningKeyType& type) const + { + try + { + type = std::stoi (name); + } + catch (const std::invalid_argument& ex) + { + // name is not numeric, resolving + auto it = m_SignatureTypes.find (name); + if (it != m_SignatureTypes.end ()) + type = it->second; + else + return false; + } + catch (const std::exception& ex) + { + return false; + } + // name has been resolved + return true; + } } } diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index dde6e675..4506632c 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -184,6 +184,8 @@ namespace client void RemoveSocket(const std::shared_ptr & socket); + bool ResolveSignatureType (const std::string& name, i2p::data::SigningKeyType& type) const; + private: void Run (); @@ -207,6 +209,7 @@ namespace client mutable std::mutex m_OpenSocketsMutex; std::list > m_OpenSockets; uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE+1]; + std::map m_SignatureTypes; public: diff --git a/qt/i2pd_qt/android/.gitignore b/qt/i2pd_qt/android/.gitignore deleted file mode 100644 index 2c41ac3e..00000000 --- a/qt/i2pd_qt/android/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/gen/ diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml deleted file mode 100644 index 8eb723e7..00000000 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/qt/i2pd_qt/android/build.gradle b/qt/i2pd_qt/android/build.gradle deleted file mode 100644 index ef416b0b..00000000 --- a/qt/i2pd_qt/android/build.gradle +++ /dev/null @@ -1,57 +0,0 @@ -buildscript { - repositories { - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:1.1.0' - } -} - -allprojects { - repositories { - jcenter() - } -} - -apply plugin: 'com.android.application' - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) -} - -android { - /******************************************************* - * The following variables: - * - androidBuildToolsVersion, - * - androidCompileSdkVersion - * - qt5AndroidDir - holds the path to qt android files - * needed to build any Qt application - * on Android. - * - * are defined in gradle.properties file. This file is - * updated by QtCreator and androiddeployqt tools. - * Changing them manually might break the compilation! - *******************************************************/ - - compileSdkVersion androidCompileSdkVersion.toInteger() - - buildToolsVersion androidBuildToolsVersion - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] - aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] - res.srcDirs = [qt5AndroidDir + '/res', 'res'] - resources.srcDirs = ['src'] - renderscript.srcDirs = ['src'] - assets.srcDirs = ['assets'] - jniLibs.srcDirs = ['libs'] - } - } - - lintOptions { - abortOnError false - } -} diff --git a/qt/i2pd_qt/android/libs/android-support-v4.jar b/qt/i2pd_qt/android/libs/android-support-v4.jar deleted file mode 100644 index 2ff47f4f..00000000 Binary files a/qt/i2pd_qt/android/libs/android-support-v4.jar and /dev/null differ diff --git a/qt/i2pd_qt/android/project.properties b/qt/i2pd_qt/android/project.properties deleted file mode 100644 index 4d07452b..00000000 --- a/qt/i2pd_qt/android/project.properties +++ /dev/null @@ -1,14 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-11 diff --git a/qt/i2pd_qt/android/res/drawable-hdpi/icon.png b/qt/i2pd_qt/android/res/drawable-hdpi/icon.png deleted file mode 100644 index 9a2f7404..00000000 Binary files a/qt/i2pd_qt/android/res/drawable-hdpi/icon.png and /dev/null differ diff --git a/qt/i2pd_qt/android/res/drawable/itoopie_notification_icon.png b/qt/i2pd_qt/android/res/drawable/itoopie_notification_icon.png deleted file mode 100644 index fa99e7fc..00000000 Binary files a/qt/i2pd_qt/android/res/drawable/itoopie_notification_icon.png and /dev/null differ diff --git a/qt/i2pd_qt/android/res/layout/splash.xml b/qt/i2pd_qt/android/res/layout/splash.xml deleted file mode 100644 index 476d91a8..00000000 --- a/qt/i2pd_qt/android/res/layout/splash.xml +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/qt/i2pd_qt/android/res/values-de/strings.xml b/qt/i2pd_qt/android/res/values-de/strings.xml deleted file mode 100644 index 320d9ec3..00000000 --- a/qt/i2pd_qt/android/res/values-de/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Ministro-Dienst wurde nicht gefunden.\nAnwendung kann nicht gestartet werden - Diese Anwendung benötigt den Ministro-Dienst. Möchten Sie ihn installieren? - In Ihrer Anwendung ist ein schwerwiegender Fehler aufgetreten, sie kann nicht fortgesetzt werden - diff --git a/qt/i2pd_qt/android/res/values-el/strings.xml b/qt/i2pd_qt/android/res/values-el/strings.xml deleted file mode 100644 index 3cab212f..00000000 --- a/qt/i2pd_qt/android/res/values-el/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Δεν ήταν δυνατή η εύρεση της υπηρεσίας Ministro. Δεν είναι δυνατή η εκκίνηση της εφαρμογής. - Η εφαρμογή απαιτεί την υπηρεσία Ministro. Να εγκατασταθεί η υπηρεσία? - Παρουσιάστηκε ένα κρίσιμο σφάλμα και η εφαρμογή δεν μπορεί να συνεχίσει. - diff --git a/qt/i2pd_qt/android/res/values-es/strings.xml b/qt/i2pd_qt/android/res/values-es/strings.xml deleted file mode 100644 index cf0b54d0..00000000 --- a/qt/i2pd_qt/android/res/values-es/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Servicio Ministro inesistente. Imposible ejecutar la aplicación. - Esta aplicación requiere el servicio Ministro. Instalarlo? - La aplicación ha causado un error grave y no es posible continuar. - diff --git a/qt/i2pd_qt/android/res/values-et/strings.xml b/qt/i2pd_qt/android/res/values-et/strings.xml deleted file mode 100644 index d55a3c14..00000000 --- a/qt/i2pd_qt/android/res/values-et/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Ei suuda leida Ministro teenust.\nProgrammi ei saa käivitada. - See programm vajab Ministro teenust.\nKas soovite paigaldada? - Programmiga juhtus fataalne viga.\nKahjuks ei saa jätkata. - diff --git a/qt/i2pd_qt/android/res/values-fa/strings.xml b/qt/i2pd_qt/android/res/values-fa/strings.xml deleted file mode 100644 index a8d1b874..00000000 --- a/qt/i2pd_qt/android/res/values-fa/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - سرویس Ministro را پیدا نمی‌کند. برنامه نمی‌تواند آغاز شود. - این نرم‌افزار به سرویس Ministro احتیاج دارد. آیا دوست دارید آن را نصب کنید؟ - خطایی اساسی در برنامه‌تان رخ داد و اجرای برنامه نمی‌تواند ادامه یابد. - diff --git a/qt/i2pd_qt/android/res/values-fr/strings.xml b/qt/i2pd_qt/android/res/values-fr/strings.xml deleted file mode 100644 index efc0fb6e..00000000 --- a/qt/i2pd_qt/android/res/values-fr/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Le service Ministro est introuvable.\nL\'application ne peut pas démarrer. - Cette application requiert le service Ministro. Voulez-vous l\'installer? - Votre application a rencontré une erreur fatale et ne peut pas continuer. - diff --git a/qt/i2pd_qt/android/res/values-id/strings.xml b/qt/i2pd_qt/android/res/values-id/strings.xml deleted file mode 100644 index aaa5bda0..00000000 --- a/qt/i2pd_qt/android/res/values-id/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Layanan Ministro tidak bisa ditemukan.\nAplikasi tidak bisa dimulai. - Aplikasi ini membutuhkan layanan Ministro. Apakah Anda ingin menginstalnya? - Aplikasi Anda mengalami kesalahan fatal dan tidak dapat melanjutkan. - diff --git a/qt/i2pd_qt/android/res/values-it/strings.xml b/qt/i2pd_qt/android/res/values-it/strings.xml deleted file mode 100644 index 4773419c..00000000 --- a/qt/i2pd_qt/android/res/values-it/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Servizio Ministro inesistente. Impossibile eseguire \nl\'applicazione. - Questa applicazione richiede il servizio Ministro.Installarlo? - L\'applicazione ha provocato un errore grave e non puo\' continuare. - diff --git a/qt/i2pd_qt/android/res/values-ja/strings.xml b/qt/i2pd_qt/android/res/values-ja/strings.xml deleted file mode 100644 index ba1cfda9..00000000 --- a/qt/i2pd_qt/android/res/values-ja/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Ministroサービスが見つかりません。\nアプリケーションが起動できません。 - このアプリケーションにはMinistroサービスが必要です。 インストールしてもよろしいですか? - アプリケーションで致命的なエラーが発生したため続行できません。 - diff --git a/qt/i2pd_qt/android/res/values-ms/strings.xml b/qt/i2pd_qt/android/res/values-ms/strings.xml deleted file mode 100644 index 6e3952ea..00000000 --- a/qt/i2pd_qt/android/res/values-ms/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Tidak jumpa servis Ministro.\nAplikasi tidak boleh dimulakan. - Aplikasi ini memerlukan servis Ministro. Adakah anda ingin pasang servis itu? - Aplikasi anda menemui ralat muat dan tidak boleh diteruskan. - diff --git a/qt/i2pd_qt/android/res/values-nb/strings.xml b/qt/i2pd_qt/android/res/values-nb/strings.xml deleted file mode 100644 index 8a550e99..00000000 --- a/qt/i2pd_qt/android/res/values-nb/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Kan ikke finne tjenesten Ministro. Applikasjonen kan ikke starte. - Denne applikasjonen krever tjenesten Ministro. Vil du installere denne? - Applikasjonen fikk en kritisk feil og kan ikke fortsette - diff --git a/qt/i2pd_qt/android/res/values-nl/strings.xml b/qt/i2pd_qt/android/res/values-nl/strings.xml deleted file mode 100644 index 8a45a724..00000000 --- a/qt/i2pd_qt/android/res/values-nl/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - De Ministro service is niet gevonden.\nDe applicatie kan niet starten. - Deze applicatie maakt gebruik van de Ministro service. Wilt u deze installeren? - Er is een fatale fout in de applicatie opgetreden. De applicatie kan niet verder gaan. - diff --git a/qt/i2pd_qt/android/res/values-pl/strings.xml b/qt/i2pd_qt/android/res/values-pl/strings.xml deleted file mode 100644 index 9fefc92d..00000000 --- a/qt/i2pd_qt/android/res/values-pl/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Usługa Ministro nie została znaleziona.\nAplikacja nie może zostać uruchomiona. - Aplikacja wymaga usługi Ministro. Czy chcesz ją zainstalować? - Wystąpił błąd krytyczny. Aplikacja zostanie zamknięta. - diff --git a/qt/i2pd_qt/android/res/values-pt-rBR/strings.xml b/qt/i2pd_qt/android/res/values-pt-rBR/strings.xml deleted file mode 100644 index 67ac3f9f..00000000 --- a/qt/i2pd_qt/android/res/values-pt-rBR/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Não foi possível encontrar o serviço Ministro.\nA aplicação não pode iniciar. - Essa aplicação requer o serviço Ministro. Gostaria de instalá-lo? - Sua aplicação encontrou um erro fatal e não pode continuar. - diff --git a/qt/i2pd_qt/android/res/values-ro/strings.xml b/qt/i2pd_qt/android/res/values-ro/strings.xml deleted file mode 100644 index f88a442b..00000000 --- a/qt/i2pd_qt/android/res/values-ro/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Serviciul Ministro nu poate fi găsit.\nAplicaţia nu poate porni. - Această aplicaţie necesită serviciul Ministro.\nDoriţi să-l instalaţi? - Aplicaţia dumneavoastră a întâmpinat o eroare fatală şi nu poate continua. - diff --git a/qt/i2pd_qt/android/res/values-rs/strings.xml b/qt/i2pd_qt/android/res/values-rs/strings.xml deleted file mode 100644 index 3194ce90..00000000 --- a/qt/i2pd_qt/android/res/values-rs/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Ministro servise nije pronađen. Aplikacija ne može biti pokrenuta. - Ova aplikacija zahteva Ministro servis. Želite li da ga instalirate? - Vaša aplikacija je naišla na fatalnu grešku i ne može nastaviti sa radom. - diff --git a/qt/i2pd_qt/android/res/values-ru/strings.xml b/qt/i2pd_qt/android/res/values-ru/strings.xml deleted file mode 100644 index d3cee80f..00000000 --- a/qt/i2pd_qt/android/res/values-ru/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Сервис Ministro не найден.\nПриложение нельзя запустить. - Этому приложению необходим сервис Ministro. Вы хотите его установить? - Ваше приложение столкнулось с фатальной ошибкой и не может более работать. - diff --git a/qt/i2pd_qt/android/res/values-zh-rCN/strings.xml b/qt/i2pd_qt/android/res/values-zh-rCN/strings.xml deleted file mode 100644 index 2eb12698..00000000 --- a/qt/i2pd_qt/android/res/values-zh-rCN/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 无法找到Ministro服务。\n应用程序无法启动。 - 此应用程序需要Ministro服务。您想安装它吗? - 您的应用程序遇到一个致命错误导致它无法继续。 - diff --git a/qt/i2pd_qt/android/res/values-zh-rTW/strings.xml b/qt/i2pd_qt/android/res/values-zh-rTW/strings.xml deleted file mode 100644 index f6e68efa..00000000 --- a/qt/i2pd_qt/android/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 無法找到Ministro服務。\n應用程序無法啟動。 - 此應用程序需要Ministro服務。您想安裝它嗎? - 您的應用程序遇到一個致命錯誤導致它無法繼續。 - diff --git a/qt/i2pd_qt/android/res/values/libs.xml b/qt/i2pd_qt/android/res/values/libs.xml deleted file mode 100644 index 4d68673c..00000000 --- a/qt/i2pd_qt/android/res/values/libs.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - https://download.qt-project.org/ministro/android/qt5/qt-5.4 - - - - - - - - - - - - - - - - - - - - diff --git a/qt/i2pd_qt/android/res/values/strings.xml b/qt/i2pd_qt/android/res/values/strings.xml deleted file mode 100644 index 713c7aa0..00000000 --- a/qt/i2pd_qt/android/res/values/strings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - Can\'t find Ministro service.\nThe application can\'t start. - This application requires Ministro service. Would you like to install it? - Your application encountered a fatal error and cannot continue. - i2pd started - i2pd stopped - i2pd - diff --git a/qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistro.aidl b/qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistro.aidl deleted file mode 100644 index e23cb699..00000000 --- a/qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistro.aidl +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (c) 2011-2013, BogDan Vatra - Contact: http://www.qt.io/licensing/ - - Commercial License Usage - Licensees holding valid commercial Qt licenses may use this file in - accordance with the commercial license agreement provided with the - Software or, alternatively, in accordance with the terms contained in - a written agreement between you and The Qt Company. For licensing terms - and conditions see http://www.qt.io/terms-conditions. For further - information use the contact form at http://www.qt.io/contact-us. - - BSD License Usage - Alternatively, this file may be used under the BSD license as follows: - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -package org.kde.necessitas.ministro; - -import org.kde.necessitas.ministro.IMinistroCallback; - -interface IMinistro -{ -/** -* Check/download required libs to run the application -* -* param callback - interface used by Minsitro service to notify the client when the loader is ready -* param parameters -* parameters fields: -* * Key Name Key type Explanations -* "sources" StringArray Sources list from where Ministro will download the libs. Make sure you are using ONLY secure locations. -* "repository" String Overwrites the default Ministro repository. Possible values: default, stable, testing and unstable -* "required.modules" StringArray Required modules by your application -* "application.title" String Application name, used to show more information to user -* "qt.provider" String Qt libs provider, currently only "necessitas" is supported. -* "minimum.ministro.api" Integer Minimum Ministro API level, used to check if Ministro service compatible with your application. Current API Level is 3 ! -* "minimum.qt.version" Integer Minimim Qt version (e.g. 0x040800, which means Qt 4.8.0, check http://qt-project.org/doc/qt-4.8/qtglobal.html#QT_VERSION)! -*/ - void requestLoader(in IMinistroCallback callback, in Bundle parameters); -} diff --git a/qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl b/qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl deleted file mode 100644 index f19caa69..00000000 --- a/qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (c) 2011-2013, BogDan Vatra - Contact: http://www.qt.io/licensing/ - - Commercial License Usage - Licensees holding valid commercial Qt licenses may use this file in - accordance with the commercial license agreement provided with the - Software or, alternatively, in accordance with the terms contained in - a written agreement between you and The Qt Company. For licensing terms - and conditions see http://www.qt.io/terms-conditions. For further - information use the contact form at http://www.qt.io/contact-us. - - BSD License Usage - Alternatively, this file may be used under the BSD license as follows: - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package org.kde.necessitas.ministro; - -oneway interface IMinistroCallback { -/** -* This method is called by the Ministro service back into the application which -* implements this interface. -* -* param in - loaderParams -* loaderParams fields: -* * Key Name Key type Explanations -* * "error.code" Integer See below -* * "error.message" String Missing if no error, otherwise will contain the error message translated into phone language where available. -* * "dex.path" String The list of jar/apk files containing classes and resources, needed to be passed to application DexClassLoader -* * "lib.path" String The list of directories containing native libraries; may be missing, needed to be passed to application DexClassLoader -* * "loader.class.name" String Loader class name. -* -* "error.code" field possible errors: -* - 0 no error. -* - 1 incompatible Ministro version. Ministro needs to be upgraded. -* - 2 not all modules could be satisfy. -* - 3 invalid parameters -* - 4 invalid qt version -* - 5 download canceled -* -* The parameter contains additional fields which are used by the loader to start your application, so it must be passed to the loader. -*/ - - void loaderReady(in Bundle loaderParams); -} diff --git a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java deleted file mode 100644 index aea50bf6..00000000 --- a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.purplei2p.i2pd; - -import org.qtproject.qt5.android.bindings.QtActivity; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.IBinder; - -public class I2PDMainActivity extends QtActivity -{ - - private static I2PDMainActivity instance; - - public I2PDMainActivity() {} - - /* (non-Javadoc) - * @see org.qtproject.qt5.android.bindings.QtActivity#onCreate(android.os.Bundle) - */ - @Override - public void onCreate(Bundle savedInstanceState) { - I2PDMainActivity.setInstance(this); - super.onCreate(savedInstanceState); - - //set the app be foreground (do not unload when RAM needed) - doBindService(); - } - - /* (non-Javadoc) - * @see org.qtproject.qt5.android.bindings.QtActivity#onDestroy() - */ - @Override - protected void onDestroy() { - I2PDMainActivity.setInstance(null); - doUnbindService(); - super.onDestroy(); - } - - public static I2PDMainActivity getInstance() { - return instance; - } - - private static void setInstance(I2PDMainActivity instance) { - I2PDMainActivity.instance = instance; - } - - - -// private LocalService mBoundService; - - private ServiceConnection mConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - // This is called when the connection with the service has been - // established, giving us the service object we can use to - // interact with the service. Because we have bound to a explicit - // service that we know is running in our own process, we can - // cast its IBinder to a concrete class and directly access it. -// mBoundService = ((LocalService.LocalBinder)service).getService(); - - // Tell the user about this for our demo. -// Toast.makeText(Binding.this, R.string.local_service_connected, -// Toast.LENGTH_SHORT).show(); - } - - public void onServiceDisconnected(ComponentName className) { - // This is called when the connection with the service has been - // unexpectedly disconnected -- that is, its process crashed. - // Because it is running in our same process, we should never - // see this happen. -// mBoundService = null; -// Toast.makeText(Binding.this, R.string.local_service_disconnected, -// Toast.LENGTH_SHORT).show(); - } - }; - - private boolean mIsBound; - - private void doBindService() { - // Establish a connection with the service. We use an explicit - // class name because we want a specific service implementation that - // we know will be running in our own process (and thus won't be - // supporting component replacement by other applications). - bindService(new Intent(this, - LocalService.class), mConnection, Context.BIND_AUTO_CREATE); - mIsBound = true; - } - - void doUnbindService() { - if (mIsBound) { - // Detach our existing connection. - unbindService(mConnection); - mIsBound = false; - } - } -} diff --git a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java deleted file mode 100644 index e2901504..00000000 --- a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.purplei2p.i2pd; - -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Intent; -import android.os.Binder; -import android.os.IBinder; -import android.support.v4.app.NotificationCompat; -import android.util.Log; -import android.widget.Toast; - -public class LocalService extends Service { -// private NotificationManager mNM; - - // Unique Identification Number for the Notification. - // We use it on Notification start, and to cancel it. - private int NOTIFICATION = R.string.local_service_started; - - /** - * Class for clients to access. Because we know this service always - * runs in the same process as its clients, we don't need to deal with - * IPC. - */ - public class LocalBinder extends Binder { - LocalService getService() { - return LocalService.this; - } - } - - @Override - public void onCreate() { -// mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - - // Display a notification about us starting. We put an icon in the status bar. - showNotification(); - - - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Log.i("LocalService", "Received start id " + startId + ": " + intent); - return START_NOT_STICKY; - } - - @Override - public void onDestroy() { - // Cancel the persistent notification. - //mNM.cancel(NOTIFICATION); - stopForeground(true); - - // Tell the user we stopped. - Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show(); - } - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - // This is the object that receives interactions from clients. See - // RemoteService for a more complete example. - private final IBinder mBinder = new LocalBinder(); - - /** - * Show a notification while this service is running. - */ - private void showNotification() { - // In this sample, we'll use the same text for the ticker and the expanded notification - CharSequence text = getText(R.string.local_service_started); - - // The PendingIntent to launch our activity if the user selects this notification - PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - new Intent(this, I2PDMainActivity.class), 0); - - // Set the info for the views that show in the notification panel. - Notification notification = new NotificationCompat.Builder(this) - .setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon - .setTicker(text) // the status text - .setWhen(System.currentTimeMillis()) // the time stamp - .setContentTitle(getText(R.string.local_service_label)) // the label of the entry - .setContentText(text) // the contents of the entry - .setContentIntent(contentIntent) // The intent to send when the entry is clicked - .build(); - - // Send the notification. - //mNM.notify(NOTIFICATION, notification); - startForeground(NOTIFICATION, notification); - } -} \ No newline at end of file diff --git a/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java b/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java deleted file mode 100644 index 9c607109..00000000 --- a/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ /dev/null @@ -1,1621 +0,0 @@ -/* - Copyright (c) 2012-2013, BogDan Vatra - Contact: http://www.qt.io/licensing/ - - Commercial License Usage - Licensees holding valid commercial Qt licenses may use this file in - accordance with the commercial license agreement provided with the - Software or, alternatively, in accordance with the terms contained in - a written agreement between you and The Qt Company. For licensing terms - and conditions see http://www.qt.io/terms-conditions. For further - information use the contact form at http://www.qt.io/contact-us. - - BSD License Usage - Alternatively, this file may be used under the BSD license as follows: - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package org.qtproject.qt5.android.bindings; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.io.InputStream; -import java.io.FileOutputStream; -import java.io.FileInputStream; -import java.io.DataOutputStream; -import java.io.DataInputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; - -import org.kde.necessitas.ministro.IMinistro; -import org.kde.necessitas.ministro.IMinistroCallback; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageInfo; -import android.content.res.Configuration; -import android.content.res.Resources.Theme; -import android.content.res.AssetManager; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.drawable.ColorDrawable; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.AttributeSet; -import android.util.Log; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.view.Window; -import android.view.WindowManager.LayoutParams; -import android.view.accessibility.AccessibilityEvent; -import dalvik.system.DexClassLoader; - -//@ANDROID-11 -import android.app.Fragment; -import android.view.ActionMode; -import android.view.ActionMode.Callback; -//@ANDROID-11 - - -public class QtActivity extends Activity -{ - private final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro installation is finished - private static final int MINISTRO_API_LEVEL = 5; // Ministro api level (check IMinistro.aidl file) - private static final int NECESSITAS_API_LEVEL = 2; // Necessitas api level used by platform plugin - private static final int QT_VERSION = 0x050100; // This app requires at least Qt version 5.1.0 - - private static final String ERROR_CODE_KEY = "error.code"; - private static final String ERROR_MESSAGE_KEY = "error.message"; - private static final String DEX_PATH_KEY = "dex.path"; - private static final String LIB_PATH_KEY = "lib.path"; - private static final String LOADER_CLASS_NAME_KEY = "loader.class.name"; - private static final String NATIVE_LIBRARIES_KEY = "native.libraries"; - private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables"; - private static final String APPLICATION_PARAMETERS_KEY = "application.parameters"; - private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries"; - private static final String BUNDLED_IN_LIB_RESOURCE_ID_KEY = "android.app.bundled_in_lib_resource_id"; - private static final String BUNDLED_IN_ASSETS_RESOURCE_ID_KEY = "android.app.bundled_in_assets_resource_id"; - private static final String MAIN_LIBRARY_KEY = "main.library"; - private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes"; - private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level"; - private static final String EXTRACT_STYLE_KEY = "extract.android.style"; - - /// Ministro server parameter keys - private static final String REQUIRED_MODULES_KEY = "required.modules"; - private static final String APPLICATION_TITLE_KEY = "application.title"; - private static final String MINIMUM_MINISTRO_API_KEY = "minimum.ministro.api"; - private static final String MINIMUM_QT_VERSION_KEY = "minimum.qt.version"; - private static final String SOURCES_KEY = "sources"; // needs MINISTRO_API_LEVEL >=3 !!! - // Use this key to specify any 3rd party sources urls - // Ministro will download these repositories into their - // own folders, check http://community.kde.org/Necessitas/Ministro - // for more details. - - private static final String REPOSITORY_KEY = "repository"; // use this key to overwrite the default ministro repsitory - private static final String ANDROID_THEMES_KEY = "android.themes"; // themes that your application uses - - - public String APPLICATION_PARAMETERS = null; // use this variable to pass any parameters to your application, - // the parameters must not contain any white spaces - // and must be separated with "\t" - // e.g "-param1\t-param2=value2\t-param3\tvalue3" - - public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=1\tQT_USE_ANDROID_NATIVE_DIALOGS=1\t"; - // use this variable to add any environment variables to your application. - // the env vars must be separated with "\t" - // e.g. "ENV_VAR1=1\tENV_VAR2=2\t" - // Currently the following vars are used by the android plugin: - // * QT_USE_ANDROID_NATIVE_STYLE - 1 to use the android widget style if available. - // * QT_USE_ANDROID_NATIVE_DIALOGS -1 to use the android native dialogs. - - public String[] QT_ANDROID_THEMES = null; // A list with all themes that your application want to use. - // The name of the theme must be the same with any theme from - // http://developer.android.com/reference/android/R.style.html - // The most used themes are: - // * "Theme" - (fallback) check http://developer.android.com/reference/android/R.style.html#Theme - // * "Theme_Black" - check http://developer.android.com/reference/android/R.style.html#Theme_Black - // * "Theme_Light" - (default for API <=10) check http://developer.android.com/reference/android/R.style.html#Theme_Light - // * "Theme_Holo" - check http://developer.android.com/reference/android/R.style.html#Theme_Holo - // * "Theme_Holo_Light" - (default for API 11-13) check http://developer.android.com/reference/android/R.style.html#Theme_Holo_Light - // * "Theme_DeviceDefault" - check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault - // * "Theme_DeviceDefault_Light" - (default for API 14+) check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault_Light - - public String QT_ANDROID_DEFAULT_THEME = null; // sets the default theme. - - private static final int INCOMPATIBLE_MINISTRO_VERSION = 1; // Incompatible Ministro version. Ministro needs to be upgraded. - private static final int BUFFER_SIZE = 1024; - - private ActivityInfo m_activityInfo = null; // activity info object, used to access the libs and the strings - private DexClassLoader m_classLoader = null; // loader object - private String[] m_sources = {"https://download.qt-project.org/ministro/android/qt5/qt-5.2"}; // Make sure you are using ONLY secure locations - private String m_repository = "default"; // Overwrites the default Ministro repository - // Possible values: - // * default - Ministro default repository set with "Ministro configuration tool". - // By default the stable version is used. Only this or stable repositories should - // be used in production. - // * stable - stable repository, only this and default repositories should be used - // in production. - // * testing - testing repository, DO NOT use this repository in production, - // this repository is used to push a new release, and should be used to test your application. - // * unstable - unstable repository, DO NOT use this repository in production, - // this repository is used to push Qt snapshots. - private String[] m_qtLibs = null; // required qt libs - private int m_displayDensity = -1; - - public QtActivity() - { - if (Build.VERSION.SDK_INT <= 10) { - QT_ANDROID_THEMES = new String[] {"Theme_Light"}; - QT_ANDROID_DEFAULT_THEME = "Theme_Light"; - } - else if ((Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT <= 13) || Build.VERSION.SDK_INT >= 21){ - QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"}; - QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light"; - } else { - QT_ANDROID_THEMES = new String[] {"Theme_DeviceDefault_Light"}; - QT_ANDROID_DEFAULT_THEME = "Theme_DeviceDefault_Light"; - } - } - - // this function is used to load and start the loader - private void loadApplication(Bundle loaderParams) - { - try { - final int errorCode = loaderParams.getInt(ERROR_CODE_KEY); - if (errorCode != 0) { - if (errorCode == INCOMPATIBLE_MINISTRO_VERSION) { - downloadUpgradeMinistro(loaderParams.getString(ERROR_MESSAGE_KEY)); - return; - } - - // fatal error, show the error and quit - AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create(); - errorDialog.setMessage(loaderParams.getString(ERROR_MESSAGE_KEY)); - errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - finish(); - } - }); - errorDialog.show(); - return; - } - - // add all bundled Qt libs to loader params - ArrayList libs = new ArrayList(); - if ( m_activityInfo.metaData.containsKey("android.app.bundled_libs_resource_id") ) - libs.addAll(Arrays.asList(getResources().getStringArray(m_activityInfo.metaData.getInt("android.app.bundled_libs_resource_id")))); - - String libName = null; - if ( m_activityInfo.metaData.containsKey("android.app.lib_name") ) { - libName = m_activityInfo.metaData.getString("android.app.lib_name"); - loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function - } - - loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs); - loaderParams.putInt(NECESSITAS_API_LEVEL_KEY, NECESSITAS_API_LEVEL); - - // load and start QtLoader class - m_classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files - getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written. - loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists) - getClassLoader()); // parent loader - - @SuppressWarnings("rawtypes") - Class loaderClass = m_classLoader.loadClass(loaderParams.getString(LOADER_CLASS_NAME_KEY)); // load QtLoader class - Object qtLoader = loaderClass.newInstance(); // create an instance - Method prepareAppMethod = qtLoader.getClass().getMethod("loadApplication", - Activity.class, - ClassLoader.class, - Bundle.class); - if (!(Boolean)prepareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams)) - throw new Exception(""); - - QtApplication.setQtActivityDelegate(qtLoader); - - // now load the application library so it's accessible from this class loader - if (libName != null) - System.loadLibrary(libName); - - Method startAppMethod=qtLoader.getClass().getMethod("startApplication"); - if (!(Boolean)startAppMethod.invoke(qtLoader)) - throw new Exception(""); - - } catch (Exception e) { - e.printStackTrace(); - AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create(); - if (m_activityInfo.metaData.containsKey("android.app.fatal_error_msg")) - errorDialog.setMessage(m_activityInfo.metaData.getString("android.app.fatal_error_msg")); - else - errorDialog.setMessage("Fatal error, your application can't be started."); - - errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - finish(); - } - }); - errorDialog.show(); - } - } - - private ServiceConnection m_ministroConnection=new ServiceConnection() { - private IMinistro m_service = null; - @Override - public void onServiceConnected(ComponentName name, IBinder service) - { - m_service = IMinistro.Stub.asInterface(service); - try { - if (m_service != null) { - Bundle parameters = new Bundle(); - parameters.putStringArray(REQUIRED_MODULES_KEY, m_qtLibs); - parameters.putString(APPLICATION_TITLE_KEY, (String)QtActivity.this.getTitle()); - parameters.putInt(MINIMUM_MINISTRO_API_KEY, MINISTRO_API_LEVEL); - parameters.putInt(MINIMUM_QT_VERSION_KEY, QT_VERSION); - parameters.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES); - if (APPLICATION_PARAMETERS != null) - parameters.putString(APPLICATION_PARAMETERS_KEY, APPLICATION_PARAMETERS); - parameters.putStringArray(SOURCES_KEY, m_sources); - parameters.putString(REPOSITORY_KEY, m_repository); - if (QT_ANDROID_THEMES != null) - parameters.putStringArray(ANDROID_THEMES_KEY, QT_ANDROID_THEMES); - m_service.requestLoader(m_ministroCallback, parameters); - } - } catch (RemoteException e) { - e.printStackTrace(); - } - } - - private IMinistroCallback m_ministroCallback = new IMinistroCallback.Stub() { - // this function is called back by Ministro. - @Override - public void loaderReady(final Bundle loaderParams) throws RemoteException { - runOnUiThread(new Runnable() { - @Override - public void run() { - unbindService(m_ministroConnection); - loadApplication(loaderParams); - } - }); - } - }; - - @Override - public void onServiceDisconnected(ComponentName name) { - m_service = null; - } - }; - - private void downloadUpgradeMinistro(String msg) - { - AlertDialog.Builder downloadDialog = new AlertDialog.Builder(this); - downloadDialog.setMessage(msg); - downloadDialog.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - try { - Uri uri = Uri.parse("market://search?q=pname:org.kde.necessitas.ministro"); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivityForResult(intent, MINISTRO_INSTALL_REQUEST_CODE); - } catch (Exception e) { - e.printStackTrace(); - ministroNotFound(); - } - } - }); - - downloadDialog.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - QtActivity.this.finish(); - } - }); - downloadDialog.show(); - } - - private void ministroNotFound() - { - AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create(); - - if (m_activityInfo.metaData.containsKey("android.app.ministro_not_found_msg")) - errorDialog.setMessage(m_activityInfo.metaData.getString("android.app.ministro_not_found_msg")); - else - errorDialog.setMessage("Can't find Ministro service.\nThe application can't start."); - - errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - finish(); - } - }); - errorDialog.show(); - } - - static private void copyFile(InputStream inputStream, OutputStream outputStream) - throws IOException - { - byte[] buffer = new byte[BUFFER_SIZE]; - - int count; - while ((count = inputStream.read(buffer)) > 0) - outputStream.write(buffer, 0, count); - } - - - private void copyAsset(String source, String destination) - throws IOException - { - // Already exists, we don't have to do anything - File destinationFile = new File(destination); - if (destinationFile.exists()) - return; - - File parentDirectory = destinationFile.getParentFile(); - if (!parentDirectory.exists()) - parentDirectory.mkdirs(); - - destinationFile.createNewFile(); - - AssetManager assetsManager = getAssets(); - InputStream inputStream = assetsManager.open(source); - OutputStream outputStream = new FileOutputStream(destinationFile); - copyFile(inputStream, outputStream); - - inputStream.close(); - outputStream.close(); - } - - private static void createBundledBinary(String source, String destination) - throws IOException - { - // Already exists, we don't have to do anything - File destinationFile = new File(destination); - if (destinationFile.exists()) - return; - - File parentDirectory = destinationFile.getParentFile(); - if (!parentDirectory.exists()) - parentDirectory.mkdirs(); - - destinationFile.createNewFile(); - - InputStream inputStream = new FileInputStream(source); - OutputStream outputStream = new FileOutputStream(destinationFile); - copyFile(inputStream, outputStream); - - inputStream.close(); - outputStream.close(); - } - - private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion) - { - File versionFile = new File(pluginsPrefix + "cache.version"); - - long cacheVersion = 0; - if (versionFile.exists() && versionFile.canRead()) { - try { - DataInputStream inputStream = new DataInputStream(new FileInputStream(versionFile)); - cacheVersion = inputStream.readLong(); - inputStream.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (cacheVersion != packageVersion) { - deleteRecursively(new File(pluginsPrefix)); - return true; - } else { - return false; - } - } - - private void extractBundledPluginsAndImports(String pluginsPrefix) - throws IOException - { - ArrayList libs = new ArrayList(); - - String libsDir = getApplicationInfo().nativeLibraryDir + "/"; - - long packageVersion = -1; - try { - PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0); - packageVersion = packageInfo.lastUpdateTime; - } catch (Exception e) { - e.printStackTrace(); - } - - if (!cleanCacheIfNecessary(pluginsPrefix, packageVersion)) - return; - - { - File versionFile = new File(pluginsPrefix + "cache.version"); - - File parentDirectory = versionFile.getParentFile(); - if (!parentDirectory.exists()) - parentDirectory.mkdirs(); - - versionFile.createNewFile(); - - DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(versionFile)); - outputStream.writeLong(packageVersion); - outputStream.close(); - } - - { - String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY; - java.util.Set keys = m_activityInfo.metaData.keySet(); - if (m_activityInfo.metaData.containsKey(key)) { - String[] list = getResources().getStringArray(m_activityInfo.metaData.getInt(key)); - - for (String bundledImportBinary : list) { - String[] split = bundledImportBinary.split(":"); - String sourceFileName = libsDir + split[0]; - String destinationFileName = pluginsPrefix + split[1]; - createBundledBinary(sourceFileName, destinationFileName); - } - } - } - - { - String key = BUNDLED_IN_ASSETS_RESOURCE_ID_KEY; - if (m_activityInfo.metaData.containsKey(key)) { - String[] list = getResources().getStringArray(m_activityInfo.metaData.getInt(key)); - - for (String fileName : list) { - String[] split = fileName.split(":"); - String sourceFileName = split[0]; - String destinationFileName = pluginsPrefix + split[1]; - copyAsset(sourceFileName, destinationFileName); - } - } - - } - } - - private void deleteRecursively(File directory) - { - File[] files = directory.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory()) - deleteRecursively(file); - else - file.delete(); - } - - directory.delete(); - } - } - - private void cleanOldCacheIfNecessary(String oldLocalPrefix, String localPrefix) - { - File newCache = new File(localPrefix); - if (!newCache.exists()) { - { - File oldPluginsCache = new File(oldLocalPrefix + "plugins/"); - if (oldPluginsCache.exists() && oldPluginsCache.isDirectory()) - deleteRecursively(oldPluginsCache); - } - - { - File oldImportsCache = new File(oldLocalPrefix + "imports/"); - if (oldImportsCache.exists() && oldImportsCache.isDirectory()) - deleteRecursively(oldImportsCache); - } - - { - File oldQmlCache = new File(oldLocalPrefix + "qml/"); - if (oldQmlCache.exists() && oldQmlCache.isDirectory()) - deleteRecursively(oldQmlCache); - } - } - } - - private void startApp(final boolean firstStart) - { - try { - if (m_activityInfo.metaData.containsKey("android.app.qt_sources_resource_id")) { - int resourceId = m_activityInfo.metaData.getInt("android.app.qt_sources_resource_id"); - m_sources = getResources().getStringArray(resourceId); - } - - if (m_activityInfo.metaData.containsKey("android.app.repository")) - m_repository = m_activityInfo.metaData.getString("android.app.repository"); - - if (m_activityInfo.metaData.containsKey("android.app.qt_libs_resource_id")) { - int resourceId = m_activityInfo.metaData.getInt("android.app.qt_libs_resource_id"); - m_qtLibs = getResources().getStringArray(resourceId); - } - - if (m_activityInfo.metaData.containsKey("android.app.use_local_qt_libs") - && m_activityInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) { - ArrayList libraryList = new ArrayList(); - - - String localPrefix = "/data/local/tmp/qt/"; - if (m_activityInfo.metaData.containsKey("android.app.libs_prefix")) - localPrefix = m_activityInfo.metaData.getString("android.app.libs_prefix"); - - String pluginsPrefix = localPrefix; - - boolean bundlingQtLibs = false; - if (m_activityInfo.metaData.containsKey("android.app.bundle_local_qt_libs") - && m_activityInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) { - localPrefix = getApplicationInfo().dataDir + "/"; - pluginsPrefix = localPrefix + "qt-reserved-files/"; - cleanOldCacheIfNecessary(localPrefix, pluginsPrefix); - extractBundledPluginsAndImports(pluginsPrefix); - bundlingQtLibs = true; - } - - if (m_qtLibs != null) { - for (int i=0;i 0) { - if (lib.startsWith("lib/")) - libraryList.add(localPrefix + lib); - else - libraryList.add(pluginsPrefix + lib); - } - } - } - - - String dexPaths = new String(); - String pathSeparator = System.getProperty("path.separator", ":"); - if (!bundlingQtLibs && m_activityInfo.metaData.containsKey("android.app.load_local_jars")) { - String[] jarFiles = m_activityInfo.metaData.getString("android.app.load_local_jars").split(":"); - for (String jar:jarFiles) { - if (jar.length() > 0) { - if (dexPaths.length() > 0) - dexPaths += pathSeparator; - dexPaths += localPrefix + jar; - } - } - } - - Bundle loaderParams = new Bundle(); - loaderParams.putInt(ERROR_CODE_KEY, 0); - loaderParams.putString(DEX_PATH_KEY, dexPaths); - loaderParams.putString(LOADER_CLASS_NAME_KEY, "org.qtproject.qt5.android.QtActivityDelegate"); - if (m_activityInfo.metaData.containsKey("android.app.static_init_classes")) { - loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY, - m_activityInfo.metaData.getString("android.app.static_init_classes").split(":")); - } - loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList); - - - String themePath = getApplicationInfo().dataDir + "/qt-reserved-files/android-style/"; - String stylePath = themePath + m_displayDensity + "/"; - if (!(new File(stylePath)).exists()) - loaderParams.putString(EXTRACT_STYLE_KEY, stylePath); - ENVIRONMENT_VARIABLES += "\tMINISTRO_ANDROID_STYLE_PATH=" + stylePath - + "\tQT_ANDROID_THEMES_ROOT_PATH=" + themePath; - - loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES - + "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml" - + "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports" - + "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins"); - - if (APPLICATION_PARAMETERS != null) { - loaderParams.putString(APPLICATION_PARAMETERS_KEY, APPLICATION_PARAMETERS); - } else { - Intent intent = getIntent(); - if (intent != null) { - String parameters = intent.getStringExtra("applicationArguments"); - if (parameters != null) - loaderParams.putString(APPLICATION_PARAMETERS_KEY, parameters.replace(' ', '\t')); - } - } - - loadApplication(loaderParams); - return; - } - - try { - if (!bindService(new Intent(org.kde.necessitas.ministro.IMinistro.class.getCanonicalName()), - m_ministroConnection, - Context.BIND_AUTO_CREATE)) { - throw new SecurityException(""); - } - } catch (Exception e) { - if (firstStart) { - String msg = "This application requires Ministro service. Would you like to install it?"; - if (m_activityInfo.metaData.containsKey("android.app.ministro_needed_msg")) - msg = m_activityInfo.metaData.getString("android.app.ministro_needed_msg"); - downloadUpgradeMinistro(msg); - } else { - ministroNotFound(); - } - } - } catch (Exception e) { - Log.e(QtApplication.QtTAG, "Can't create main activity", e); - } - } - - - - /////////////////////////// forward all notifications //////////////////////////// - /////////////////////////// Super class calls //////////////////////////////////// - /////////////// PLEASE DO NOT CHANGE THE FOLLOWING CODE ////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - @Override - public boolean dispatchKeyEvent(KeyEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.dispatchKeyEvent != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchKeyEvent, event); - else - return super.dispatchKeyEvent(event); - } - public boolean super_dispatchKeyEvent(KeyEvent event) - { - return super.dispatchKeyEvent(event); - } - //--------------------------------------------------------------------------- - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.dispatchPopulateAccessibilityEvent != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchPopulateAccessibilityEvent, event); - else - return super.dispatchPopulateAccessibilityEvent(event); - } - public boolean super_dispatchPopulateAccessibilityEvent(AccessibilityEvent event) - { - return super_dispatchPopulateAccessibilityEvent(event); - } - //--------------------------------------------------------------------------- - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) - { - if (QtApplication.m_delegateObject != null && QtApplication.dispatchTouchEvent != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchTouchEvent, ev); - else - return super.dispatchTouchEvent(ev); - } - public boolean super_dispatchTouchEvent(MotionEvent event) - { - return super.dispatchTouchEvent(event); - } - //--------------------------------------------------------------------------- - - @Override - public boolean dispatchTrackballEvent(MotionEvent ev) - { - if (QtApplication.m_delegateObject != null && QtApplication.dispatchTrackballEvent != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchTrackballEvent, ev); - else - return super.dispatchTrackballEvent(ev); - } - public boolean super_dispatchTrackballEvent(MotionEvent event) - { - return super.dispatchTrackballEvent(event); - } - //--------------------------------------------------------------------------- - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) - { - - if (QtApplication.m_delegateObject != null && QtApplication.onActivityResult != null) { - QtApplication.invokeDelegateMethod(QtApplication.onActivityResult, requestCode, resultCode, data); - return; - } - if (requestCode == MINISTRO_INSTALL_REQUEST_CODE) - startApp(false); - super.onActivityResult(requestCode, resultCode, data); - } - public void super_onActivityResult(int requestCode, int resultCode, Intent data) - { - super.onActivityResult(requestCode, resultCode, data); - } - //--------------------------------------------------------------------------- - - @Override - protected void onApplyThemeResource(Theme theme, int resid, boolean first) - { - if (!QtApplication.invokeDelegate(theme, resid, first).invoked) - super.onApplyThemeResource(theme, resid, first); - } - public void super_onApplyThemeResource(Theme theme, int resid, boolean first) - { - super.onApplyThemeResource(theme, resid, first); - } - //--------------------------------------------------------------------------- - - - @Override - protected void onChildTitleChanged(Activity childActivity, CharSequence title) - { - if (!QtApplication.invokeDelegate(childActivity, title).invoked) - super.onChildTitleChanged(childActivity, title); - } - public void super_onChildTitleChanged(Activity childActivity, CharSequence title) - { - super.onChildTitleChanged(childActivity, title); - } - //--------------------------------------------------------------------------- - - @Override - public void onConfigurationChanged(Configuration newConfig) - { - if (!QtApplication.invokeDelegate(newConfig).invoked) - super.onConfigurationChanged(newConfig); - } - public void super_onConfigurationChanged(Configuration newConfig) - { - super.onConfigurationChanged(newConfig); - } - //--------------------------------------------------------------------------- - - @Override - public void onContentChanged() - { - if (!QtApplication.invokeDelegate().invoked) - super.onContentChanged(); - } - public void super_onContentChanged() - { - super.onContentChanged(); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onContextItemSelected(MenuItem item) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(item); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onContextItemSelected(item); - } - public boolean super_onContextItemSelected(MenuItem item) - { - return super.onContextItemSelected(item); - } - //--------------------------------------------------------------------------- - - @Override - public void onContextMenuClosed(Menu menu) - { - if (!QtApplication.invokeDelegate(menu).invoked) - super.onContextMenuClosed(menu); - } - public void super_onContextMenuClosed(Menu menu) - { - super.onContextMenuClosed(menu); - } - //--------------------------------------------------------------------------- - - @Override - public void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - - try { - m_activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA); - for (Field f : Class.forName("android.R$style").getDeclaredFields()) { - if (f.getInt(null) == m_activityInfo.getThemeResource()) { - QT_ANDROID_THEMES = new String[] {f.getName()}; - QT_ANDROID_DEFAULT_THEME = f.getName(); - } - } - } catch (Exception e) { - e.printStackTrace(); - finish(); - return; - } - - try { - setTheme(Class.forName("android.R$style").getDeclaredField(QT_ANDROID_DEFAULT_THEME).getInt(null)); - } catch (Exception e) { - e.printStackTrace(); - } - - if (Build.VERSION.SDK_INT > 10) { - try { - requestWindowFeature(Window.class.getField("FEATURE_ACTION_BAR").getInt(null)); - } catch (Exception e) { - e.printStackTrace(); - } - } else { - requestWindowFeature(Window.FEATURE_NO_TITLE); - } - - if (QtApplication.m_delegateObject != null && QtApplication.onCreate != null) { - QtApplication.invokeDelegateMethod(QtApplication.onCreate, savedInstanceState); - return; - } - - m_displayDensity = getResources().getDisplayMetrics().densityDpi; - - ENVIRONMENT_VARIABLES += "\tQT_ANDROID_THEME=" + QT_ANDROID_DEFAULT_THEME - + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + m_displayDensity + "\t"; - - if (null == getLastNonConfigurationInstance()) { - // if splash screen is defined, then show it - if (m_activityInfo.metaData.containsKey("android.app.splash_screen_drawable")) - getWindow().setBackgroundDrawableResource(m_activityInfo.metaData.getInt("android.app.splash_screen_drawable")); - else - getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000)); - - if (m_activityInfo.metaData.containsKey("android.app.background_running") - && m_activityInfo.metaData.getBoolean("android.app.background_running")) { - ENVIRONMENT_VARIABLES += "QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED=0\t"; - } else { - ENVIRONMENT_VARIABLES += "QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED=1\t"; - } - - if (m_activityInfo.metaData.containsKey("android.app.auto_screen_scale_factor") - && m_activityInfo.metaData.getBoolean("android.app.auto_screen_scale_factor")) { - ENVIRONMENT_VARIABLES += "QT_AUTO_SCREEN_SCALE_FACTOR=1\t"; - } - - startApp(true); - } - } - //--------------------------------------------------------------------------- - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) - { - if (!QtApplication.invokeDelegate(menu, v, menuInfo).invoked) - super.onCreateContextMenu(menu, v, menuInfo); - } - public void super_onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) - { - super.onCreateContextMenu(menu, v, menuInfo); - } - //--------------------------------------------------------------------------- - - @Override - public CharSequence onCreateDescription() - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(); - if (res.invoked) - return (CharSequence)res.methodReturns; - else - return super.onCreateDescription(); - } - public CharSequence super_onCreateDescription() - { - return super.onCreateDescription(); - } - //--------------------------------------------------------------------------- - - @Override - protected Dialog onCreateDialog(int id) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(id); - if (res.invoked) - return (Dialog)res.methodReturns; - else - return super.onCreateDialog(id); - } - public Dialog super_onCreateDialog(int id) - { - return super.onCreateDialog(id); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onCreateOptionsMenu(Menu menu) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(menu); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onCreateOptionsMenu(menu); - } - public boolean super_onCreateOptionsMenu(Menu menu) - { - return super.onCreateOptionsMenu(menu); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onCreatePanelMenu(int featureId, Menu menu) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, menu); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onCreatePanelMenu(featureId, menu); - } - public boolean super_onCreatePanelMenu(int featureId, Menu menu) - { - return super.onCreatePanelMenu(featureId, menu); - } - //--------------------------------------------------------------------------- - - - @Override - public View onCreatePanelView(int featureId) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId); - if (res.invoked) - return (View)res.methodReturns; - else - return super.onCreatePanelView(featureId); - } - public View super_onCreatePanelView(int featureId) - { - return super.onCreatePanelView(featureId); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(outBitmap, canvas); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onCreateThumbnail(outBitmap, canvas); - } - public boolean super_onCreateThumbnail(Bitmap outBitmap, Canvas canvas) - { - return super.onCreateThumbnail(outBitmap, canvas); - } - //--------------------------------------------------------------------------- - - @Override - public View onCreateView(String name, Context context, AttributeSet attrs) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(name, context, attrs); - if (res.invoked) - return (View)res.methodReturns; - else - return super.onCreateView(name, context, attrs); - } - public View super_onCreateView(String name, Context context, AttributeSet attrs) - { - return super.onCreateView(name, context, attrs); - } - //--------------------------------------------------------------------------- - - @Override - protected void onDestroy() - { - super.onDestroy(); - QtApplication.invokeDelegate(); - } - //--------------------------------------------------------------------------- - - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyDown, keyCode, event); - else - return super.onKeyDown(keyCode, event); - } - public boolean super_onKeyDown(int keyCode, KeyEvent event) - { - return super.onKeyDown(keyCode, event); - } - //--------------------------------------------------------------------------- - - - @Override - public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.onKeyMultiple != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyMultiple, keyCode, repeatCount, event); - else - return super.onKeyMultiple(keyCode, repeatCount, event); - } - public boolean super_onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) - { - return super.onKeyMultiple(keyCode, repeatCount, event); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyUp, keyCode, event); - else - return super.onKeyUp(keyCode, event); - } - public boolean super_onKeyUp(int keyCode, KeyEvent event) - { - return super.onKeyUp(keyCode, event); - } - //--------------------------------------------------------------------------- - - @Override - public void onLowMemory() - { - if (!QtApplication.invokeDelegate().invoked) - super.onLowMemory(); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, item); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onMenuItemSelected(featureId, item); - } - public boolean super_onMenuItemSelected(int featureId, MenuItem item) - { - return super.onMenuItemSelected(featureId, item); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onMenuOpened(int featureId, Menu menu) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, menu); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onMenuOpened(featureId, menu); - } - public boolean super_onMenuOpened(int featureId, Menu menu) - { - return super.onMenuOpened(featureId, menu); - } - //--------------------------------------------------------------------------- - - @Override - protected void onNewIntent(Intent intent) - { - if (!QtApplication.invokeDelegate(intent).invoked) - super.onNewIntent(intent); - } - public void super_onNewIntent(Intent intent) - { - super.onNewIntent(intent); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onOptionsItemSelected(MenuItem item) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(item); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onOptionsItemSelected(item); - } - public boolean super_onOptionsItemSelected(MenuItem item) - { - return super.onOptionsItemSelected(item); - } - //--------------------------------------------------------------------------- - - @Override - public void onOptionsMenuClosed(Menu menu) - { - if (!QtApplication.invokeDelegate(menu).invoked) - super.onOptionsMenuClosed(menu); - } - public void super_onOptionsMenuClosed(Menu menu) - { - super.onOptionsMenuClosed(menu); - } - //--------------------------------------------------------------------------- - - @Override - public void onPanelClosed(int featureId, Menu menu) - { - if (!QtApplication.invokeDelegate(featureId, menu).invoked) - super.onPanelClosed(featureId, menu); - } - public void super_onPanelClosed(int featureId, Menu menu) - { - super.onPanelClosed(featureId, menu); - } - //--------------------------------------------------------------------------- - - @Override - protected void onPause() - { - super.onPause(); - QtApplication.invokeDelegate(); - } - //--------------------------------------------------------------------------- - - @Override - protected void onPostCreate(Bundle savedInstanceState) - { - super.onPostCreate(savedInstanceState); - QtApplication.invokeDelegate(savedInstanceState); - } - //--------------------------------------------------------------------------- - - @Override - protected void onPostResume() - { - super.onPostResume(); - QtApplication.invokeDelegate(); - } - //--------------------------------------------------------------------------- - - @Override - protected void onPrepareDialog(int id, Dialog dialog) - { - if (!QtApplication.invokeDelegate(id, dialog).invoked) - super.onPrepareDialog(id, dialog); - } - public void super_onPrepareDialog(int id, Dialog dialog) - { - super.onPrepareDialog(id, dialog); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onPrepareOptionsMenu(Menu menu) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(menu); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onPrepareOptionsMenu(menu); - } - public boolean super_onPrepareOptionsMenu(Menu menu) - { - return super.onPrepareOptionsMenu(menu); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onPreparePanel(int featureId, View view, Menu menu) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, view, menu); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onPreparePanel(featureId, view, menu); - } - public boolean super_onPreparePanel(int featureId, View view, Menu menu) - { - return super.onPreparePanel(featureId, view, menu); - } - //--------------------------------------------------------------------------- - - @Override - protected void onRestart() - { - super.onRestart(); - QtApplication.invokeDelegate(); - } - //--------------------------------------------------------------------------- - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) - { - if (!QtApplication.invokeDelegate(savedInstanceState).invoked) - super.onRestoreInstanceState(savedInstanceState); - } - public void super_onRestoreInstanceState(Bundle savedInstanceState) - { - super.onRestoreInstanceState(savedInstanceState); - } - //--------------------------------------------------------------------------- - - @Override - protected void onResume() - { - super.onResume(); - QtApplication.invokeDelegate(); - } - //--------------------------------------------------------------------------- - - @Override - public Object onRetainNonConfigurationInstance() - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(); - if (res.invoked) - return res.methodReturns; - else - return super.onRetainNonConfigurationInstance(); - } - public Object super_onRetainNonConfigurationInstance() - { - return super.onRetainNonConfigurationInstance(); - } - //--------------------------------------------------------------------------- - - @Override - protected void onSaveInstanceState(Bundle outState) - { - if (!QtApplication.invokeDelegate(outState).invoked) - super.onSaveInstanceState(outState); - } - public void super_onSaveInstanceState(Bundle outState) - { - super.onSaveInstanceState(outState); - - } - //--------------------------------------------------------------------------- - - @Override - public boolean onSearchRequested() - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onSearchRequested(); - } - public boolean super_onSearchRequested() - { - return super.onSearchRequested(); - } - //--------------------------------------------------------------------------- - - @Override - protected void onStart() - { - super.onStart(); - QtApplication.invokeDelegate(); - } - //--------------------------------------------------------------------------- - - @Override - protected void onStop() - { - super.onStop(); - QtApplication.invokeDelegate(); - } - //--------------------------------------------------------------------------- - - @Override - protected void onTitleChanged(CharSequence title, int color) - { - if (!QtApplication.invokeDelegate(title, color).invoked) - super.onTitleChanged(title, color); - } - public void super_onTitleChanged(CharSequence title, int color) - { - super.onTitleChanged(title, color); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onTouchEvent(MotionEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.onTouchEvent != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onTouchEvent, event); - else - return super.onTouchEvent(event); - } - public boolean super_onTouchEvent(MotionEvent event) - { - return super.onTouchEvent(event); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onTrackballEvent(MotionEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.onTrackballEvent != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onTrackballEvent, event); - else - return super.onTrackballEvent(event); - } - public boolean super_onTrackballEvent(MotionEvent event) - { - return super.onTrackballEvent(event); - } - //--------------------------------------------------------------------------- - - @Override - public void onUserInteraction() - { - if (!QtApplication.invokeDelegate().invoked) - super.onUserInteraction(); - } - public void super_onUserInteraction() - { - super.onUserInteraction(); - } - //--------------------------------------------------------------------------- - - @Override - protected void onUserLeaveHint() - { - if (!QtApplication.invokeDelegate().invoked) - super.onUserLeaveHint(); - } - public void super_onUserLeaveHint() - { - super.onUserLeaveHint(); - } - //--------------------------------------------------------------------------- - - @Override - public void onWindowAttributesChanged(LayoutParams params) - { - if (!QtApplication.invokeDelegate(params).invoked) - super.onWindowAttributesChanged(params); - } - public void super_onWindowAttributesChanged(LayoutParams params) - { - super.onWindowAttributesChanged(params); - } - //--------------------------------------------------------------------------- - - @Override - public void onWindowFocusChanged(boolean hasFocus) - { - if (!QtApplication.invokeDelegate(hasFocus).invoked) - super.onWindowFocusChanged(hasFocus); - } - public void super_onWindowFocusChanged(boolean hasFocus) - { - super.onWindowFocusChanged(hasFocus); - } - //--------------------------------------------------------------------------- - - //////////////// Activity API 5 ///////////// -//@ANDROID-5 - @Override - public void onAttachedToWindow() - { - if (!QtApplication.invokeDelegate().invoked) - super.onAttachedToWindow(); - } - public void super_onAttachedToWindow() - { - super.onAttachedToWindow(); - } - //--------------------------------------------------------------------------- - - @Override - public void onBackPressed() - { - if (!QtApplication.invokeDelegate().invoked) - super.onBackPressed(); - } - public void super_onBackPressed() - { - super.onBackPressed(); - } - //--------------------------------------------------------------------------- - - @Override - public void onDetachedFromWindow() - { - if (!QtApplication.invokeDelegate().invoked) - super.onDetachedFromWindow(); - } - public void super_onDetachedFromWindow() - { - super.onDetachedFromWindow(); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onKeyLongPress(int keyCode, KeyEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.onKeyLongPress != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyLongPress, keyCode, event); - else - return super.onKeyLongPress(keyCode, event); - } - public boolean super_onKeyLongPress(int keyCode, KeyEvent event) - { - return super.onKeyLongPress(keyCode, event); - } - //--------------------------------------------------------------------------- -//@ANDROID-5 - -//////////////// Activity API 8 ///////////// -//@ANDROID-8 -@Override - protected Dialog onCreateDialog(int id, Bundle args) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(id, args); - if (res.invoked) - return (Dialog)res.methodReturns; - else - return super.onCreateDialog(id, args); - } - public Dialog super_onCreateDialog(int id, Bundle args) - { - return super.onCreateDialog(id, args); - } - //--------------------------------------------------------------------------- - - @Override - protected void onPrepareDialog(int id, Dialog dialog, Bundle args) - { - if (!QtApplication.invokeDelegate(id, dialog, args).invoked) - super.onPrepareDialog(id, dialog, args); - } - public void super_onPrepareDialog(int id, Dialog dialog, Bundle args) - { - super.onPrepareDialog(id, dialog, args); - } - //--------------------------------------------------------------------------- -//@ANDROID-8 - //////////////// Activity API 11 ///////////// - -//@ANDROID-11 - @Override - public boolean dispatchKeyShortcutEvent(KeyEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.dispatchKeyShortcutEvent != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchKeyShortcutEvent, event); - else - return super.dispatchKeyShortcutEvent(event); - } - public boolean super_dispatchKeyShortcutEvent(KeyEvent event) - { - return super.dispatchKeyShortcutEvent(event); - } - //--------------------------------------------------------------------------- - - @Override - public void onActionModeFinished(ActionMode mode) - { - if (!QtApplication.invokeDelegate(mode).invoked) - super.onActionModeFinished(mode); - } - public void super_onActionModeFinished(ActionMode mode) - { - super.onActionModeFinished(mode); - } - //--------------------------------------------------------------------------- - - @Override - public void onActionModeStarted(ActionMode mode) - { - if (!QtApplication.invokeDelegate(mode).invoked) - super.onActionModeStarted(mode); - } - public void super_onActionModeStarted(ActionMode mode) - { - super.onActionModeStarted(mode); - } - //--------------------------------------------------------------------------- - - @Override - public void onAttachFragment(Fragment fragment) - { - if (!QtApplication.invokeDelegate(fragment).invoked) - super.onAttachFragment(fragment); - } - public void super_onAttachFragment(Fragment fragment) - { - super.onAttachFragment(fragment); - } - //--------------------------------------------------------------------------- - - @Override - public View onCreateView(View parent, String name, Context context, AttributeSet attrs) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(parent, name, context, attrs); - if (res.invoked) - return (View)res.methodReturns; - else - return super.onCreateView(parent, name, context, attrs); - } - public View super_onCreateView(View parent, String name, Context context, - AttributeSet attrs) { - return super.onCreateView(parent, name, context, attrs); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onKeyShortcut(int keyCode, KeyEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.onKeyShortcut != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyShortcut, keyCode,event); - else - return super.onKeyShortcut(keyCode, event); - } - public boolean super_onKeyShortcut(int keyCode, KeyEvent event) - { - return super.onKeyShortcut(keyCode, event); - } - //--------------------------------------------------------------------------- - - @Override - public ActionMode onWindowStartingActionMode(Callback callback) - { - QtApplication.InvokeResult res = QtApplication.invokeDelegate(callback); - if (res.invoked) - return (ActionMode)res.methodReturns; - else - return super.onWindowStartingActionMode(callback); - } - public ActionMode super_onWindowStartingActionMode(Callback callback) - { - return super.onWindowStartingActionMode(callback); - } - //--------------------------------------------------------------------------- -//@ANDROID-11 - //////////////// Activity API 12 ///////////// - -////@ANDROID-12 -// @Override -// public boolean dispatchGenericMotionEvent(MotionEvent ev) -// { -// if (QtApplication.m_delegateObject != null && QtApplication.dispatchGenericMotionEvent != null) -// return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchGenericMotionEvent, ev); -// else -// return super.dispatchGenericMotionEvent(ev); -// } -// public boolean super_dispatchGenericMotionEvent(MotionEvent event) -// { -// return super.dispatchGenericMotionEvent(event); -// } -// //--------------------------------------------------------------------------- -// -// @Override -// public boolean onGenericMotionEvent(MotionEvent event) -// { -// if (QtApplication.m_delegateObject != null && QtApplication.onGenericMotionEvent != null) -// return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onGenericMotionEvent, event); -// else -// return super.onGenericMotionEvent(event); -// } -// public boolean super_onGenericMotionEvent(MotionEvent event) -// { -// return super.onGenericMotionEvent(event); -// } -// //--------------------------------------------------------------------------- -////@ANDROID-12 - -} diff --git a/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtApplication.java b/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtApplication.java deleted file mode 100644 index c78aeb7f..00000000 --- a/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtApplication.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - Copyright (c) 2012-2013, BogDan Vatra - Contact: http://www.qt.io/licensing/ - - Commercial License Usage - Licensees holding valid commercial Qt licenses may use this file in - accordance with the commercial license agreement provided with the - Software or, alternatively, in accordance with the terms contained in - a written agreement between you and The Qt Company. For licensing terms - and conditions see http://www.qt.io/terms-conditions. For further - information use the contact form at http://www.qt.io/contact-us. - - BSD License Usage - Alternatively, this file may be used under the BSD license as follows: - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package org.qtproject.qt5.android.bindings; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; - -import android.app.Application; - -public class QtApplication extends Application -{ - public final static String QtTAG = "Qt"; - public static Object m_delegateObject = null; - public static HashMap> m_delegateMethods= new HashMap>(); - public static Method dispatchKeyEvent = null; - public static Method dispatchPopulateAccessibilityEvent = null; - public static Method dispatchTouchEvent = null; - public static Method dispatchTrackballEvent = null; - public static Method onKeyDown = null; - public static Method onKeyMultiple = null; - public static Method onKeyUp = null; - public static Method onTouchEvent = null; - public static Method onTrackballEvent = null; - public static Method onActivityResult = null; - public static Method onCreate = null; - public static Method onKeyLongPress = null; - public static Method dispatchKeyShortcutEvent = null; - public static Method onKeyShortcut = null; - public static Method dispatchGenericMotionEvent = null; - public static Method onGenericMotionEvent = null; - - public static void setQtActivityDelegate(Object listener) - { - QtApplication.m_delegateObject = listener; - - ArrayList delegateMethods = new ArrayList(); - for (Method m : listener.getClass().getMethods()) { - if (m.getDeclaringClass().getName().startsWith("org.qtproject.qt5.android")) - delegateMethods.add(m); - } - - ArrayList applicationFields = new ArrayList(); - for (Field f : QtApplication.class.getFields()) { - if (f.getDeclaringClass().getName().equals(QtApplication.class.getName())) - applicationFields.add(f); - } - - for (Method delegateMethod : delegateMethods) { - try { - QtActivity.class.getDeclaredMethod(delegateMethod.getName(), delegateMethod.getParameterTypes()); - if (QtApplication.m_delegateMethods.containsKey(delegateMethod.getName())) { - QtApplication.m_delegateMethods.get(delegateMethod.getName()).add(delegateMethod); - } else { - ArrayList delegateSet = new ArrayList(); - delegateSet.add(delegateMethod); - QtApplication.m_delegateMethods.put(delegateMethod.getName(), delegateSet); - } - for (Field applicationField:applicationFields) { - if (applicationField.getName().equals(delegateMethod.getName())) { - try { - applicationField.set(null, delegateMethod); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } catch (Exception e) { - } - } - } - - @Override - public void onTerminate() { - if (m_delegateObject != null && m_delegateMethods.containsKey("onTerminate")) - invokeDelegateMethod(m_delegateMethods.get("onTerminate").get(0)); - super.onTerminate(); - } - - public static class InvokeResult - { - public boolean invoked = false; - public Object methodReturns = null; - } - - private static int stackDeep=-1; - public static InvokeResult invokeDelegate(Object... args) - { - InvokeResult result = new InvokeResult(); - if (m_delegateObject == null) - return result; - StackTraceElement[] elements = Thread.currentThread().getStackTrace(); - if (-1 == stackDeep) { - String activityClassName = QtActivity.class.getCanonicalName(); - for (int it=0;it + diff --git a/qt/i2pd_qt/docs/patch_openssl_so_libs.html b/qt/i2pd_qt/docs/patch_openssl_so_libs.html deleted file mode 100644 index bc886abc..00000000 --- a/qt/i2pd_qt/docs/patch_openssl_so_libs.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -

- OpenSSL под Android в Qt - -

Запись от Wyn размещена 18.01.2016 в 18:22
Метки android, openssl, qt

Мини-руководство по тому, как быстро скомпилировать OpenSSL для Android и связать его с проектом Qt.
-Для Linux.

-Вначале действия полностью идентичны "расово-верному" руководству по компилянию OpenSSL для Android:
-Качаем исходники openssl нужной версии с их сайта, качаем setenv-android.sh(все ссылки на закачку выше по ссылке).
-Ложим их в одну папку. Запускаем консоль, переходим в ней в эту самую папку.
-Далее:
BashВыделить код
1
-2
-3
-
$ rm -rf openssl-1.0.1g/   # удаляем исходники(вместо версии 1.0.1g - подставляем свою), если они уже были распакованы
-$ tar xzf openssl-1.0.1g.tar.gz    # распаковываем исходники в подпапку
-$ chmod a+x setenv-android.sh    # разрешаем setenv-android.sh исполняться
Редактируем setenv-android.sh, настраивая там _ANDROID_EABI, _ANDROID_ARCH, _ANDROID_API на нужные значения.
-Дальше возвращаемся в консоль:
BashВыделить код
1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-
$ export ANDROID_NDK_ROOT=путь_до_ANDROID_NDK # указываем путь до Android NDK для setenv-android.sh
-$ . ./setenv-android.sh # запускаем скрипт, чтобы он нам в окружение проставил необходимые далее переменные
-$ cd openssl-1.0.1g/
-$ perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org
-# конфигурируем
-$ ./config shared no-ssl2 no-ssl3 no-comp no-hw no-engine --openssldir=/usr/local/ssl/$ANDROID_API
-# собираем
-$ make depend
-$ make all
-# устанавливаем
-$ sudo -E make install CC=$ANDROID_TOOLCHAIN/arm-linux-androideabi-gcc RANLIB=$ANDROID_TOOLCHAIN/arm-linux-androideabi-ranlib
И тут начинается интересное. Андроид не принимает versioned shared object (это *.so.x и подобные). Казалось бы 2016 год, космические корабли уже давно бороздят просторы Большого театра, но вот те на.

-Однако, есть обходной приём - нужно заменить *.so.x.x.x на *_x_x_x.so. Простым переименованием файлов данную проблему здесь, разумеется, не решить. Нужно лезть внутрь и переименовывать soname и внутренние ссылки на другие versioned shared object. В интернете есть много способов по подобному переименованию. Большинство из них обещают райскую жизнь с rpl, забывая упомянуть, что утилита уже давно отпета и закопана на большинстве дистрибутивов. Или хитро-хитро редактируют makefile, что в итоге на место левой руки собирается правая нога. В целом множество путей из разряда "как потратить много времени на полную фигню".

-В итоге предлагаю решить данную проблему методом топора:
-Качаем hex-редактор, если ещё нет(в моём случае таковым оказался Okteta). Запускаем его из под рута(kdesu okteta), открываем в нём файлы openssldir/lib/libcrypto.so.1.0.0. Заменяем(ctrl+r) в нём символы ".so.1.0.0" на char "_1_0_0.so". Проделываем тоже самое с libssl.so.1.0.0. Всё, теперь осталось только переименовать сами файлы(в libcrypto_1_0_0.so и libssl_1_0_0.so) и поправить ссылки libssl.so и libcrypto.so, чтобы они вели на них.

-Чтобы подключить и использовать данную библиотеку в проекте нужно добавить в .pro:
BashВыделить код
1
-2
-3
-4
-5
-
android: {
-    INCLUDEPATH += /usr/local/ssl/android-21/include
-    LIBS += -L/usr/local/ssl/android-21/lib
-}
-LIBS += -lcrypto
А затем в настройках проекта, в Buld/Build Steps/Bulild Android Apk добавить libcrypto_1_0_0.so и libssl_1_0_0.so в список Additional Libraries.

-На этом всё. - -
-

Original: http://www.cyberforum.ru/blogs/748276/blog4086.html

- - diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 879efc95..e24a3963 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -7,23 +7,6 @@ TEMPLATE = app QMAKE_CXXFLAGS *= -std=c++11 -ggdb DEFINES += USE_UPNP -# change to your own path, where you will store all needed libraries with 'git clone' commands below. -MAIN_PATH = /path/to/libraries - -# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git -# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git -# git clone https://github.com/PurpleI2P/android-ifaddrs.git -BOOST_PATH = $$MAIN_PATH/Boost-for-Android-Prebuilt -OPENSSL_PATH = $$MAIN_PATH/OpenSSL-for-Android-Prebuilt -MINIUPNP_PATH = $$MAIN_PATH/MiniUPnP-for-Android-Prebuilt -IFADDRS_PATH = $$MAIN_PATH/android-ifaddrs - -# Steps in Android SDK manager: -# 1) Check Extras/Google Support Library https://developer.android.com/topic/libraries/support-library/setup.html -# 2) Check API 11 -# Finally, click Install. - SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd/api.cpp \ ../../libi2pd/Base.cpp \ @@ -218,63 +201,6 @@ macx { LIBS += $$UPNPROOT/lib/libminiupnpc.a } -android { - message("Using Android settings") - DEFINES += ANDROID=1 - DEFINES += __ANDROID__ - - CONFIG += mobility - - MOBILITY = - - INCLUDEPATH += $$BOOST_PATH/boost_1_53_0/include \ - $$OPENSSL_PATH/openssl-1.0.2/include \ - $$MINIUPNP_PATH/miniupnp-2.0/include \ - $$IFADDRS_PATH - DISTFILES += android/AndroidManifest.xml - - ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android - - SOURCES += $$IFADDRS_PATH/ifaddrs.c - HEADERS += $$IFADDRS_PATH/ifaddrs.h - - equals(ANDROID_TARGET_ARCH, armeabi-v7a){ - DEFINES += ANDROID_ARM7A - # http://stackoverflow.com/a/30235934/529442 - LIBS += -L$$BOOST_PATH/boost_1_53_0/armeabi-v7a/lib \ - -lboost_system-gcc-mt-1_53 -lboost_date_time-gcc-mt-1_53 \ - -lboost_filesystem-gcc-mt-1_53 -lboost_program_options-gcc-mt-1_53 \ - -L$$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/ -lcrypto -lssl \ - -L$$MINIUPNP_PATH/miniupnp-2.0/armeabi-v7a/lib/ -lminiupnpc - - PRE_TARGETDEPS += $$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libcrypto.a \ - $$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libssl.a - DEPENDPATH += $$OPENSSL_PATH/openssl-1.0.2/include - - ANDROID_EXTRA_LIBS += $$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libcrypto_1_0_0.so \ - $$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libssl_1_0_0.so \ - $$MINIUPNP_PATH/miniupnp-2.0/armeabi-v7a/lib/libminiupnpc.so - } - - equals(ANDROID_TARGET_ARCH, x86){ - # http://stackoverflow.com/a/30235934/529442 - LIBS += -L$$BOOST_PATH/boost_1_53_0/x86/lib \ - -lboost_system-gcc-mt-1_53 -lboost_date_time-gcc-mt-1_53 \ - -lboost_filesystem-gcc-mt-1_53 -lboost_program_options-gcc-mt-1_53 \ - -L$$OPENSSL_PATH/openssl-1.0.2/x86/lib/ -lcrypto -lssl \ - -L$$MINIUPNP_PATH/miniupnp-2.0/x86/lib/ -lminiupnpc - - PRE_TARGETDEPS += $$OPENSSL_PATH/openssl-1.0.2/x86/lib/libcrypto.a \ - $$OPENSSL_PATH/openssl-1.0.2/x86/lib/libssl.a - - DEPENDPATH += $$OPENSSL_PATH/openssl-1.0.2/include - - ANDROID_EXTRA_LIBS += $$OPENSSL_PATH/openssl-1.0.2/x86/lib/libcrypto_1_0_0.so \ - $$OPENSSL_PATH/openssl-1.0.2/x86/lib/libssl_1_0_0.so \ - $$MINIUPNP_PATH/miniupnp-2.0/x86/lib/libminiupnpc.so - } -} - linux:!android { message("Using Linux settings") LIBS += -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread -lminiupnpc diff --git a/tests/test-aeadchacha20poly1305.cpp b/tests/test-aeadchacha20poly1305.cpp index d10ab2fc..de9f1db2 100644 --- a/tests/test-aeadchacha20poly1305.cpp +++ b/tests/test-aeadchacha20poly1305.cpp @@ -53,7 +53,7 @@ int main () assert (memcmp (buf1, text, 114) == 0); // test encryption of multiple buffers memcpy (buf, text, 114); - std::vector > bufs{ std::make_pair (buf, 50), std::make_pair (buf + 50, 50), std::make_pair (buf + 100, 14) }; + std::vector > bufs{ std::make_pair (buf, 20), std::make_pair (buf + 20, 10), std::make_pair (buf + 30, 70), std::make_pair (buf + 100, 14) }; i2p::crypto::AEADChaCha20Poly1305Encrypt (bufs, key, nonce, buf + 114); i2p::crypto::AEADChaCha20Poly1305 (buf, 114, nullptr, 0, key, nonce, buf1, 114, false); assert (memcmp (buf1, text, 114) == 0);