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) {
 
+	private State state = State.uninitialized;
+
+	public State getState() { return state; }
+
+	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() {
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;
diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp
index 4dfeeb53..f29ecee3 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;
@@ -692,7 +696,7 @@ namespace client
 			std::unique_lock<std::mutex> l(newDataReceivedMutex);
 			i2p::client::context.GetSharedLocalDestination ()->RequestDestination (m_Ident,
 				[&newDataReceived, &leaseSet, &newDataReceivedMutex](std::shared_ptr<i2p::data::LeaseSet> ls)
-			    {
+				{
 					leaseSet = ls;
 					std::unique_lock<std::mutex> l1(newDataReceivedMutex);
 					newDataReceived.notify_all ();
@@ -749,7 +753,7 @@ namespace client
 						end = true;
 					newDataReceived.notify_all ();
 				},
-				30); // wait for 30 seconds
+				SUBSCRIPTION_REQUEST_TIMEOUT);
 			std::unique_lock<std::mutex> 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 3feb2ece..19257eca 100644
--- a/libi2pd_client/AddressBook.h
+++ b/libi2pd_client/AddressBook.h
@@ -22,7 +22,8 @@ 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 SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second
+	const int CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout
+	const int SUBSCRIPTION_REQUEST_TIMEOUT = 120; //in second
 
 	const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53;
 	const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54;
@@ -97,6 +98,7 @@ namespace client
 			std::map<uint32_t, std::string> m_Lookups; // nonce -> address
 			AddressBookStorage * m_Storage;
 			volatile bool m_IsLoaded, m_IsDownloading;
+			int m_NumRetries;
 			std::vector<std::shared_ptr<AddressBookSubscription> > m_Subscriptions;
 			std::shared_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet
 			boost::asio::deadline_timer * m_SubscriptionsUpdateTimer;
diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp
index 41b8615a..fb8fff97 100644
--- a/libi2pd_client/ClientContext.cpp
+++ b/libi2pd_client/ClientContext.cpp
@@ -35,87 +35,18 @@ namespace client
 
 	void ClientContext::Start ()
 	{
+		// shared local destination
 		if (!m_SharedLocalDestination)
-		{
-			m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA
-			m_SharedLocalDestination->Acquire ();
-			m_Destinations[m_SharedLocalDestination->GetIdentity ()->GetIdentHash ()] = m_SharedLocalDestination;
-			m_SharedLocalDestination->Start ();
-		}
-
+			CreateNewSharedLocalDestination ();
 
+		// addressbook	
 		m_AddressBook.Start ();
 
-		std::shared_ptr<ClientDestination> 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<std::string, std::string> params;
-					ReadI2CPOptionsFromConfig ("httpproxy.", params);
-					localDestination = CreateNewLocalDestination (keys, false, &params);
-					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<std::string, std::string> params;
-					ReadI2CPOptionsFromConfig ("socksproxy.", params);
-					localDestination = CreateNewLocalDestination (keys, false, &params);
-					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 ();
@@ -267,6 +198,26 @@ 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 ();
+
+		// 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<std::mutex> l(m_DestinationsMutex);
 		for (auto it = m_Destinations.begin (); it != m_Destinations.end ();)
@@ -407,6 +358,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<ClientDestination> ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const
 	{
 		auto it = m_Destinations.find (destination);
@@ -716,6 +675,83 @@ namespace client
 		LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created");
 	}
 
+	void ClientContext::ReadHttpProxy ()
+	{
+		std::shared_ptr<ClientDestination> 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<std::string, std::string> params;
+					ReadI2CPOptionsFromConfig ("httpproxy.", params);
+					localDestination = CreateNewLocalDestination (keys, false, &params);
+					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<ClientDestination> 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<std::string, std::string> params;
+					ReadI2CPOptionsFromConfig ("socksproxy.", params);
+					localDestination = CreateNewLocalDestination (keys, false, &params);
+					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 8f7143bb..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<typename Section, typename Type>
 			std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const;
 			template<typename Section>
@@ -99,6 +101,8 @@ namespace client
 			template<typename Visitor>
 			void VisitTunnels (Visitor v); // Visitor: (I2PService *) -> bool, true means retain
 
+			void CreateNewSharedLocalDestination (); 
+
 		private:
 
 			std::mutex m_DestinationsMutex;
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 ();
 	}