From 626ed720a6b3483746f1b9321617783d409a821e Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 22 Jan 2018 12:59:34 -0500 Subject: [PATCH 1/7] Revert " Fixes for #1024 , #1018 #1064 " --- android/.gitignore | 6 +- android/build.gradle | 54 ++++-------- android/gradle.properties | 1 - android/jni/DaemonAndroid.cpp | 5 +- android/jni/DaemonAndroid.h | 2 +- android/jni/i2pd_android.cpp | 20 +---- android/jni/org_purplei2p_i2pd_I2PD_JNI.h | 2 +- .../org/purplei2p/i2pd/DaemonSingleton.java | 39 ++++----- .../src/org/purplei2p/i2pd/Decompress.java | 83 ------------------- .../org/purplei2p/i2pd/ForegroundService.java | 17 +--- android/src/org/purplei2p/i2pd/I2PD.java | 26 ++---- android/src/org/purplei2p/i2pd/I2PD_JNI.java | 6 +- 12 files changed, 55 insertions(+), 206 deletions(-) delete mode 100644 android/gradle.properties delete mode 100644 android/src/org/purplei2p/i2pd/Decompress.java diff --git a/android/.gitignore b/android/.gitignore index 7e166aa6..d9fa5a57 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,8 +5,4 @@ ant.properties local.properties build.sh bin -log* -.gradle* -build -assets -gradle-app.setting +log* \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 46d0d057..a88403fd 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -11,24 +11,23 @@ buildscript { apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.0" - defaultConfig { - applicationId "org.purplei2p.i2pd" - targetSdkVersion 25 - minSdkVersion 14 - versionCode 1 - versionName "2.17.2e" - } + compileSdkVersion 25 + buildToolsVersion "25.0.2" + defaultConfig { + applicationId "org.purplei2p.i2pd" + targetSdkVersion 25 + minSdkVersion 14 + versionCode 1 + versionName "2.17.1" + } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] - res.srcDirs = ['res'] - jniLibs.srcDirs = ['libs'] - assets.srcDirs = ['assets'] + res.srcDirs = ['res'] + jniLibs.srcDirs = ['libs'] + } } - } signingConfigs { orignal { storeFile file("i2pdapk.jks") @@ -38,30 +37,11 @@ android { } } buildTypes { - release { - minifyEnabled false - signingConfig signingConfigs.orignal - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' - } + release { + minifyEnabled false + signingConfig signingConfigs.orignal + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' + } } } -tasks.withType(JavaCompile) { - options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation' - options.deprecation = true -} - -task zipCerts(type:Zip) { - from (files('../contrib/')) - include 'certificates/**/*.crt' - destinationDir file('assets') - archiveName 'certificates.zip' - entryCompression ZipEntryCompression.STORED -} -preBuild.dependsOn zipCerts - -task clean(type: Delete,overwrite: true) { - delete 'build' - delete 'assets' -} - diff --git a/android/gradle.properties b/android/gradle.properties deleted file mode 100644 index d8894a70..00000000 --- a/android/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.jvmargs=-Xmx2048M -XX:MaxPermSize=256M -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp index 9865ac79..75584740 100644 --- a/android/jni/DaemonAndroid.cpp +++ b/android/jni/DaemonAndroid.cpp @@ -126,11 +126,12 @@ namespace android } */ static DaemonAndroidImpl daemon; + static char* argv[1]={strdup("tmp")}; /** * returns error details if failed * returns "ok" if daemon initialized and started okay */ - std::string start(int argc, char* argv[]) + std::string start(/*int argc, char* argv[]*/) { try { @@ -138,7 +139,7 @@ namespace android { //Log.d(TAG"Initialising the daemon..."); - bool daemonInitSuccess = daemon.init(argc,argv); + bool daemonInitSuccess = daemon.init(1,argv); if(!daemonInitSuccess) { //QMessageBox::critical(0, "Error", "Daemon init failed"); diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h index 81031936..9cc8219b 100644 --- a/android/jni/DaemonAndroid.h +++ b/android/jni/DaemonAndroid.h @@ -37,7 +37,7 @@ namespace android * returns "ok" if daemon init failed * returns errinfo if daemon initialized and started okay */ - std::string start(int argc, char* argv[]); + std::string start(); // stops the daemon void stop(); diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index 1079a252..8791c90b 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -44,24 +44,8 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith } JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv * env, jclass clazz, jobjectArray args) { - int argc = env->GetArrayLength(args); - typedef char *pchar; - pchar* argv = new pchar[argc]; - for (int i = 0; i < argc; i++) { - jstring arg = (jstring) env->GetObjectArrayElement(args, i); - const char *argStr = env->GetStringUTFChars(arg, 0); - size_t len = strlen(argStr); - argv[i] = new char[len + 1]; - strcpy(argv[i], argStr); - env->ReleaseStringUTFChars(arg, argStr); - } - const char* result = i2p::android::start(argc,argv).c_str(); - for (int i = 0; i < argc; i++) { - delete [] argv[i]; - } - delete [] argv; - return env->NewStringUTF(result); + (JNIEnv * env, jclass clazz) { + return env->NewStringUTF(i2p::android::start().c_str()); } JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon diff --git a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h index 484b3230..04923d22 100644 --- a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h +++ b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h @@ -16,7 +16,7 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith (JNIEnv *, jclass); JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv *, jclass, jobjectArray args); + (JNIEnv *, jclass); JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon (JNIEnv *, jclass); diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index beff0c39..65afd0f5 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -14,10 +14,10 @@ public class DaemonSingleton { public static DaemonSingleton getInstance() { return instance; } - + public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); } public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); } - + public synchronized void stopAcceptingTunnels() { if(isStartedOkay()){ state=State.gracefulShutdownInProgress; @@ -25,21 +25,20 @@ public class DaemonSingleton { I2PD_JNI.stopAcceptingTunnels(); } } - + public void onNetworkStateChange(boolean isConnected) { I2PD_JNI.onNetworkStateChanged(isConnected); } - + private boolean startedOkay; public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress}; - + private State state = State.uninitialized; - + public State getState() { return state; } - - public synchronized void start(final String confDir, final String dataDir) { + public synchronized void start() { if(state != State.uninitialized)return; state = State.starting; fireStateUpdate(); @@ -63,15 +62,7 @@ public class DaemonSingleton { } try { synchronized (DaemonSingleton.this) { - - String args[] = new String[] { - "i2pd", "--service", "--daemon", - "--datadir=" + dataDir, - "--conf=" + confDir + "/i2pd.conf", - "--tunconf=" + confDir + "/tunnels.conf" - }; - - daemonStartResult = I2PD_JNI.startDaemon(args); + daemonStartResult = I2PD_JNI.startDaemon(); if("ok".equals(daemonStartResult)){ state=State.startedOkay; setStartedOkay(true); @@ -85,9 +76,9 @@ public class DaemonSingleton { fireStateUpdate(); } return; - } + } } - + }, "i2pdDaemonStart").start(); } private Throwable lastThrowable; @@ -96,10 +87,10 @@ public class DaemonSingleton { private synchronized void fireStateUpdate() { Log.i(TAG, "daemon state change: "+state); for(StateUpdateListener listener : stateUpdateListeners) { - try { - listener.daemonStateUpdate(); - } catch (Throwable tr) { - Log.e(TAG, "exception in listener ignored", tr); + try { + listener.daemonStateUpdate(); + } catch (Throwable tr) { + Log.e(TAG, "exception in listener ignored", tr); } } } @@ -111,7 +102,7 @@ public class DaemonSingleton { public String getDaemonStartResult() { return daemonStartResult; } - + private final Object startedOkayLock = new Object(); public boolean isStartedOkay() { diff --git a/android/src/org/purplei2p/i2pd/Decompress.java b/android/src/org/purplei2p/i2pd/Decompress.java deleted file mode 100644 index 917abc7c..00000000 --- a/android/src/org/purplei2p/i2pd/Decompress.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.purplei2p.i2pd; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import android.content.Context; -import android.util.Log; - -public class Decompress { - private static final int BUFFER_SIZE = 1024 * 10; - private static final String TAG = "Decompress"; - - public static void unzipFromAssets(Context context, String zipFile, String destination) { - try { - if (destination == null || destination.length() == 0) - destination = context.getFilesDir().getAbsolutePath(); - InputStream stream = context.getAssets().open(zipFile); - unzip(stream, destination); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static void unzip(String zipFile, String location) { - try { - FileInputStream fin = new FileInputStream(zipFile); - unzip(fin, location); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - - } - - public static void unzip(InputStream stream, String destination) { - dirChecker(destination, ""); - byte[] buffer = new byte[BUFFER_SIZE]; - try { - ZipInputStream zin = new ZipInputStream(stream); - ZipEntry ze = null; - - while ((ze = zin.getNextEntry()) != null) { - Log.v(TAG, "Unzipping " + ze.getName()); - - if (ze.isDirectory()) { - dirChecker(destination, ze.getName()); - } else { - File f = new File(destination + ze.getName()); - if (!f.exists()) { - FileOutputStream fout = new FileOutputStream(destination + ze.getName()); - int count; - while ((count = zin.read(buffer)) != -1) { - fout.write(buffer, 0, count); - } - zin.closeEntry(); - fout.close(); - } - } - - } - zin.close(); - } catch (Exception e) { - Log.e(TAG, "unzip", e); - } - - } - - private static void dirChecker(String destination, String dir) { - File f = new File(destination + dir); - - if (!f.isDirectory()) { - boolean success = f.mkdirs(); - if (!success) { - Log.w(TAG, "Failed to create folder " + f.getName()); - } - } - } -} diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index 645d0dca..bfd650c8 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -5,8 +5,6 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; -import android.content.Context; -import android.os.Environment; import android.os.Binder; import android.os.IBinder; import android.util.Log; @@ -30,20 +28,13 @@ public class ForegroundService extends Service { } } - private String dataDir; - private String confDir; - @Override public void onCreate() { notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - dataDir = this.getDir("data", Context.MODE_PRIVATE).toString(); - confDir = Environment.getExternalStoragePublicDirectory("i2pd").toString(); // Display a notification about us starting. We put an icon in the status bar. showNotification(); - - Log.i("ForegroundService", "About to start daemon with dataDir: " + dataDir + ", confDir: " + confDir); - daemon.start(confDir, dataDir); + daemon.start(); // Tell the user we started. Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); } @@ -51,7 +42,7 @@ public class ForegroundService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("ForegroundService", "Received start id " + startId + ": " + intent); - daemon.start(confDir, dataDir); + daemon.start(); return START_STICKY; } @@ -59,7 +50,7 @@ public class ForegroundService extends Service { public void onDestroy() { // Cancel the persistent notification. notificationManager.cancel(NOTIFICATION); - + stopForeground(true); // Tell the user we stopped. @@ -100,7 +91,7 @@ public class ForegroundService extends Service { //mNM.notify(NOTIFICATION, notification); startForeground(NOTIFICATION, notification); } - + private final DaemonSingleton daemon = DaemonSingleton.getInstance(); } diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PD.java index d66a0174..a2494b2b 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PD.java @@ -2,13 +2,6 @@ package org.purplei2p.i2pd; import java.io.PrintWriter; import java.io.StringWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - import java.util.Timer; import java.util.TimerTask; @@ -31,12 +24,12 @@ public class I2PD extends Activity { private static final String TAG = "i2pd"; private TextView textView; - + private final DaemonSingleton daemon = DaemonSingleton.getInstance(); private DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() { - + @Override public void daemonStateUpdate() { runOnUiThread(new Runnable(){ @@ -60,14 +53,11 @@ public class I2PD extends Activity { }); } }; - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - //install certs every time - Decompress.unzipFromAssets(this, "certificates.zip", this.getDir("data", Context.MODE_PRIVATE).toString() + "/" ); - textView = new TextView(this); setContentView(textView); DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); @@ -133,7 +123,7 @@ public class I2PD extends Activity { } }; - + private boolean mIsBound; private void doBindService() { @@ -157,7 +147,7 @@ public class I2PD extends Activity { @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.options_main, menu); + getMenuInflater().inflate(R.menu.options_main, menu); return true; } @@ -226,9 +216,9 @@ public class I2PD extends Activity { @Override public void run() { - quit(); + quit(); } - + }, 10*60*1000/*milliseconds*/); }else{ quit(); @@ -237,7 +227,7 @@ public class I2PD extends Activity { Log.e(TAG,"",tr); } } - + },"gracQuitInit").start(); } diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java index bfdf8967..f965d471 100644 --- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java +++ b/android/src/org/purplei2p/i2pd/I2PD_JNI.java @@ -6,12 +6,12 @@ public class I2PD_JNI { * returns error info if failed * returns "ok" if daemon initialized and started okay */ - public static native String startDaemon(String args[]); + public static native String startDaemon(); //should only be called after startDaemon() success public static native void stopDaemon(); - + public static native void stopAcceptingTunnels(); - + public static native void onNetworkStateChanged(boolean isConnected); public static void loadLibraries() { From c730839989d3d00d70c649226ecf92530985fba0 Mon Sep 17 00:00:00 2001 From: Veggie Monster Date: Mon, 22 Jan 2018 20:47:31 -0500 Subject: [PATCH 2/7] the change allows when an TCPIPAcceptor is constructed by setting port = 0, the random port chosen by asio can be retrieved using TCPIPAcceptor::GetLocalEndpoint().port() --- libi2pd_client/I2PService.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 6fd5d763..21e1fdfa 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -280,6 +280,8 @@ namespace client void TCPIPAcceptor::Start () { m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint)); + //update the local end point in case port has been set zero and got updated now + m_LocalEndpoint = m_Acceptor->local_endpoint(); m_Acceptor->listen (); Accept (); } From c7db9010ad36cbe11d503de186a23bf746b3e3af Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 23 Jan 2018 11:01:50 -0500 Subject: [PATCH 3/7] fixed #1047. Return EXIT_FAILURE --- daemon/i2pd.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/daemon/i2pd.cpp b/daemon/i2pd.cpp index 589274f5..8718ad0c 100644 --- a/daemon/i2pd.cpp +++ b/daemon/i2pd.cpp @@ -22,6 +22,8 @@ int main( int argc, char* argv[] ) { if (Daemon.start()) Daemon.run (); + else + return EXIT_FAILURE; Daemon.stop(); } return EXIT_SUCCESS; From 85fa728d41b8449bad0d6f288cd5693a60bc1917 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 23 Jan 2018 14:40:05 -0500 Subject: [PATCH 4/7] change shared local destination upon reload --- libi2pd_client/ClientContext.cpp | 20 +++++++++++++------- libi2pd_client/ClientContext.h | 2 ++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 41b8615a..d8aa10d8 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -36,13 +36,7 @@ namespace client void ClientContext::Start () { if (!m_SharedLocalDestination) - { - m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA - m_SharedLocalDestination->Acquire (); - m_Destinations[m_SharedLocalDestination->GetIdentity ()->GetIdentHash ()] = m_SharedLocalDestination; - m_SharedLocalDestination->Start (); - } - + CreateNewSharedLocalDestination (); m_AddressBook.Start (); @@ -267,6 +261,10 @@ namespace client // delete not updated tunnels (not in config anymore) VisitTunnels ([](I2PService * s)->bool { return s->isUpdated; }); + // change shared local destination + m_SharedLocalDestination->Release (); + CreateNewSharedLocalDestination (); + // delete unused destinations std::unique_lock l(m_DestinationsMutex); for (auto it = m_Destinations.begin (); it != m_Destinations.end ();) @@ -407,6 +405,14 @@ namespace client return localDestination; } + void ClientContext::CreateNewSharedLocalDestination () + { + m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA + m_SharedLocalDestination->Acquire (); + m_Destinations[m_SharedLocalDestination->GetIdentity ()->GetIdentHash ()] = m_SharedLocalDestination; + m_SharedLocalDestination->Start (); + } + std::shared_ptr ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const { auto it = m_Destinations.find (destination); diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 8f7143bb..2d5d140f 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -99,6 +99,8 @@ namespace client template void VisitTunnels (Visitor v); // Visitor: (I2PService *) -> bool, true means retain + void CreateNewSharedLocalDestination (); + private: std::mutex m_DestinationsMutex; From 162bd592f8d4816e51d5a9700f588d27c07d778f Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 23 Jan 2018 15:13:43 -0500 Subject: [PATCH 5/7] recreate http and socks proxy upon reload --- libi2pd_client/ClientContext.cpp | 168 ++++++++++++++++++------------- libi2pd_client/ClientContext.h | 2 + 2 files changed, 101 insertions(+), 69 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index d8aa10d8..fb8fff97 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -35,81 +35,18 @@ namespace client void ClientContext::Start () { + // shared local destination if (!m_SharedLocalDestination) CreateNewSharedLocalDestination (); + // addressbook m_AddressBook.Start (); - std::shared_ptr localDestination; - bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); - if (httproxy) - { - std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); - std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); - uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); - i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); - std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); - LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); - if (httpProxyKeys.length () > 0) - { - i2p::data::PrivateKeys keys; - if(LoadPrivateKeys (keys, httpProxyKeys, sigType)) - { - std::map params; - ReadI2CPOptionsFromConfig ("httpproxy.", params); - localDestination = CreateNewLocalDestination (keys, false, ¶ms); - localDestination->Acquire (); - } - else - LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); - } - try - { - m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination); - m_HttpProxy->Start(); - } - catch (std::exception& e) - { - LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); - } - } + // HTTP proxy + ReadHttpProxy (); - localDestination = nullptr; - bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy); - if (socksproxy) - { - std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys); - std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr); - uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort); - bool socksOutProxy; i2p::config::GetOption("socksproxy.outproxy.enabled", socksOutProxy); - std::string socksOutProxyAddr; i2p::config::GetOption("socksproxy.outproxy", socksOutProxyAddr); - uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort); - i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType); - LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort); - if (socksProxyKeys.length () > 0) - { - i2p::data::PrivateKeys keys; - if (LoadPrivateKeys (keys, socksProxyKeys, sigType)) - { - std::map params; - ReadI2CPOptionsFromConfig ("socksproxy.", params); - localDestination = CreateNewLocalDestination (keys, false, ¶ms); - localDestination->Acquire (); - } - else - LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key"); - } - try - { - m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort, - socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination); - m_SocksProxy->Start(); - } - catch (std::exception& e) - { - LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what()); - } - } + // SOCKS proxy + ReadSocksProxy (); // I2P tunnels ReadTunnels (); @@ -265,6 +202,22 @@ namespace client m_SharedLocalDestination->Release (); CreateNewSharedLocalDestination (); + // recreate HTTP proxy + if (m_HttpProxy) + { + m_HttpProxy->Stop (); + m_HttpProxy = nullptr; + } + ReadHttpProxy (); + + // recreate SOCKS proxy + if (m_SocksProxy) + { + m_SocksProxy->Stop (); + m_SocksProxy = nullptr; + } + ReadSocksProxy (); + // delete unused destinations std::unique_lock l(m_DestinationsMutex); for (auto it = m_Destinations.begin (); it != m_Destinations.end ();) @@ -722,6 +675,83 @@ namespace client LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created"); } + void ClientContext::ReadHttpProxy () + { + std::shared_ptr localDestination; + bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); + if (httproxy) + { + std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); + std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); + uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); + i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); + std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); + LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); + if (httpProxyKeys.length () > 0) + { + i2p::data::PrivateKeys keys; + if(LoadPrivateKeys (keys, httpProxyKeys, sigType)) + { + std::map params; + ReadI2CPOptionsFromConfig ("httpproxy.", params); + localDestination = CreateNewLocalDestination (keys, false, ¶ms); + localDestination->Acquire (); + } + else + LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); + } + try + { + m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination); + m_HttpProxy->Start(); + } + catch (std::exception& e) + { + LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); + } + } + } + + void ClientContext::ReadSocksProxy () + { + std::shared_ptr localDestination; + bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy); + if (socksproxy) + { + std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys); + std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr); + uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort); + bool socksOutProxy; i2p::config::GetOption("socksproxy.outproxy.enabled", socksOutProxy); + std::string socksOutProxyAddr; i2p::config::GetOption("socksproxy.outproxy", socksOutProxyAddr); + uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort); + i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType); + LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort); + if (socksProxyKeys.length () > 0) + { + i2p::data::PrivateKeys keys; + if (LoadPrivateKeys (keys, socksProxyKeys, sigType)) + { + std::map params; + ReadI2CPOptionsFromConfig ("socksproxy.", params); + localDestination = CreateNewLocalDestination (keys, false, ¶ms); + localDestination->Acquire (); + } + else + LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key"); + } + try + { + m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort, + socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination); + m_SocksProxy->Start(); + } + catch (std::exception& e) + { + LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what()); + } + } + } + void ClientContext::ScheduleCleanupUDP() { if (m_CleanupUDPTimer) diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 2d5d140f..922d7acc 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -87,6 +87,8 @@ namespace client private: void ReadTunnels (); + void ReadHttpProxy (); + void ReadSocksProxy (); template std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const; template From ddd25f09459e34b77898206aa09ad88320141c24 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 23 Jan 2018 15:50:28 -0500 Subject: [PATCH 6/7] limit number of retries for subscriptions --- libi2pd_client/AddressBook.cpp | 8 ++++++-- libi2pd_client/AddressBook.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 4dfeeb53..4b563ac0 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -207,7 +207,7 @@ namespace client //--------------------------------------------------------------------- AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false), - m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr) + m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr) { } @@ -486,9 +486,13 @@ namespace client void AddressBook::DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) { m_IsDownloading = false; - int nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT; + m_NumRetries++; + int nextUpdateTimeout = m_NumRetries*CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT; + if (m_NumRetries > CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES || nextUpdateTimeout > CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT) + nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT; if (success) { + m_NumRetries = 0; if (m_DefaultSubscription) m_DefaultSubscription = nullptr; if (m_IsLoaded) nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT; diff --git a/libi2pd_client/AddressBook.h b/libi2pd_client/AddressBook.h index 3feb2ece..2d4475cb 100644 --- a/libi2pd_client/AddressBook.h +++ b/libi2pd_client/AddressBook.h @@ -22,6 +22,7 @@ namespace client const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes + const int CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; @@ -97,6 +98,7 @@ namespace client std::map m_Lookups; // nonce -> address AddressBookStorage * m_Storage; volatile bool m_IsLoaded, m_IsDownloading; + int m_NumRetries; std::vector > m_Subscriptions; std::shared_ptr m_DefaultSubscription; // in case if we don't know any addresses yet boost::asio::deadline_timer * m_SubscriptionsUpdateTimer; From 0bb0adbf3eb3fa58fa2b1e9d7713e9c4a1d0fd29 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 24 Jan 2018 15:34:32 +0300 Subject: [PATCH 7/7] fix addressbook fetch timeout --- libi2pd_client/AddressBook.cpp | 4 ++-- libi2pd_client/AddressBook.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 4b563ac0..f29ecee3 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -696,7 +696,7 @@ namespace client std::unique_lock l(newDataReceivedMutex); i2p::client::context.GetSharedLocalDestination ()->RequestDestination (m_Ident, [&newDataReceived, &leaseSet, &newDataReceivedMutex](std::shared_ptr ls) - { + { leaseSet = ls; std::unique_lock l1(newDataReceivedMutex); newDataReceived.notify_all (); @@ -753,7 +753,7 @@ namespace client end = true; newDataReceived.notify_all (); }, - 30); // wait for 30 seconds + SUBSCRIPTION_REQUEST_TIMEOUT); std::unique_lock l(newDataReceivedMutex); if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout) { diff --git a/libi2pd_client/AddressBook.h b/libi2pd_client/AddressBook.h index 2d4475cb..19257eca 100644 --- a/libi2pd_client/AddressBook.h +++ b/libi2pd_client/AddressBook.h @@ -23,7 +23,7 @@ namespace client const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes const int CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout - const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second + const int SUBSCRIPTION_REQUEST_TIMEOUT = 120; //in second const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54;