From 7b00d828b2b26862920542f7dd428793869931ce Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 1 Jan 2018 08:28:42 -0500 Subject: [PATCH 001/134] fix lambda capture, don't capture copy --- libi2pd/Streaming.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 93cf2a9f..6c933752 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -334,7 +334,7 @@ namespace stream void Stream::AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout) { auto s = shared_from_this(); - m_Service.post ([=](void) + m_Service.post ([s, buffer, handler, timeout](void) { if (!s->m_ReceiveQueue.empty () || s->m_Status == eStreamStatusReset) s->HandleReceiveTimer (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), buffer, handler, 0); From 938d5d901ace83d785cd546d74c068aa6a3f002b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 2 Jan 2018 11:34:58 -0500 Subject: [PATCH 002/134] implement i2cp session reconfigure --- libi2pd/Destination.cpp | 40 ++++++++++++++++++++++++++++++ libi2pd/Destination.h | 4 +++ libi2pd/TunnelPool.cpp | 12 +++++++++ libi2pd/TunnelPool.h | 5 ++++ libi2pd_client/I2CP.cpp | 55 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 114 insertions(+), 2 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index cb42e480..160b95e6 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -169,6 +169,46 @@ namespace client return false; } + bool LeaseSetDestination::Reconfigure(std::map params) + { + + auto itr = params.find("i2cp.dontPublishLeaseSet"); + if (itr != params.end()) + { + m_IsPublic = itr->second != "true"; + } + + int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency; + std::map intOpts = { + {I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen}, + {I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen}, + {I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, inQuant}, + {I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, outQuant}, + {I2CP_PARAM_TAGS_TO_SEND, numTags}, + {I2CP_PARAM_MIN_TUNNEL_LATENCY, minLatency}, + {I2CP_PARAM_MAX_TUNNEL_LATENCY, maxLatency} + }; + + auto pool = GetTunnelPool(); + inLen = pool->GetNumInboundHops(); + outLen = pool->GetNumOutboundHops(); + inQuant = pool->GetNumInboundTunnels(); + outQuant = pool->GetNumOutboundTunnels(); + minLatency = 0; + maxLatency = 0; + + for (auto opt : intOpts) + { + itr = params.find(opt.first); + if(itr != params.end()) + { + opt.second = std::stoi(itr->second); + } + } + pool->RequireLatency(minLatency, maxLatency); + return pool->Reconfigure(inLen, outLen, inQuant, outQuant); + } + std::shared_ptr LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident) { std::shared_ptr remoteLS; diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 17daecb5..f93577e6 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -96,6 +96,10 @@ namespace client virtual bool Start (); virtual bool Stop (); + + /** i2cp reconfigure */ + virtual bool Reconfigure(std::map i2cpOpts); + bool IsRunning () const { return m_IsRunning; }; boost::asio::io_service& GetService () { return m_Service; }; std::shared_ptr GetTunnelPool () { return m_Pool; }; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index a3592708..dd163993 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -69,6 +69,18 @@ namespace tunnel m_Tests.clear (); } + bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant) { + if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0) + { + m_NumInboundHops = inHops; + m_NumOutboundHops = outHops; + m_NumInboundTunnels = inQuant; + m_NumOutboundTunnels = outQuant; + return true; + } + return false; + } + void TunnelPool::TunnelCreated (std::shared_ptr createdTunnel) { if (!m_IsActive) return; diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 07c3024e..fc46930c 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -78,7 +78,12 @@ namespace tunnel int GetNumInboundTunnels () const { return m_NumInboundTunnels; }; int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; }; + int GetNumInboundHops() const { return m_NumInboundHops; }; + int GetNumOutboundHops() const { return m_NumOutboundHops; }; + /** i2cp reconfigure */ + bool Reconfigure(int inboundHops, int outboundHops, int inboundQuant, int outboundQuant); + void SetCustomPeerSelector(ITunnelPeerSelector * selector); void UnsetCustomPeerSelector(); bool HasCustomPeerSelector(); diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index f98b1af3..293f4067 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -416,8 +416,59 @@ namespace client void I2CPSession::ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len) { - // TODO: implement actual reconfiguration - SendSessionStatusMessage (2); // updated + uint8_t status = 3; // rejected + if(len > sizeof(uint16_t)) + { + uint16_t sessionID = bufbe16toh(buf); + if(sessionID == m_SessionID) + { + buf += sizeof(uint16_t); + const uint8_t * body = buf; + i2p::data::IdentityEx ident; + if(ident.FromBuffer(buf, len - sizeof(uint16_t))) + { + if (ident == *m_Destination->GetIdentity()) + { + size_t identsz = ident.GetFullLen(); + buf += identsz; + uint16_t optssize = bufbe16toh(buf); + if (optssize <= len - sizeof(uint16_t) - sizeof(uint64_t) - identsz - ident.GetSignatureLen() - sizeof(uint16_t)) + { + buf += sizeof(uint16_t); + std::map opts; + ExtractMapping(buf, optssize, opts); + buf += optssize; + //uint64_t date = bufbe64toh(buf); + buf += sizeof(uint64_t); + const uint8_t * sig = buf; + if(ident.Verify(body, len - sizeof(uint16_t), sig)) + { + if(m_Destination->Reconfigure(opts)) + { + LogPrint(eLogInfo, "I2CP: reconfigured destination"); + status = 2; // updated + } + else + LogPrint(eLogWarning, "I2CP: failed to reconfigure destination"); + } + else + LogPrint(eLogError, "I2CP: invalid reconfigure message signature"); + } + else + LogPrint(eLogError, "I2CP: mapping size missmatch"); + } + else + LogPrint(eLogError, "I2CP: destination missmatch"); + } + else + LogPrint(eLogError, "I2CP: malfromed destination"); + } + else + LogPrint(eLogError, "I2CP: session missmatch"); + } + else + LogPrint(eLogError, "I2CP: short message"); + SendSessionStatusMessage (status); } void I2CPSession::SendSessionStatusMessage (uint8_t status) From 254bf313a2e5cbc6fbcff656ea6c4da2c0eea24a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 2 Jan 2018 11:48:38 -0500 Subject: [PATCH 003/134] fix previous commit --- libi2pd_client/I2CP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 293f4067..5717ab50 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -441,7 +441,7 @@ namespace client //uint64_t date = bufbe64toh(buf); buf += sizeof(uint64_t); const uint8_t * sig = buf; - if(ident.Verify(body, len - sizeof(uint16_t), sig)) + if(ident.Verify(body, len - sizeof(uint16_t) - ident.GetSignatureLen(), sig)) { if(m_Destination->Reconfigure(opts)) { From ab80def94b3c5c53e3a250135922589dbda90d1f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 2 Jan 2018 12:06:10 -0500 Subject: [PATCH 004/134] use reference instead of copy --- libi2pd/Destination.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 160b95e6..642be1f9 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -197,7 +197,7 @@ namespace client minLatency = 0; maxLatency = 0; - for (auto opt : intOpts) + for (auto & opt : intOpts) { itr = params.find(opt.first); if(itr != params.end()) From 1967dee50c48b474979aa6e532f5677182c86d0d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 2 Jan 2018 12:59:16 -0500 Subject: [PATCH 005/134] don't recreate tunnels of different size --- libi2pd/Tunnel.cpp | 11 ++++++++--- libi2pd/TunnelPool.cpp | 28 ++++++++++++++++++---------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 6ae1e119..e39c4fd4 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -670,10 +670,12 @@ namespace tunnel { if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { - tunnel->SetIsRecreated (); auto pool = tunnel->GetTunnelPool (); - if (pool) + if (pool && tunnel->GetPeers().size() == pool->GetNumOutboundHops()) + { + tunnel->SetIsRecreated (); pool->RecreateOutboundTunnel (tunnel); + } } if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) tunnel->SetState (eTunnelStateExpiring); @@ -723,8 +725,11 @@ namespace tunnel { tunnel->SetIsRecreated (); auto pool = tunnel->GetTunnelPool (); - if (pool) + if (pool && tunnel->GetPeers().size() == pool->GetNumInboundHops()) + { + tunnel->SetIsRecreated (); pool->RecreateInboundTunnel (tunnel); + } } if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index dd163993..7fc2592c 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -491,11 +491,14 @@ namespace tunnel outboundTunnel = tunnels.GetNextOutboundTunnel (); LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel..."); std::shared_ptr config; - if (m_NumInboundHops > 0) config = std::make_shared(tunnel->GetPeers ()); - auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel); - newTunnel->SetTunnelPool (shared_from_this()); - if (newTunnel->IsEstablished ()) // zero hops - TunnelCreated (newTunnel); + if (m_NumInboundHops > 0 && tunnel->GetPeers().size() > 0) config = std::make_shared(tunnel->GetPeers ()); + if (m_NumInboundHops == 0 || config) + { + auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel); + newTunnel->SetTunnelPool (shared_from_this()); + if (newTunnel->IsEstablished ()) // zero hops + TunnelCreated (newTunnel); + } } void TunnelPool::CreateOutboundTunnel () @@ -533,12 +536,17 @@ namespace tunnel { LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel..."); std::shared_ptr config; - if (m_NumOutboundHops > 0) + if (tunnel->GetPeers().size() > 0 && m_NumOutboundHops > 0) + { config = std::make_shared(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()); - auto newTunnel = tunnels.CreateOutboundTunnel (config); - newTunnel->SetTunnelPool (shared_from_this ()); - if (newTunnel->IsEstablished ()) // zero hops - TunnelCreated (newTunnel); + } + if(m_NumOutboundHops == 0 || config) + { + auto newTunnel = tunnels.CreateOutboundTunnel (config); + newTunnel->SetTunnelPool (shared_from_this ()); + if (newTunnel->IsEstablished ()) // zero hops + TunnelCreated (newTunnel); + } } else LogPrint (eLogDebug, "Tunnels: Can't re-create outbound tunnel, no inbound tunnels found"); From 80149342f252c1cb96c50c7835a53da12c9c2adb Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 3 Jan 2018 10:02:11 -0500 Subject: [PATCH 006/134] proper bounds check --- libi2pd/Garlic.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 3212da01..f9c297f6 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -538,7 +538,7 @@ namespace garlic { case eGarlicDeliveryTypeLocal: LogPrint (eLogDebug, "Garlic: type local"); - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -549,7 +549,7 @@ namespace garlic LogPrint (eLogDebug, "Garlic: type destination"); buf += 32; // destination. check it later or for multiple destinations offset = buf1 - buf; - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -563,7 +563,7 @@ namespace garlic uint8_t * gwHash = buf; buf += 32; offset = buf1 - buf; - if (offset + 4 > (int)len) + if (offset + 4 > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -594,7 +594,7 @@ namespace garlic offset = buf1 - buf; if (!from) // received directly { - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -609,7 +609,7 @@ namespace garlic default: LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType); } - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -619,7 +619,7 @@ namespace garlic buf += 8; // Date buf += 3; // Certificate offset = buf1 - buf; - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: clove is too long"); break; From d41fabbc9fdcb324ecab7796775398a6f78219fc Mon Sep 17 00:00:00 2001 From: unknown542a Date: Sat, 6 Jan 2018 23:59:22 +0300 Subject: [PATCH 007/134] netDB and certificates in internal storage --- .../src/org/purplei2p/i2pd/Decompress.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 android/src/org/purplei2p/i2pd/Decompress.java diff --git a/android/src/org/purplei2p/i2pd/Decompress.java b/android/src/org/purplei2p/i2pd/Decompress.java new file mode 100644 index 00000000..917abc7c --- /dev/null +++ b/android/src/org/purplei2p/i2pd/Decompress.java @@ -0,0 +1,83 @@ +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()); + } + } + } +} From 81d7a832c098d21df939eea2e2d74312c1ba8232 Mon Sep 17 00:00:00 2001 From: unknown542a Date: Sun, 7 Jan 2018 00:08:07 +0300 Subject: [PATCH 008/134] netDB and certificates in internal storage --- android/.gitignore | 6 ++- android/build.gradle | 47 +++++++++++++++--------- android/jni/DaemonAndroid.cpp | 5 +-- android/jni/DaemonAndroid.h | 2 +- android/jni/i2pd_android.cpp | 11 +++++- android/src/org/purplei2p/i2pd/I2PD.java | 12 +++++- 6 files changed, 59 insertions(+), 24 deletions(-) diff --git a/android/.gitignore b/android/.gitignore index d9fa5a57..7e166aa6 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,4 +5,8 @@ ant.properties local.properties build.sh bin -log* \ No newline at end of file +log* +.gradle* +build +assets +gradle-app.setting diff --git a/android/build.gradle b/android/build.gradle index a88403fd..b69967ef 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,26 +8,32 @@ buildscript { } } +task clean(type: Delete,overwrite: true) { + delete 'build' + delete 'assets' +} + apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" - defaultConfig { - applicationId "org.purplei2p.i2pd" - targetSdkVersion 25 - minSdkVersion 14 - versionCode 1 - versionName "2.17.1" - } + compileSdkVersion 25 + buildToolsVersion "25.0.0" + defaultConfig { + applicationId "org.purplei2p.i2pd" + targetSdkVersion 25 + minSdkVersion 14 + versionCode 1 + versionName "2.17.2b" + } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] - res.srcDirs = ['res'] - jniLibs.srcDirs = ['libs'] - } + res.srcDirs = ['res'] + jniLibs.srcDirs = ['libs'] + assets.srcDirs = ['assets'] } + } signingConfigs { orignal { storeFile file("i2pdapk.jks") @@ -37,11 +43,18 @@ 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' + } } } +task zipCerts(type: Zip) { + archiveName 'certificates.zip' + destinationDir file('assets') + from (files('../contrib/certificates')) +} + +preBuild.dependsOn zipCerts diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp index 75584740..9865ac79 100644 --- a/android/jni/DaemonAndroid.cpp +++ b/android/jni/DaemonAndroid.cpp @@ -126,12 +126,11 @@ 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 { @@ -139,7 +138,7 @@ namespace android { //Log.d(TAG"Initialising the daemon..."); - bool daemonInitSuccess = daemon.init(1,argv); + bool daemonInitSuccess = daemon.init(argc,argv); if(!daemonInitSuccess) { //QMessageBox::critical(0, "Error", "Daemon init failed"); diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h index 9cc8219b..81031936 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(); + std::string start(int argc, char* argv[]); // stops the daemon void stop(); diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index 8791c90b..b4bfa6e6 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -45,7 +45,16 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon (JNIEnv * env, jclass clazz) { - return env->NewStringUTF(i2p::android::start().c_str()); + + int argc=5; + static char* argv[]={ + "i2pd", "--service", "--daemon", + "--conf=/sdcard/i2pd/i2pd.conf", + "--tunconf=/sdcard/i2pd/tunnels.conf", + "--datadir=/data/data/org.purplei2p.i2pd/app_data/" + }; + + return env->NewStringUTF(i2p::android::start(argc,argv).c_str()); } JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PD.java index 86b877ac..869cf570 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PD.java @@ -2,6 +2,13 @@ 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; @@ -26,7 +33,7 @@ public class I2PD extends Activity { private TextView textView; private final DaemonSingleton daemon = DaemonSingleton.getInstance(); - + private DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() { @@ -58,6 +65,9 @@ public class I2PD extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + //install certs every time + Decompress.unzipFromAssets(this, "certificates.zip", "/data/data/org.purplei2p.i2pd/app_data/"); + textView = new TextView(this); setContentView(textView); DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); From 8864cbf80ad50146757985b6b36a5aaa94aa91ff Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Sun, 7 Jan 2018 00:40:17 +0300 Subject: [PATCH 009/134] return to strdup() when filling argv[] for i2p::android::start(argc,argv).c_str() --- android/build.gradle | 2 +- android/jni/i2pd_android.cpp | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index b69967ef..fb2fe8c6 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -23,7 +23,7 @@ android { targetSdkVersion 25 minSdkVersion 14 versionCode 1 - versionName "2.17.2b" + versionName "2.17.2c" } sourceSets { main { diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index b4bfa6e6..ac1e2b70 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -46,13 +46,14 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon (JNIEnv * env, jclass clazz) { - int argc=5; - static char* argv[]={ - "i2pd", "--service", "--daemon", - "--conf=/sdcard/i2pd/i2pd.conf", - "--tunconf=/sdcard/i2pd/tunnels.conf", - "--datadir=/data/data/org.purplei2p.i2pd/app_data/" - }; + int argc=5; + static char* argv[]={ + strdup("i2pd"), + strdup("--conf=/sdcard/i2pd/i2pd.conf"), + strdup("--tunconf=/sdcard/i2pd/tunnels.conf"), + strdup("--datadir=/data/data/org.purplei2p.i2pd/app_data/"), + strdup("--service"), strdup("--daemon") + }; return env->NewStringUTF(i2p::android::start(argc,argv).c_str()); } From cf5081d300051b7c188ff39aacadad29d492900e Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Sun, 7 Jan 2018 19:30:32 +0300 Subject: [PATCH 010/134] fixed creating certificates.zip when target zip did not include the directory certificates, so they were bein unpacked into datadir. Added entryCompression ZipEntryCompression.STORED since final APK is being compressed as well. Put all custom tasks under android plugin definitions --- android/build.gradle | 22 ++++++++++++---------- android/gradle.properties | 1 + 2 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 android/gradle.properties diff --git a/android/build.gradle b/android/build.gradle index fb2fe8c6..fcbb47ec 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,11 +8,6 @@ buildscript { } } -task clean(type: Delete,overwrite: true) { - delete 'build' - delete 'assets' -} - apply plugin: 'com.android.application' android { @@ -23,7 +18,7 @@ android { targetSdkVersion 25 minSdkVersion 14 versionCode 1 - versionName "2.17.2c" + versionName "2.17.2e" } sourceSets { main { @@ -51,10 +46,17 @@ android { } } -task zipCerts(type: Zip) { - archiveName 'certificates.zip' +task zipCerts(type:Zip) { + from (files('../contrib/')) + include 'certificates/**/*.crt' destinationDir file('assets') - from (files('../contrib/certificates')) + archiveName 'certificates.zip' + entryCompression ZipEntryCompression.STORED +} +preBuild.dependsOn zipCerts + +task clean(type: Delete,overwrite: true) { + delete 'build' + delete 'assets' } -preBuild.dependsOn zipCerts diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 00000000..e32ec00b --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 From 207212557ebb5a2b63f1037d0b3a61d89b4f2b5f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 15 Jan 2018 08:19:57 -0500 Subject: [PATCH 011/134] fix sam race conditions --- libi2pd/Streaming.h | 21 +-- libi2pd_client/SAM.cpp | 320 ++++++++++++++++++++++++++--------------- libi2pd_client/SAM.h | 22 +-- 3 files changed, 227 insertions(+), 136 deletions(-) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 93cf2a9f..a9e5dcdd 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -69,7 +69,7 @@ namespace stream */ const uint64_t DEFAULT_BAN_INTERVAL = 60 * 60 * 1000; - struct Packet + struct Packet { size_t len, offset; uint8_t buf[MAX_PACKET_SIZE]; @@ -276,8 +276,8 @@ namespace stream /** set max connections per minute per destination */ void SetMaxConnsPerMinute(const uint32_t conns); - Packet * NewPacket () { return m_PacketsPool.Acquire (); } - void DeletePacket (Packet * p) { m_PacketsPool.Release (p); } + Packet * NewPacket () { return new Packet; } + void DeletePacket (Packet * p) { delete p; } private: @@ -316,7 +316,7 @@ namespace stream std::vector m_Banned; uint64_t m_LastBanClear; - i2p::util::MemoryPool m_PacketsPool; + //i2p::util::MemoryPool m_PacketsPool; bool m_EnableDrop; public: @@ -334,16 +334,21 @@ namespace stream void Stream::AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout) { auto s = shared_from_this(); - m_Service.post ([=](void) + m_Service.post ([s, buffer, handler, timeout](void) { if (!s->m_ReceiveQueue.empty () || s->m_Status == eStreamStatusReset) s->HandleReceiveTimer (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), buffer, handler, 0); else { - int t = (timeout > MAX_RECEIVE_TIMEOUT) ? MAX_RECEIVE_TIMEOUT : timeout; + int t = (timeout > MAX_RECEIVE_TIMEOUT) ? MAX_RECEIVE_TIMEOUT : timeout; s->m_ReceiveTimer.expires_from_now (boost::posix_time::seconds(t)); - s->m_ReceiveTimer.async_wait ([=](const boost::system::error_code& ecode) - { s->HandleReceiveTimer (ecode, buffer, handler, timeout - t); }); + int left = timeout - t; + auto self = s->shared_from_this(); + self->m_ReceiveTimer.async_wait ( + [self, buffer, handler, left](const boost::system::error_code & ec) + { + self->HandleReceiveTimer(ec, buffer, handler, left); + }); } }); } diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 140140fc..4ea6b61b 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -15,31 +15,22 @@ namespace i2p { namespace client { - SAMSocket::SAMSocket (SAMBridge& owner): - m_Owner (owner), m_Socket (m_Owner.GetService ()), m_Timer (m_Owner.GetService ()), - m_BufferOffset (0), m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false), - m_IsAccepting (false), m_Stream (nullptr), m_Session (nullptr) + SAMSocket::SAMSocket (SAMBridge& owner, std::shared_ptr socket): + m_Owner (owner), m_Socket(socket), m_Timer (m_Owner.GetService ()), + m_BufferOffset (0), + m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false), + m_IsAccepting (false), m_Stream (nullptr) { } SAMSocket::~SAMSocket () { - Terminate ("~SAMSocket()"); - } - - void SAMSocket::CloseStream (const char* reason) - { - LogPrint (eLogDebug, "SAMSocket::CloseStream, reason: ", reason); - if (m_Stream) + if(m_Stream) { m_Stream->Close (); m_Stream.reset (); - } - } - - void SAMSocket::Terminate (const char* reason) - { - CloseStream (reason); + } + auto Session = m_Owner.FindSession(m_ID); switch (m_SocketType) { @@ -48,17 +39,17 @@ namespace client break; case eSAMSocketTypeStream: { - if (m_Session) - m_Session->DelSocket (shared_from_this ()); + if (Session) + Session->DelSocket (this); break; } case eSAMSocketTypeAcceptor: { - if (m_Session) + if (Session) { - m_Session->DelSocket (shared_from_this ()); - if (m_IsAccepting && m_Session->localDestination) - m_Session->localDestination->StopAcceptingStreams (); + Session->DelSocket (this); + if (m_IsAccepting && Session->localDestination) + Session->localDestination->StopAcceptingStreams (); } break; } @@ -66,15 +57,54 @@ namespace client ; } m_SocketType = eSAMSocketTypeTerminated; - if (m_Socket.is_open()) m_Socket.close (); - m_Session = nullptr; + if (m_Socket && m_Socket->is_open()) m_Socket->close (); + m_Socket.reset (); + } + + void SAMSocket::Terminate (const char* reason) + { + if(m_Stream) + { + m_Stream->Close (); + m_Stream.reset (); + } + auto Session = m_Owner.FindSession(m_ID); + + switch (m_SocketType) + { + case eSAMSocketTypeSession: + m_Owner.CloseSession (m_ID); + break; + case eSAMSocketTypeStream: + { + if (Session) + Session->DelSocket (this); + break; + } + case eSAMSocketTypeAcceptor: + { + if (Session) + { + Session->DelSocket (this); + if (m_IsAccepting && Session->localDestination) + Session->localDestination->StopAcceptingStreams (); + } + break; + } + default: + ; + } + m_SocketType = eSAMSocketTypeTerminated; + if (m_Socket && m_Socket->is_open()) m_Socket->close (); + m_Socket.reset (); } void SAMSocket::ReceiveHandshake () { - m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), - std::bind(&SAMSocket::HandleHandshakeReceived, shared_from_this (), - std::placeholders::_1, std::placeholders::_2)); + if(m_Socket) + m_Socket->async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), + std::bind(&SAMSocket::HandleHandshakeReceived, shared_from_this (), + std::placeholders::_1, std::placeholders::_2)); } void SAMSocket::HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) @@ -121,7 +151,7 @@ namespace client #else size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ()); #endif - boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (), + boost::asio::async_write (*m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (), std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -144,9 +174,9 @@ namespace client if (ecode != boost::asio::error::operation_aborted) Terminate ("SAM: handshake reply send error"); } - else + else if(m_Socket) { - m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), + m_Socket->async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), std::bind(&SAMSocket::HandleMessage, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -157,7 +187,7 @@ namespace client LogPrint (eLogDebug, "SAMSocket::SendMessageReply, close=",close?"true":"false", " reason: ", msg); if (!m_IsSilent) - boost::asio::async_write (m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (), + boost::asio::async_write (*m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (), std::bind(&SAMSocket::HandleMessageReplySent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, close)); else @@ -306,19 +336,19 @@ namespace client } // create destination - m_Session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms); - if (m_Session) + auto session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms); + if (session) { m_SocketType = eSAMSocketTypeSession; if (style == SAM_VALUE_DATAGRAM) { - m_Session->UDPEndpoint = forward; - auto dest = m_Session->localDestination->CreateDatagramDestination (); + session->UDPEndpoint = forward; + auto dest = session->localDestination->CreateDatagramDestination (); dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); } - if (m_Session->localDestination->IsReady ()) + if (session->localDestination->IsReady ()) SendSessionCreateReplyOk (); else { @@ -335,30 +365,38 @@ namespace client { if (ecode != boost::asio::error::operation_aborted) { - if (m_Session->localDestination->IsReady ()) - SendSessionCreateReplyOk (); - else + auto session = m_Owner.FindSession(m_ID); + if(session) { - m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); - m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer, - shared_from_this (), std::placeholders::_1)); + if (session->localDestination->IsReady ()) + SendSessionCreateReplyOk (); + else + { + m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); + m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer, + shared_from_this (), std::placeholders::_1)); + } } } } void SAMSocket::SendSessionCreateReplyOk () { - uint8_t buf[1024]; - char priv[1024]; - size_t l = m_Session->localDestination->GetPrivateKeys ().ToBuffer (buf, 1024); - size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024); - priv[l1] = 0; + auto session = m_Owner.FindSession(m_ID); + if (session) + { + uint8_t buf[1024]; + char priv[1024]; + size_t l = session->localDestination->GetPrivateKeys ().ToBuffer (buf, 1024); + size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024); + priv[l1] = 0; #ifdef _MSC_VER - size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); + size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); #else - size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); + size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); #endif - SendMessageReply (m_Buffer, l2, false); + SendMessageReply (m_Buffer, l2, false); + } } void SAMSocket::ProcessStreamConnect (char * buf, size_t len, size_t rem) @@ -371,8 +409,8 @@ namespace client std::string& silent = params[SAM_PARAM_SILENT]; if (silent == SAM_VALUE_TRUE) m_IsSilent = true; m_ID = id; - m_Session = m_Owner.FindSession (id); - if (m_Session) + auto session = m_Owner.FindSession (id); + if (session) { if (rem > 0) // handle follow on data { @@ -387,12 +425,12 @@ namespace client if (l > 0) { context.GetAddressBook().InsertAddress(dest); - auto leaseSet = m_Session->localDestination->FindLeaseSet(dest->GetIdentHash()); + auto leaseSet = session->localDestination->FindLeaseSet(dest->GetIdentHash()); if (leaseSet) Connect(leaseSet); else { - m_Session->localDestination->RequestDestination(dest->GetIdentHash(), + session->localDestination->RequestDestination(dest->GetIdentHash(), std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete, shared_from_this(), std::placeholders::_1)); } @@ -406,13 +444,17 @@ namespace client void SAMSocket::Connect (std::shared_ptr remote) { - m_SocketType = eSAMSocketTypeStream; - m_Session->AddSocket (shared_from_this ()); - m_Stream = m_Session->localDestination->CreateStream (remote); - m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send - m_BufferOffset = 0; - I2PReceive (); - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + auto session = m_Owner.FindSession(m_ID); + if(session) + { + m_SocketType = eSAMSocketTypeStream; + session->AddSocket (shared_from_this ()); + m_Stream = session->localDestination->CreateStream (remote); + m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send + m_BufferOffset = 0; + I2PReceive (); + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + } } void SAMSocket::HandleConnectLeaseSetRequestComplete (std::shared_ptr leaseSet) @@ -435,15 +477,15 @@ namespace client std::string& silent = params[SAM_PARAM_SILENT]; if (silent == SAM_VALUE_TRUE) m_IsSilent = true; m_ID = id; - m_Session = m_Owner.FindSession (id); - if (m_Session) + auto session = m_Owner.FindSession (id); + if (session) { m_SocketType = eSAMSocketTypeAcceptor; - m_Session->AddSocket (shared_from_this ()); - if (!m_Session->localDestination->IsAcceptingStreams ()) + session->AddSocket (shared_from_this ()); + if (!session->localDestination->IsAcceptingStreams ()) { m_IsAccepting = true; - m_Session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); + session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); } @@ -459,9 +501,10 @@ namespace client size_t size = std::stoi(params[SAM_PARAM_SIZE]), offset = data - buf; if (offset + size <= len) { - if (m_Session) + auto session = m_Owner.FindSession(m_ID); + if (session) { - auto d = m_Session->localDestination->GetDatagramDestination (); + auto d = session->localDestination->GetDatagramDestination (); if (d) { i2p::data::IdentityEx dest; @@ -516,7 +559,8 @@ namespace client std::string& name = params[SAM_PARAM_NAME]; std::shared_ptr identity; i2p::data::IdentHash ident; - auto dest = m_Session == nullptr ? context.GetSharedLocalDestination() : m_Session->localDestination; + auto session = m_Owner.FindSession(m_ID); + auto dest = session == nullptr ? context.GetSharedLocalDestination() : session->localDestination; if (name == "ME") SendNamingLookupReply (dest->GetIdentity ()); else if ((identity = context.GetAddressBook ().GetAddress (name)) != nullptr) @@ -612,16 +656,18 @@ namespace client LogPrint (eLogError, "SAM: Buffer is full, terminate"); Terminate ("Buffer is full"); return; - } - m_Socket.async_read_some (boost::asio::buffer(m_Buffer + m_BufferOffset, SAM_SOCKET_BUFFER_SIZE - m_BufferOffset), - std::bind((m_SocketType == eSAMSocketTypeStream) ? &SAMSocket::HandleReceived : &SAMSocket::HandleMessage, - shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + } else if (m_Socket) + m_Socket->async_read_some (boost::asio::buffer(m_Buffer + m_BufferOffset, SAM_SOCKET_BUFFER_SIZE - m_BufferOffset), + std::bind((m_SocketType == eSAMSocketTypeStream) ? &SAMSocket::HandleReceived : &SAMSocket::HandleMessage, + shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + else + LogPrint(eLogError, "SAM: receive with no native socket"); } void SAMSocket::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) - { + { LogPrint (eLogError, "SAM: read error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) Terminate ("read error"); @@ -637,7 +683,7 @@ namespace client [s](const boost::system::error_code& ecode) { if (!ecode) - s->Receive (); + s->m_Owner.GetService ().post ([s] { s->Receive (); }); else s->m_Owner.GetService ().post ([s] { s->Terminate ("AsyncSend failed"); }); }); @@ -650,21 +696,21 @@ namespace client if (m_Stream) { if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || - m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular + m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular { m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE), - std::bind (&SAMSocket::HandleI2PReceive, shared_from_this (), + std::bind (&SAMSocket::HandleI2PReceive, shared_from_this(), std::placeholders::_1, std::placeholders::_2), - SAM_SOCKET_CONNECTION_MAX_IDLE); + SAM_SOCKET_CONNECTION_MAX_IDLE); } else // closed by peer { + uint8_t * buff = new uint8_t[SAM_SOCKET_BUFFER_SIZE]; // get remaning data - auto len = m_Stream->ReadSome (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE); + auto len = m_Stream->ReadSome (buff, SAM_SOCKET_BUFFER_SIZE); if (len > 0) // still some data { - boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, len), - std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); + WriteI2PDataImmediate(buff, len); } else // no more data Terminate ("no more data"); @@ -672,6 +718,30 @@ namespace client } } + void SAMSocket::WriteI2PDataImmediate(uint8_t * buff, size_t sz) + { + if(m_Socket) + boost::asio::async_write ( + *m_Socket, + boost::asio::buffer (buff, sz), + boost::asio::transfer_all(), + std::bind (&SAMSocket::HandleWriteI2PDataImmediate, shared_from_this (), std::placeholders::_1, buff)); // postpone termination + else + LogPrint(eLogError, "SAM: no native socket"); + } + + void SAMSocket::HandleWriteI2PDataImmediate(const boost::system::error_code & ec, uint8_t * buff) + { + delete [] buff; + } + + void SAMSocket::WriteI2PData(size_t sz) + { + uint8_t * sendbuff = new uint8_t[sz]; + memcpy(sendbuff, m_StreamBuffer, sz); + WriteI2PDataImmediate(sendbuff, sz); + } + void SAMSocket::HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) @@ -680,8 +750,9 @@ namespace client if (ecode != boost::asio::error::operation_aborted) { if (bytes_transferred > 0) - boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred), - std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); // postpone termination + { + WriteI2PData(bytes_transferred); + } else { auto s = shared_from_this (); @@ -696,13 +767,18 @@ namespace client } else { - if (m_SocketType != eSAMSocketTypeTerminated) // check for possible race condition with Terminate() - boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred), - std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); + if (m_SocketType != eSAMSocketTypeTerminated) + { + if (bytes_transferred > 0) + { + WriteI2PData(bytes_transferred); + } + I2PReceive(); + } } } - void SAMSocket::HandleWriteI2PData (const boost::system::error_code& ecode) + void SAMSocket::HandleWriteI2PData (const boost::system::error_code& ecode, size_t bytes_transferred) { if (ecode) { @@ -711,7 +787,9 @@ namespace client Terminate ("socket write error at HandleWriteI2PData"); } else + { I2PReceive (); + } } void SAMSocket::HandleI2PAccept (std::shared_ptr stream) @@ -760,39 +838,42 @@ namespace client { LogPrint (eLogDebug, "SAM: datagram received ", len); auto base64 = from.ToBase64 (); - auto ep = m_Session->UDPEndpoint; - if (ep) + auto session = m_Owner.FindSession(m_ID); + if(session) { - // udp forward enabled - size_t bsz = base64.size(); - size_t sz = bsz + 1 + len; - // build datagram body - uint8_t * data = new uint8_t[sz]; - // Destination - memcpy(data, base64.c_str(), bsz); - // linefeed - data[bsz] = '\n'; - // Payload - memcpy(data+bsz+1, buf, len); - // send to remote endpoint - m_Owner.SendTo(data, sz, ep); - delete [] data; - } - else - { -#ifdef _MSC_VER - size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); -#else - size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); -#endif - if (len < SAM_SOCKET_BUFFER_SIZE - l) + auto ep = session->UDPEndpoint; + if (ep) { - memcpy (m_StreamBuffer + l, buf, len); - boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, len + l), - std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); + // udp forward enabled + size_t bsz = base64.size(); + size_t sz = bsz + 1 + len; + // build datagram body + uint8_t * data = new uint8_t[sz]; + // Destination + memcpy(data, base64.c_str(), bsz); + // linefeed + data[bsz] = '\n'; + // Payload + memcpy(data+bsz+1, buf, len); + // send to remote endpoint + m_Owner.SendTo(data, sz, ep); + delete [] data; } else - LogPrint (eLogWarning, "SAM: received datagram size ", len," exceeds buffer"); + { +#ifdef _MSC_VER + size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); +#else + size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); +#endif + if (len < SAM_SOCKET_BUFFER_SIZE - l) + { + memcpy (m_StreamBuffer + l, buf, len); + WriteI2PData(len + l); + } + else + LogPrint (eLogWarning, "SAM: received datagram size ", len," exceeds buffer"); + } } } @@ -875,8 +956,9 @@ namespace client void SAMBridge::Accept () { - auto newSocket = std::make_shared (*this); - m_Acceptor.async_accept (newSocket->GetSocket (), std::bind (&SAMBridge::HandleAccept, this, + auto native = std::make_shared(m_Service); + auto newSocket = std::make_shared (*this, native); + m_Acceptor.async_accept (*native, std::bind (&SAMBridge::HandleAccept, this, std::placeholders::_1, newSocket)); } diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index f2c84e3c..9282fe1d 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -79,11 +79,11 @@ namespace client { public: - SAMSocket (SAMBridge& owner); + typedef boost::asio::ip::tcp::socket Socket_t; + SAMSocket (SAMBridge& owner, std::shared_ptr socket); ~SAMSocket (); - void CloseStream (const char* reason); // TODO: implement it better - boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; + boost::asio::ip::tcp::socket& GetSocket () { return *m_Socket; }; void ReceiveHandshake (); void SetSocketType (SAMSocketType socketType) { m_SocketType = socketType; }; SAMSocketType GetSocketType () const { return m_SocketType; }; @@ -103,7 +103,7 @@ namespace client void I2PReceive (); void HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleI2PAccept (std::shared_ptr stream); - void HandleWriteI2PData (const boost::system::error_code& ecode); + void HandleWriteI2PData (const boost::system::error_code& ecode, size_t sz); void HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void ProcessSessionCreate (char * buf, size_t len); @@ -122,10 +122,15 @@ namespace client void HandleSessionReadinessCheckTimer (const boost::system::error_code& ecode); void SendSessionCreateReplyOk (); + void WriteI2PData(size_t sz); + void WriteI2PDataImmediate(uint8_t * ptr, size_t sz); + + void HandleWriteI2PDataImmediate(const boost::system::error_code & ec, uint8_t * buff); + private: SAMBridge& m_Owner; - boost::asio::ip::tcp::socket m_Socket; + std::shared_ptr m_Socket; boost::asio::deadline_timer m_Timer; char m_Buffer[SAM_SOCKET_BUFFER_SIZE + 1]; size_t m_BufferOffset; @@ -135,7 +140,6 @@ namespace client bool m_IsSilent; bool m_IsAccepting; // for eSAMSocketTypeAcceptor only std::shared_ptr m_Stream; - std::shared_ptr m_Session; }; struct SAMSession @@ -146,15 +150,15 @@ namespace client std::mutex m_SocketsMutex; /** safely add a socket to this session */ - void AddSocket(const std::shared_ptr & sock) { + void AddSocket(std::shared_ptr sock) { std::lock_guard lock(m_SocketsMutex); m_Sockets.push_back(sock); } /** safely remove a socket from this session */ - void DelSocket(const std::shared_ptr & sock) { + void DelSocket(SAMSocket * sock) { std::lock_guard lock(m_SocketsMutex); - m_Sockets.remove(sock); + m_Sockets.remove_if([sock](const std::shared_ptr s) -> bool { return s.get() == sock; }); } /** get a list holding a copy of all sam sockets from this session */ From 951f8972c78de0850143118eac0926eb5f32144a Mon Sep 17 00:00:00 2001 From: yangfl Date: Thu, 11 Jan 2018 13:48:09 +0800 Subject: [PATCH 012/134] replace non-working CheckLibcxxAtomic --- build/CMakeLists.txt | 10 +- build/cmake_modules/CheckAtomic.cmake | 106 ++++++++++++++++++++ build/cmake_modules/CheckLibcxxAtomic.cmake | 47 --------- 3 files changed, 108 insertions(+), 55 deletions(-) create mode 100644 build/cmake_modules/CheckAtomic.cmake delete mode 100644 build/cmake_modules/CheckLibcxxAtomic.cmake diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 4d462700..bc80423a 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -257,8 +257,6 @@ if(THREADS_HAVE_PTHREAD_ARG) # compile time flag set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") endif() -include(CheckLibcxxAtomic) - if (WITH_STATIC) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) @@ -384,11 +382,7 @@ if (WITH_MESHNET) message(WARNING "This build will NOT work on mainline i2p") endif() -if (ARCHITECTURE MATCHES "arm") - set(ATOMIC_LIB -latomic) -else() - set(ATMOIC_LIB "") -endif() +include(CheckAtomic) # show summary @@ -457,7 +451,7 @@ if (WITH_BINARY) if (WITH_STATIC) set(DL_LIB ${CMAKE_DL_LIBS}) endif() - target_link_libraries( "${PROJECT_NAME}" libi2pd i2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${ATOMIC_LIB}) + target_link_libraries( "${PROJECT_NAME}" libi2pd i2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime) set (APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}") diff --git a/build/cmake_modules/CheckAtomic.cmake b/build/cmake_modules/CheckAtomic.cmake new file mode 100644 index 00000000..b8296a1c --- /dev/null +++ b/build/cmake_modules/CheckAtomic.cmake @@ -0,0 +1,106 @@ +# atomic builtins are required for threading support. + +INCLUDE(CheckCXXSourceCompiles) + +# Sometimes linking against libatomic is required for atomic ops, if +# the platform doesn't support lock-free atomics. + +function(check_working_cxx_atomics varname) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "-std=c++11") + CHECK_CXX_SOURCE_COMPILES(" +#include +std::atomic x; +int main() { + return x; +} +" ${varname}) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +endfunction(check_working_cxx_atomics) + +function(check_working_cxx_atomics64 varname) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}") + CHECK_CXX_SOURCE_COMPILES(" +#include +#include +std::atomic x (0); +int main() { + uint64_t i = x.load(std::memory_order_relaxed); + return 0; +} +" ${varname}) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +endfunction(check_working_cxx_atomics64) + + +# This isn't necessary on MSVC, so avoid command-line switch annoyance +# by only running on GCC-like hosts. +if (LLVM_COMPILER_IS_GCC_COMPATIBLE) + # First check if atomics work without the library. + check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) + # If not, check if the library exists, and atomics work with it. + if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) + check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) + if( HAVE_LIBATOMIC ) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) + if (NOT HAVE_CXX_ATOMICS_WITH_LIB) + message(FATAL_ERROR "Host compiler must support std::atomic!") + endif() + else() + message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") + endif() + endif() +endif() + +# Check for 64 bit atomic operations. +if(MSVC) + set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True) +else() + check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) +endif() + +# If not, check if the library exists, and atomics work with it. +if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) + check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) + if(HAVE_CXX_LIBATOMICS64) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) + if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) + message(FATAL_ERROR "Host compiler must support std::atomic!") + endif() + else() + message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") + endif() +endif() + +## TODO: This define is only used for the legacy atomic operations in +## llvm's Atomic.h, which should be replaced. Other code simply +## assumes C++11 works. +CHECK_CXX_SOURCE_COMPILES(" +#ifdef _MSC_VER +#include /* Workaround for PR19898. */ +#include +#endif +int main() { +#ifdef _MSC_VER + volatile LONG val = 1; + MemoryBarrier(); + InterlockedCompareExchange(&val, 0, 1); + InterlockedIncrement(&val); + InterlockedDecrement(&val); +#else + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); +#endif + return 0; + } +" LLVM_HAS_ATOMICS) + +if( NOT LLVM_HAS_ATOMICS ) + message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") +endif() diff --git a/build/cmake_modules/CheckLibcxxAtomic.cmake b/build/cmake_modules/CheckLibcxxAtomic.cmake deleted file mode 100644 index a7ae667a..00000000 --- a/build/cmake_modules/CheckLibcxxAtomic.cmake +++ /dev/null @@ -1,47 +0,0 @@ -INCLUDE(CheckCXXSourceCompiles) - -# Sometimes linking against libatomic is required for atomic ops, if -# the platform doesn't support lock-free atomics. -# -# We could modify LLVM's CheckAtomic module and have it check for 64-bit -# atomics instead. However, we would like to avoid careless uses of 64-bit -# atomics inside LLVM over time on 32-bit platforms. - -function(check_cxx_atomics varname) - set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "-nodefaultlibs -std=c++11 -nostdinc++ -isystem ${LIBCXX_SOURCE_DIR}/include") - if (${LIBCXX_GCC_TOOLCHAIN}) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} --gcc-toolchain=${LIBCXX_GCC_TOOLCHAIN}") - endif() - if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all") - endif() - if (CMAKE_C_FLAGS MATCHES -fsanitize-coverage OR CMAKE_CXX_FLAGS MATCHES -fsanitize-coverage) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters") - endif() - check_cxx_source_compiles(" -#include -#include -std::atomic x; -std::atomic y; -int main() { - return x + y; -} -" ${varname}) - set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) -endfunction(check_cxx_atomics) - -check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB) -check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB) -# If not, check if the library exists, and atomics work with it. -if(NOT LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB) - if(LIBCXX_HAS_ATOMIC_LIB) - list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") - check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB) - if (NOT LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB) - message(WARNING "Host compiler must support std::atomic!") - endif() - else() - message(WARNING "Host compiler appears to require libatomic, but cannot find it.") - endif() -endif() From bc72800fef9aa42bef305bb6700da167c5ba00fe Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Wed, 17 Jan 2018 20:58:56 +0300 Subject: [PATCH 013/134] moved hard code into java side and successfully passed back to native --- android/jni/i2pd_android.cpp | 29 ++++++++++++------- android/jni/org_purplei2p_i2pd_I2PD_JNI.h | 2 +- .../org/purplei2p/i2pd/DaemonSingleton.java | 11 ++++++- android/src/org/purplei2p/i2pd/I2PD_JNI.java | 2 +- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index ac1e2b70..5a8d8eaf 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -44,18 +44,27 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith } JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv * env, jclass clazz) { + (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); + } - int argc=5; - static char* argv[]={ - strdup("i2pd"), - strdup("--conf=/sdcard/i2pd/i2pd.conf"), - strdup("--tunconf=/sdcard/i2pd/tunnels.conf"), - strdup("--datadir=/data/data/org.purplei2p.i2pd/app_data/"), - strdup("--service"), strdup("--daemon") - }; + 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(i2p::android::start(argc,argv).c_str()); + return env->NewStringUTF(result); } 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 04923d22..484b3230 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); + (JNIEnv *, jclass, jobjectArray args); 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 e1ebc269..e95e0df1 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -62,7 +62,16 @@ public class DaemonSingleton { } try { synchronized (DaemonSingleton.this) { - daemonStartResult = I2PD_JNI.startDaemon(); + String args[] = { + "i2pd", + "--conf=/sdcard/i2pd/i2pd.conf", + "--tunconf=/sdcard/i2pd/tunnels.conf", + "--datadir=/data/data/org.purplei2p.i2pd/app_data/", + "--service", + "--daemon" + }; + + daemonStartResult = I2PD_JNI.startDaemon(args); if("ok".equals(daemonStartResult)){ state=State.startedOkay; setStartedOkay(true); diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java index 5a3addbf..bfdf8967 100644 --- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java +++ b/android/src/org/purplei2p/i2pd/I2PD_JNI.java @@ -6,7 +6,7 @@ public class I2PD_JNI { * returns error info if failed * returns "ok" if daemon initialized and started okay */ - public static native String startDaemon(); + public static native String startDaemon(String args[]); //should only be called after startDaemon() success public static native void stopDaemon(); From 0bd4db4cc795d968e1f24fa81d95179d3fdf394a Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Thu, 18 Jan 2018 16:41:02 +0300 Subject: [PATCH 014/134] less lines --- android/jni/i2pd_android.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index 5a8d8eaf..19f78a8d 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -56,14 +56,11 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon 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); } From 4c6988e3bc9ebd1d34e0b5faa50748c75a160c8b Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Thu, 18 Jan 2018 19:35:37 +0300 Subject: [PATCH 015/134] code cleanup --- android/build.gradle | 5 +++++ android/gradle.properties | 2 +- .../src/org/purplei2p/i2pd/DaemonSingleton.java | 17 ++++++++--------- .../org/purplei2p/i2pd/ForegroundService.java | 13 +++++++++++-- android/src/org/purplei2p/i2pd/I2PD.java | 2 +- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index fcbb47ec..46d0d057 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -46,6 +46,11 @@ android { } } +tasks.withType(JavaCompile) { + options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation' + options.deprecation = true +} + task zipCerts(type:Zip) { from (files('../contrib/')) include 'certificates/**/*.crt' diff --git a/android/gradle.properties b/android/gradle.properties index e32ec00b..d8894a70 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1 +1 @@ -org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx2048M -XX:MaxPermSize=256M -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index e95e0df1..031a7ef1 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -38,7 +38,7 @@ public class DaemonSingleton { public State getState() { return state; } - public synchronized void start() { + public synchronized void start(final String confDir, final String dataDir) { if(state != State.uninitialized)return; state = State.starting; fireStateUpdate(); @@ -62,14 +62,13 @@ public class DaemonSingleton { } try { synchronized (DaemonSingleton.this) { - String args[] = { - "i2pd", - "--conf=/sdcard/i2pd/i2pd.conf", - "--tunconf=/sdcard/i2pd/tunnels.conf", - "--datadir=/data/data/org.purplei2p.i2pd/app_data/", - "--service", - "--daemon" - }; + + String args[] = new String[] { + "i2pd", "--service", "--daemon", + "--datadir=" + dataDir, + "--conf=" + confDir + "/i2pd.conf", + "--tunconf=" + confDir + "/tunnels.conf" + }; daemonStartResult = I2PD_JNI.startDaemon(args); if("ok".equals(daemonStartResult)){ diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index d25d0a88..645d0dca 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -5,6 +5,8 @@ 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; @@ -28,13 +30,20 @@ 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(); - daemon.start(); + + Log.i("ForegroundService", "About to start daemon with dataDir: " + dataDir + ", confDir: " + confDir); + daemon.start(confDir, dataDir); // Tell the user we started. Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); } @@ -42,7 +51,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(); + daemon.start(confDir, dataDir); return START_STICKY; } diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PD.java index 869cf570..b9d8d037 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PD.java @@ -66,7 +66,7 @@ public class I2PD extends Activity { super.onCreate(savedInstanceState); //install certs every time - Decompress.unzipFromAssets(this, "certificates.zip", "/data/data/org.purplei2p.i2pd/app_data/"); + Decompress.unzipFromAssets(this, "certificates.zip", this.getDir("data", Context.MODE_PRIVATE).toString() + "/" ); textView = new TextView(this); setContentView(textView); From b3b38015c28a3b7e052023f116c0ca99c170ab9c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 20 Jan 2018 07:31:05 -0500 Subject: [PATCH 016/134] check max buffer size in Stream::Send --- libi2pd/Streaming.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 37d9d2c4..9942d8e2 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -378,9 +378,15 @@ namespace stream size_t Stream::Send (const uint8_t * buf, size_t len) { - // TODO: check max buffer size + size_t sent = len; + while(len > MAX_PACKET_SIZE) + { + AsyncSend (buf, MAX_PACKET_SIZE, nullptr); + buf += MAX_PACKET_SIZE; + len -= MAX_PACKET_SIZE; + } AsyncSend (buf, len, nullptr); - return len; + return sent; } void Stream::AsyncSend (const uint8_t * buf, size_t len, SendHandler handler) From 06020b8f544ae09734992a47c95597e9998629c2 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 20 Jan 2018 13:06:08 -0500 Subject: [PATCH 017/134] re-enable packet pool --- libi2pd/Streaming.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 9410df9d..a114844d 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -276,8 +276,8 @@ namespace stream /** set max connections per minute per destination */ void SetMaxConnsPerMinute(const uint32_t conns); - Packet * NewPacket () { return new Packet; } - void DeletePacket (Packet * p) { delete p; } + Packet * NewPacket () { return m_PacketsPool.Acquire(); } + void DeletePacket (Packet * p) { return m_PacketsPool.Release(p); } void AcceptOnceAcceptor (std::shared_ptr stream, Acceptor acceptor, Acceptor prev); @@ -315,7 +315,7 @@ namespace stream std::vector m_Banned; uint64_t m_LastBanClear; - //i2p::util::MemoryPool m_PacketsPool; + i2p::util::MemoryPool m_PacketsPool; bool m_EnableDrop; public: From 42d3770b1492331e6840bbf9f2f7fbc0d1cd66c0 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 21 Jan 2018 11:28:16 -0500 Subject: [PATCH 018/134] fixed layout --- README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 546cea64..4d8bf108 100644 --- a/README.md +++ b/README.md @@ -3,27 +3,27 @@ i2pd [Русская версия](https://github.com/PurpleI2P/i2pd_docs_ru/blob/master/README.md) -i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client. +i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client. -I2P (Invisible Internet Protocol) is a universal anonymous network layer. +I2P (Invisible Internet Protocol) is a universal anonymous network layer. All communications over I2P are anonymous and end-to-end encrypted, participants -don't reveal their real IP addresses. +don't reveal their real IP addresses. I2P client is a software used for building and using anonymous I2P networks. Such networks are commonly used for anonymous peer-to-peer applications (filesharing, cryptocurrencies) and anonymous client-server -applications (websites, instant messengers, chat-servers). +applications (websites, instant messengers, chat-servers). I2P allows people from all around the world to communicate and share information -without restrictions. +without restrictions. Features -------- -* Distributed anonymous networking framework -* End-to-end encrypted communications -* Small footprint, simple dependencies, fast performance -* Rich set of APIs for developers of secure applications +* Distributed anonymous networking framework +* End-to-end encrypted communications +* Small footprint, simple dependencies, fast performance +* Rich set of APIs for developers of secure applications Resources --------- @@ -41,7 +41,7 @@ Installing The easiest way to install i2pd is by using [precompiled binaries](https://github.com/PurpleI2P/i2pd/releases/latest). See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build -i2pd from source on your OS. +i2pd from source on your OS. Build instructions: @@ -70,16 +70,16 @@ See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and Donations --------- -BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY -ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ -DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF -LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 -DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y -ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z -GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG +BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY +ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ +DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF +LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 +DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y +ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z +GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG License ------- This project is licensed under the BSD 3-clause license, which can be found in the file -LICENSE in the root of the project source code. +LICENSE in the root of the project source code. From 347a2c215001f888f047c3fe26834477dec15567 Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Mon, 22 Jan 2018 01:30:21 +0300 Subject: [PATCH 019/134] fixing conflicts --- android/.gitignore | 6 +- android/build.gradle | 54 ++++++++---- 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 +- 11 files changed, 205 insertions(+), 55 deletions(-) create mode 100644 android/src/org/purplei2p/i2pd/Decompress.java diff --git a/android/.gitignore b/android/.gitignore index d9fa5a57..7e166aa6 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,4 +5,8 @@ ant.properties local.properties build.sh bin -log* \ No newline at end of file +log* +.gradle* +build +assets +gradle-app.setting diff --git a/android/build.gradle b/android/build.gradle index a88403fd..46d0d057 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -11,23 +11,24 @@ buildscript { apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" - defaultConfig { - applicationId "org.purplei2p.i2pd" - targetSdkVersion 25 - minSdkVersion 14 - versionCode 1 - versionName "2.17.1" - } + compileSdkVersion 25 + buildToolsVersion "25.0.0" + defaultConfig { + applicationId "org.purplei2p.i2pd" + targetSdkVersion 25 + minSdkVersion 14 + versionCode 1 + versionName "2.17.2e" + } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] - res.srcDirs = ['res'] - jniLibs.srcDirs = ['libs'] - } + res.srcDirs = ['res'] + jniLibs.srcDirs = ['libs'] + assets.srcDirs = ['assets'] } + } signingConfigs { orignal { storeFile file("i2pdapk.jks") @@ -37,11 +38,30 @@ 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/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp index 75584740..9865ac79 100644 --- a/android/jni/DaemonAndroid.cpp +++ b/android/jni/DaemonAndroid.cpp @@ -126,12 +126,11 @@ 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 { @@ -139,7 +138,7 @@ namespace android { //Log.d(TAG"Initialising the daemon..."); - bool daemonInitSuccess = daemon.init(1,argv); + bool daemonInitSuccess = daemon.init(argc,argv); if(!daemonInitSuccess) { //QMessageBox::critical(0, "Error", "Daemon init failed"); diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h index 9cc8219b..81031936 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(); + std::string start(int argc, char* argv[]); // stops the daemon void stop(); diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index 8791c90b..1079a252 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -44,8 +44,24 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith } JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv * env, jclass clazz) { - return env->NewStringUTF(i2p::android::start().c_str()); + (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); } 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 04923d22..484b3230 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); + (JNIEnv *, jclass, jobjectArray args); 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 65afd0f5..beff0c39 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,20 +25,21 @@ 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(); @@ -62,7 +63,15 @@ public class DaemonSingleton { } try { synchronized (DaemonSingleton.this) { - daemonStartResult = I2PD_JNI.startDaemon(); + + String args[] = new String[] { + "i2pd", "--service", "--daemon", + "--datadir=" + dataDir, + "--conf=" + confDir + "/i2pd.conf", + "--tunconf=" + confDir + "/tunnels.conf" + }; + + daemonStartResult = I2PD_JNI.startDaemon(args); if("ok".equals(daemonStartResult)){ state=State.startedOkay; setStartedOkay(true); @@ -76,9 +85,9 @@ public class DaemonSingleton { fireStateUpdate(); } return; - } + } } - + }, "i2pdDaemonStart").start(); } private Throwable lastThrowable; @@ -87,10 +96,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); } } } @@ -102,7 +111,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 new file mode 100644 index 00000000..917abc7c --- /dev/null +++ b/android/src/org/purplei2p/i2pd/Decompress.java @@ -0,0 +1,83 @@ +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 bfd650c8..645d0dca 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -5,6 +5,8 @@ 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; @@ -28,13 +30,20 @@ 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(); - daemon.start(); + + Log.i("ForegroundService", "About to start daemon with dataDir: " + dataDir + ", confDir: " + confDir); + daemon.start(confDir, dataDir); // Tell the user we started. Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); } @@ -42,7 +51,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(); + daemon.start(confDir, dataDir); return START_STICKY; } @@ -50,7 +59,7 @@ public class ForegroundService extends Service { public void onDestroy() { // Cancel the persistent notification. notificationManager.cancel(NOTIFICATION); - + stopForeground(true); // Tell the user we stopped. @@ -91,7 +100,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 a2494b2b..d66a0174 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PD.java @@ -2,6 +2,13 @@ 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; @@ -24,12 +31,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(){ @@ -53,11 +60,14 @@ 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); @@ -123,7 +133,7 @@ public class I2PD extends Activity { } }; - + private boolean mIsBound; private void doBindService() { @@ -147,7 +157,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; } @@ -216,9 +226,9 @@ public class I2PD extends Activity { @Override public void run() { - quit(); + quit(); } - + }, 10*60*1000/*milliseconds*/); }else{ quit(); @@ -227,7 +237,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 f965d471..bfdf8967 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(); + public static native String startDaemon(String args[]); //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 626ed720a6b3483746f1b9321617783d409a821e Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 22 Jan 2018 12:59:34 -0500 Subject: [PATCH 020/134] 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 | 43 ++++------ .../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, 57 insertions(+), 208 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) { + 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() { From 4ee364640d85eb2966217e526ff12ee674d27e82 Mon Sep 17 00:00:00 2001 From: Darknet Villain Date: Mon, 22 Jan 2018 13:55:12 -0500 Subject: [PATCH 021/134] Update rpm spec and systemd unit --- contrib/rpm/i2pd.service | 23 +++++++++++++++++------ contrib/rpm/i2pd.spec | 18 ++++++++++++++---- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service index b14af025..89562ff5 100644 --- a/contrib/rpm/i2pd.service +++ b/contrib/rpm/i2pd.service @@ -1,16 +1,27 @@ [Unit] -Description=I2P router +Description=I2P Router written in C++ After=network.target [Service] User=i2pd Group=i2pd +RuntimeDirectory=i2pd +RuntimeDirectoryMode=0700 Type=simple -ExecStart=/usr/bin/i2pd --service -PIDFile=/var/lib/i2pd/i2pd.pid -Restart=always -PrivateTmp=true +ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service +ExecReload=/bin/kill -HUP $MAINPID +PIDFile=/var/run/i2pd/i2pd.pid +### Uncomment, if auto restart needed +#Restart=on-failure + +### Use SIGINT for graceful stop daemon. +# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die. +KillSignal=SIGINT +TimeoutStopSec=10m + +# If you have problems with hunging i2pd, you can try enable this +#LimitNOFILE=4096 +PrivateDevices=yes [Install] WantedBy=multi-user.target - diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 0b6fa463..f0f7a9a7 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -68,9 +68,15 @@ make %{?_smp_mflags} %install cd build chrpath -d i2pd -install -D -m 755 i2pd %{buildroot}%{_bindir}/i2pd +install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd +install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf +install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf +install -d -m 755 %{buildroot}/%{_datadir}/i2pd +%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}/%{_unitdir}/i2pd.service install -d -m 700 %{buildroot}/%{_sharedstatedir}/i2pd +install -d -m 700 %{buildroot}/%{_localstatedir}/log/i2pd +ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/%{name}/certificates %pre systemd @@ -94,12 +100,16 @@ getent passwd i2pd >/dev/null || \ %files %doc LICENSE README.md -%_bindir/i2pd +%{_sbindir}/i2pd +%{_datadir}/i2pd/certificates +%config(noreplace) %{_sysconfdir}/i2pd/* %files systemd -/%_unitdir/i2pd.service -%dir %attr(0700,i2pd,i2pd) %_sharedstatedir/i2pd +/%{_unitdir}/i2pd.service +%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd +%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd +%{_sharedstatedir}/i2pd/certificates %changelog From c730839989d3d00d70c649226ecf92530985fba0 Mon Sep 17 00:00:00 2001 From: Veggie Monster Date: Mon, 22 Jan 2018 20:47:31 -0500 Subject: [PATCH 022/134] 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 023/134] 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 024/134] 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 025/134] 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 026/134] 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 027/134] 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; From e070ce4e3493dd06c9572f7b79e3bbfb2cf30d34 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 09:35:24 -0500 Subject: [PATCH 028/134] check for valid LS before updating --- libi2pd/NetDb.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0215c570..afe2fdde 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -237,19 +237,17 @@ namespace data auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - if (it->second->IsNewer (buf, len)) + /* make sure LS is valid before updating */ + LeaseSet ls(buf, len, false); + if(!ls.IsValid()) + { + LogPrint(eLogInfo, "NetDb: Updated LeaseSet is Invalid: ", ident.ToBase32()); + } + else if (it->second->IsNewer (buf, len)) { it->second->Update (buf, len); - if (it->second->IsValid ()) - { - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); - updated = true; - } - else - { - LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); - m_LeaseSets.erase (it); - } + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); + updated = true; } else LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); From 3820b51960c5532aa53f29607f82866b92ff9c8b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 09:44:55 -0500 Subject: [PATCH 029/134] Revert "check for valid LS before updating" This reverts commit e070ce4e3493dd06c9572f7b79e3bbfb2cf30d34. --- libi2pd/NetDb.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index afe2fdde..0215c570 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -237,17 +237,19 @@ namespace data auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - /* make sure LS is valid before updating */ - LeaseSet ls(buf, len, false); - if(!ls.IsValid()) - { - LogPrint(eLogInfo, "NetDb: Updated LeaseSet is Invalid: ", ident.ToBase32()); - } - else if (it->second->IsNewer (buf, len)) + if (it->second->IsNewer (buf, len)) { it->second->Update (buf, len); - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); - updated = true; + if (it->second->IsValid ()) + { + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); + updated = true; + } + else + { + LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); + m_LeaseSets.erase (it); + } } else LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); From 4a77a030338a8bc8f41617f3466cafcb551ecf06 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 10:16:51 -0500 Subject: [PATCH 030/134] * Add LeaseSetBufferValidate which checks lease validity and extracts timestamp * check for leases with LeaseSetBufferValidate before update in floodfill code as to prevent malicous nodes removing good LS --- libi2pd/LeaseSet.cpp | 34 ++++++++++++++++++++++++++++++++++ libi2pd/LeaseSet.h | 6 ++++++ libi2pd/NetDb.cpp | 14 ++++++-------- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d1a70ba5..02fdafb6 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -265,5 +265,39 @@ namespace data auto ts = i2p::util::GetMillisecondsSinceEpoch (); return ts > m_ExpirationTime; } + + bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires) + { + IdentityEx ident(ptr, sz); + size_t size = ident.GetFullLen (); + if (size > sz) + { + LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", sz); + return false; + } + // encryption key + size += 256; + // signing key (unused) + size += ident.GetSigningPublicKeyLen (); + uint8_t numLeases = ptr[size]; + ++size; + if (!numLeases || numLeases > MAX_NUM_LEASES) + { + LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)numLeases); + return false; + } + const uint8_t * leases = ptr + size; + expires = 0; + /** find lease with the max expiration timestamp */ + for (int i = 0; i < numLeases; i++) + { + leases += 36; // gateway + tunnel ID + uint64_t endDate = bufbe64toh (leases); + leases += 8; // end date + if(endDate > expires) + expires = endDate; + } + return ident.Verify(ptr, leases - ptr, leases); + } } } diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index c7d2066e..4c2903aa 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -95,6 +95,12 @@ namespace data size_t m_BufferLen; }; + /** + validate lease set buffer signature and extract expiration timestamp + @returns true if the leaseset is well formed and signature is valid + */ + bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires); + class LocalLeaseSet { public: diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0215c570..b5e20628 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -237,22 +237,20 @@ namespace data auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - if (it->second->IsNewer (buf, len)) + uint64_t expires; + if(LeaseSetBufferValidate(buf, len, expires)) { - it->second->Update (buf, len); - if (it->second->IsValid ()) + if(it->second->GetExpirationTime() < expires) { + it->second->Update (buf, len); LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); updated = true; } else - { - LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); - m_LeaseSets.erase (it); - } + LogPrint(eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); } else - LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); + LogPrint(eLogError, "NetDb: LeaseSet is invalid: ", ident.ToBase32()); } else { From 3ac86db0380274261666f7a047ac696190dc9245 Mon Sep 17 00:00:00 2001 From: Darknet Villain Date: Wed, 24 Jan 2018 12:48:05 -0500 Subject: [PATCH 031/134] Fix Docker image error --- contrib/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 5ca03f4c..e7e60f37 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -35,7 +35,7 @@ RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boos && mv i2pd /usr/local/bin \ && cd /usr/local/bin \ && strip i2pd \ - && rm -fr /tmp/build && apk --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \ + && rm -fr /tmp/build && apk --no-cache --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \ boost-python3 python3 gdbm boost-unit_test_framework boost-python linux-headers boost-prg_exec_monitor \ boost-serialization boost-signals boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre \ libtool g++ gcc pkgconfig From f4a2dda94e9adc36b3078c6f0d2829df93102c37 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 25 Jan 2018 08:49:30 -0500 Subject: [PATCH 032/134] try streaming race condition fix --- libi2pd/Streaming.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 9942d8e2..91acc9d0 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -578,7 +578,9 @@ namespace stream if (m_SentPackets.empty () && m_SendBuffer.IsEmpty ()) // nothing to send { m_Status = eStreamStatusClosed; - SendClose (); + // close could be called from another thread so do SendClose from the destination thread + // this is so m_LocalDestination.NewPacket () does not trigger a race condition + m_Service.post(std::bind(&Stream::SendClose, shared_from_this())); } break; case eStreamStatusClosed: From b1c701085b5bf9115b06b3c1d84ba48dab9b0f18 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 25 Jan 2018 10:09:34 -0500 Subject: [PATCH 033/134] don't verify signature twice --- libi2pd/LeaseSet.cpp | 6 +++--- libi2pd/LeaseSet.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 02fdafb6..497a562f 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -31,7 +31,7 @@ namespace data } memcpy (m_Buffer, buf, len); m_BufferLen = len; - ReadFromBuffer (false); + ReadFromBuffer (false, false); // we assume signature is verified already } void LeaseSet::PopulateLeases () @@ -40,7 +40,7 @@ namespace data ReadFromBuffer (false); } - void LeaseSet::ReadFromBuffer (bool readIdentity) + void LeaseSet::ReadFromBuffer (bool readIdentity, bool verifySignature) { if (readIdentity || !m_Identity) m_Identity = std::make_shared(m_Buffer, m_BufferLen); @@ -128,7 +128,7 @@ namespace data } // verify - if (!m_Identity->Verify (m_Buffer, leases - m_Buffer, leases)) + if (verifySignature && !m_Identity->Verify (m_Buffer, leases - m_Buffer, leases)) { LogPrint (eLogWarning, "LeaseSet: verification failed"); m_IsValid = false; diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 4c2903aa..9839361e 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -81,7 +81,7 @@ namespace data private: - void ReadFromBuffer (bool readIdentity = true); + void ReadFromBuffer (bool readIdentity = true, bool verifySignature = true); uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // min expiration time private: From 7db2e9dc4af0f5486cb2e556dd663cffc347a0d5 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 25 Jan 2018 10:32:08 -0500 Subject: [PATCH 034/134] don't verify signature twice --- libi2pd/LeaseSet.cpp | 4 ++-- libi2pd/LeaseSet.h | 2 +- libi2pd/NetDb.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 497a562f..f2355930 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -21,7 +21,7 @@ namespace data ReadFromBuffer (); } - void LeaseSet::Update (const uint8_t * buf, size_t len) + void LeaseSet::Update (const uint8_t * buf, size_t len, bool verifySignature) { if (len > m_BufferLen) { @@ -31,7 +31,7 @@ namespace data } memcpy (m_Buffer, buf, len); m_BufferLen = len; - ReadFromBuffer (false, false); // we assume signature is verified already + ReadFromBuffer (false, verifySignature); } void LeaseSet::PopulateLeases () diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 9839361e..391a3b79 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -57,7 +57,7 @@ namespace data LeaseSet (const uint8_t * buf, size_t len, bool storeLeases = true); ~LeaseSet () { delete[] m_Buffer; }; - void Update (const uint8_t * buf, size_t len); + 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 diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index b5e20628..b136dfd5 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -242,7 +242,7 @@ namespace data { if(it->second->GetExpirationTime() < expires) { - it->second->Update (buf, len); + it->second->Update (buf, len, false); // signature is verified already LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); updated = true; } From e1527dc137623029461bd12fb4030e04baf984df Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Jan 2018 14:07:51 -0500 Subject: [PATCH 035/134] update LeaseSet if a tunnel was deleted --- libi2pd/LeaseSet.cpp | 7 ++++--- libi2pd/LeaseSet.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index f2355930..e763912f 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -135,7 +135,7 @@ namespace data } } - uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const + uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len, uint8_t& num) const { if (!m_Identity) return 0; size_t size = m_Identity->GetFullLen (); @@ -143,7 +143,7 @@ namespace data size += 256; // encryption key size += m_Identity->GetSigningPublicKeyLen (); // unused signing key if (size > len) return 0; - uint8_t num = buf[size]; + num = buf[size]; size++; // num if (size + num*LEASE_SIZE > len) return 0; uint64_t timestamp= 0 ; @@ -160,7 +160,8 @@ namespace data bool LeaseSet::IsNewer (const uint8_t * buf, size_t len) const { - return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen); + uint8_t num1, num2; + return ExtractTimestamp (buf, len, num2) > ExtractTimestamp (m_Buffer, m_BufferLen, num1) || num2 < num1; // some lease might be deleted } bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 391a3b79..69b4e2fc 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -82,7 +82,7 @@ namespace data private: void ReadFromBuffer (bool readIdentity = true, bool verifySignature = true); - uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // min expiration time + uint64_t ExtractTimestamp (const uint8_t * buf, size_t len, uint8_t& num) const; // returns max expiration time, num is number of leases private: From 8c2de4973cbf00623fabcef801a90af971b1f9bb Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Jan 2018 14:33:06 -0500 Subject: [PATCH 036/134] rollback --- libi2pd/LeaseSet.cpp | 7 +++---- libi2pd/LeaseSet.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index e763912f..f2355930 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -135,7 +135,7 @@ namespace data } } - uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len, uint8_t& num) const + uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const { if (!m_Identity) return 0; size_t size = m_Identity->GetFullLen (); @@ -143,7 +143,7 @@ namespace data size += 256; // encryption key size += m_Identity->GetSigningPublicKeyLen (); // unused signing key if (size > len) return 0; - num = buf[size]; + uint8_t num = buf[size]; size++; // num if (size + num*LEASE_SIZE > len) return 0; uint64_t timestamp= 0 ; @@ -160,8 +160,7 @@ namespace data bool LeaseSet::IsNewer (const uint8_t * buf, size_t len) const { - uint8_t num1, num2; - return ExtractTimestamp (buf, len, num2) > ExtractTimestamp (m_Buffer, m_BufferLen, num1) || num2 < num1; // some lease might be deleted + return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen); } bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 69b4e2fc..fa24df2f 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -82,7 +82,7 @@ namespace data private: void ReadFromBuffer (bool readIdentity = true, bool verifySignature = true); - uint64_t ExtractTimestamp (const uint8_t * buf, size_t len, uint8_t& num) const; // returns max expiration time, num is number of leases + uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // returns max expiration time private: From dfbefee4771d17da3d95f72ef369fabd9b7649ab Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Jan 2018 14:34:05 -0500 Subject: [PATCH 037/134] graceful shutdown complete if no transit tunnels anymore --- daemon/UnixDaemon.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index 075aa7d8..a9c48fee 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -13,6 +13,7 @@ #include "Config.h" #include "FS.h" #include "Log.h" +#include "Tunnel.h" #include "RouterContext.h" #include "ClientContext.h" @@ -163,7 +164,7 @@ namespace i2p sigaction(SIGABRT, &sa, 0); sigaction(SIGTERM, &sa, 0); sigaction(SIGINT, &sa, 0); - sigaction(SIGPIPE, &sa, 0); + sigaction(SIGPIPE, &sa, 0); return Daemon_Singleton::start(); } @@ -183,7 +184,7 @@ namespace i2p if (gracefulShutdownInterval) { gracefulShutdownInterval--; // - 1 second - if (gracefulShutdownInterval <= 0) + if (gracefulShutdownInterval <= 0 || i2p::tunnel::tunnels.CountTransitTunnels() <= 0) { LogPrint(eLogInfo, "Graceful shutdown"); return; From b00ff43be753687c48a7f835fc2c53a93ede31f4 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Jan 2018 19:52:11 -0500 Subject: [PATCH 038/134] Update README.md --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4d8bf108..40948b34 100644 --- a/README.md +++ b/README.md @@ -70,12 +70,11 @@ See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and Donations --------- -BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY -ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ -DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF +BTC: 3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 -DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y -ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z +ETH: 0x9e5bac70d20d1079ceaa111127f4fb3bccce379d +DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF +ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG License From 6ee279d83ee538ce1afb8bde1a6a6e2d77f10a6f Mon Sep 17 00:00:00 2001 From: Darknet Villain Date: Sat, 27 Jan 2018 10:54:03 -0500 Subject: [PATCH 039/134] [rpm] Merge i2pd-systemd with i2pd package + changelog --- contrib/rpm/i2pd.spec | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index f0f7a9a7..23e0b32d 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -4,6 +4,7 @@ Name: i2pd Version: 2.17.0 Release: %{build_timestamp}git%{?dist} Summary: I2P router written in C++ +Obsoletes: %{name}-systemd License: BSD URL: https://github.com/PurpleI2P/i2pd @@ -23,25 +24,12 @@ BuildRequires: openssl-devel BuildRequires: miniupnpc-devel BuildRequires: systemd-units -%description -C++ implementation of I2P. - - -%package systemd -Summary: Files to run I2P router under systemd -Requires: i2pd Requires: systemd Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd -Obsoletes: %{name}-daemon - -%description systemd +%description C++ implementation of I2P. -This package contains systemd unit file to run i2pd as a system service -using dedicated user's permissions. - - %prep %setup -q @@ -79,22 +67,22 @@ install -d -m 700 %{buildroot}/%{_localstatedir}/log/i2pd ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/%{name}/certificates -%pre systemd +%pre getent group i2pd >/dev/null || %{_sbindir}/groupadd -r i2pd getent passwd i2pd >/dev/null || \ %{_sbindir}/useradd -r -g i2pd -s %{_sbindir}/nologin \ -d %{_sharedstatedir}/i2pd -c 'I2P Service' i2pd -%post systemd +%post %systemd_post i2pd.service -%preun systemd +%preun %systemd_preun i2pd.service -%postun systemd +%postun %systemd_postun_with_restart i2pd.service @@ -103,9 +91,6 @@ getent passwd i2pd >/dev/null || \ %{_sbindir}/i2pd %{_datadir}/i2pd/certificates %config(noreplace) %{_sysconfdir}/i2pd/* - - -%files systemd /%{_unitdir}/i2pd.service %dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd %dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd @@ -113,6 +98,10 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Jan 27 2018 l-n-s - 2.17.0-1 +- Added certificates and default configuration files +- Merge i2pd with i2pd-systemd package + * Mon Dec 04 2017 orignal - 2.17.0 - Added reseed through HTTP and SOCKS proxy - Added show status of client services through web console From 20b4f6b24d9d17c0829f4d1997391debb529cfd8 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 29 Jan 2018 03:47:43 +0300 Subject: [PATCH 040/134] update apparmor profile --- contrib/apparmor/usr.sbin.i2pd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/apparmor/usr.sbin.i2pd b/contrib/apparmor/usr.sbin.i2pd index f0dea839..109ab4b1 100644 --- a/contrib/apparmor/usr.sbin.i2pd +++ b/contrib/apparmor/usr.sbin.i2pd @@ -21,10 +21,11 @@ # path specific (feel free to modify if you have another paths) /etc/i2pd/** r, + /run/i2pd/i2pd.pid rw, /var/lib/i2pd/** rw, - /var/log/i2pd.log w, + /var/log/i2pd/i2pd.log w, /var/run/i2pd/i2pd.pid rw, /usr/sbin/i2pd mr, - + /usr/share/i2pd/** r, } From 6272e15b47830c601f07102a8ff4aed9290707b2 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 29 Jan 2018 04:13:33 +0300 Subject: [PATCH 041/134] add users homedir to profile --- contrib/apparmor/usr.sbin.i2pd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/apparmor/usr.sbin.i2pd b/contrib/apparmor/usr.sbin.i2pd index 109ab4b1..80d73996 100644 --- a/contrib/apparmor/usr.sbin.i2pd +++ b/contrib/apparmor/usr.sbin.i2pd @@ -28,4 +28,6 @@ /usr/sbin/i2pd mr, /usr/share/i2pd/** r, + # user homedir (if started not by init.d or systemd) + owner /home/*/.i2pd/** rw, } From 95d8887ab02bb8ca4ed628efd29cd9b20e257b6c Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 30 Jan 2018 17:30:01 +0300 Subject: [PATCH 042/134] update profile --- contrib/apparmor/usr.sbin.i2pd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/apparmor/usr.sbin.i2pd b/contrib/apparmor/usr.sbin.i2pd index 80d73996..4349e07b 100644 --- a/contrib/apparmor/usr.sbin.i2pd +++ b/contrib/apparmor/usr.sbin.i2pd @@ -29,5 +29,6 @@ /usr/share/i2pd/** r, # user homedir (if started not by init.d or systemd) - owner /home/*/.i2pd/** rw, + owner @{HOME}/.i2pd/ rw, + owner @{HOME}/.i2pd/** rwk, } From 3426906a4ffb09c8bf2bddb42d57c0e4d3a4e8a9 Mon Sep 17 00:00:00 2001 From: Darknet Villain Date: Tue, 30 Jan 2018 10:03:53 -0500 Subject: [PATCH 043/134] [rpm] Fix changelogs to comply with guidelines, add tunconf key to systemd package --- contrib/rpm/i2pd.service | 2 +- contrib/rpm/i2pd.spec | 70 ++++++---------------------------------- 2 files changed, 10 insertions(+), 62 deletions(-) diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service index 89562ff5..ec5949ff 100644 --- a/contrib/rpm/i2pd.service +++ b/contrib/rpm/i2pd.service @@ -8,7 +8,7 @@ Group=i2pd RuntimeDirectory=i2pd RuntimeDirectoryMode=0700 Type=simple -ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service +ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service ExecReload=/bin/kill -HUP $MAINPID PIDFile=/var/run/i2pd/i2pd.pid ### Uncomment, if auto restart needed diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 23e0b32d..2efe8838 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -98,83 +98,31 @@ getent passwd i2pd >/dev/null || \ %changelog -* Sat Jan 27 2018 l-n-s - 2.17.0-1 +* Sat Jan 30 2018 l-n-s - 2.17.0-1 - Added certificates and default configuration files - Merge i2pd with i2pd-systemd package +- Fixed package changelogs to comply with guidelines * Mon Dec 04 2017 orignal - 2.17.0 -- Added reseed through HTTP and SOCKS proxy -- Added show status of client services through web console -- Added change log level through web connsole -- Added transient keys for tunnels -- Added i2p.streaming.initialAckDelay parameter -- Added CRYPTO_TYPE for SAM destination -- Added signature and crypto type for newkeys BOB command -- Changed - correct publication of ECIES destinations -- Changed - disable RSA signatures completely -- Fixed CVE-2017-17066 -- Fixed possible buffer overflow for RSA-4096 -- Fixed shutdown from web console for Windows -- Fixed web console page layout +- update to 2.17.0 * Mon Nov 13 2017 orignal - 2.16.0 -- Added https and "Connect" method for HTTP proxy -- Added outproxy for HTTP proxy -- Added initial support of ECIES crypto -- Added NTCP soft and hard descriptors limits -- Added support full timestamps in logs -- Changed faster implmentation of GOST R 34.11 hash -- Changed reject routers with RSA signtures -- Changed reload config and shudown from Windows GUI -- Changed update tunnels address(destination) without restart -- Fixed BOB crashes if destination is not set -- Fixed correct SAM tunnel name -- Fixed QT GUI issues +- update to 2.16.0 * Thu Aug 17 2017 orignal - 2.15.0 -- Added QT GUI -- Added ability add and remove I2P tunnels without restart -- Added ability to disable SOCKS outproxy option -- Changed strip-out Accept-* hedaers in HTTP proxy -- Changed peer test if nat=false -- Changed separate output of NTCP and SSU sessions in Transports tab -- Fixed handle lines with comments in hosts.txt file for address book -- Fixed run router with empty netdb for testnet -- Fixed skip expired introducers by iexp +- update to 2.15.0 * Thu Jun 01 2017 orignal - 2.14.0 -- Added transit traffic bandwidth limitation -- Added NTCP connections through HTTP and SOCKS proxies -- Added ability to disable address helper for HTTP proxy -- Changed reseed servers list +- update to 2.14.0 * Thu Apr 06 2017 orignal - 2.13.0 -- Added persist local destination's tags -- Added GOST signature types 9 and 10 -- Added exploratory tunnels configuration -- Changed reseed servers list -- Changed inactive NTCP sockets get closed faster -- Changed some EdDSA speed up -- Fixed multiple acceptors for SAM -- Fixed follow on data after STREAM CREATE for SAM -- Fixed memory leaks +- update to 2.13.0 * Tue Feb 14 2017 orignal - 2.12.0 -- Additional HTTP and SOCKS proxy tunnels -- Reseed from ZIP archive -- 'X' bandwidth code -- Reduced memory and file descriptors usage +- update to 2.12.0 * Mon Dec 19 2016 orignal - 2.11.0 -- Full support of zero-hops tunnels -- Tunnel configuration for HTTP and SOCKS proxy -- Websockets support -- Multiple acceptors for SAM destination -- Routing path for UDP tunnels -- Reseed through a floodfill -- Use AVX instructions for DHT and HMAC if applicable -- Fixed UPnP discovery bug, producing excessive CPU usage -- Handle multiple lookups of the same LeaseSet correctly +- update to 2.11.0 * Thu Oct 20 2016 Anatolii Vorona - 2.10.0-3 - add support C7 From 32d300248e0e7fa1f25874890db952e545275364 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 30 Jan 2018 18:09:26 +0300 Subject: [PATCH 044/134] update building stuff --- build/build_mingw.cmd | 1 + debian/compat | 2 +- debian/control | 4 ++-- debian/copyright | 44 +++++++++++++++++++++++++++++++++++----- debian/lintian-overrides | 2 ++ 5 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 debian/lintian-overrides diff --git a/build/build_mingw.cmd b/build/build_mingw.cmd index 6763b63e..cc6a15fa 100644 --- a/build/build_mingw.cmd +++ b/build/build_mingw.cmd @@ -58,6 +58,7 @@ pause exit /b 0 :BUILDING +%xSH% "make clean" >> nul echo Building i2pd %tag% for win%bitness%: echo Build AVX+AESNI... %xSH% "make USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx_aesni.log 2>&1 diff --git a/debian/compat b/debian/compat index ec635144..f11c82a4 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -9 +9 \ No newline at end of file diff --git a/debian/control b/debian/control index 808cdda9..7bd18ebb 100644 --- a/debian/control +++ b/debian/control @@ -2,11 +2,11 @@ Source: i2pd Section: net Priority: optional Maintainer: R4SAS -Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev, libboost-filesystem-dev, libboost-program-options-dev, libminiupnpc-dev, libssl-dev, zlib1g-dev, dh-apparmor +Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev, dh-apparmor Standards-Version: 3.9.6 Homepage: http://i2pd.website/ Vcs-Git: git://github.com/PurpleI2P/i2pd.git -Vcs-Browser: https://github.com/PurpleI2P/i2pd.git +Vcs-Browser: https://github.com/PurpleI2P/i2pd Package: i2pd Architecture: any diff --git a/debian/copyright b/debian/copyright index 6aeefebf..3c513020 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,6 +4,22 @@ Source: https://github.com/PurpleI2P Files: * Copyright: 2013-2017 PurpleI2P +License: BSD-3-clause + +Files: qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistro.aidl + qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl + qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java + qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtApplication.java +Copyright: 2011-2013 BogDan Vatra +License: BSD-2-Clause + +Files: debian/* +Copyright: 2013-2015 Kill Your TV + 2014-2016 hagen + 2016-2017 R4SAS + 2017-2018 Yangfl +License: GPL-2+ + License: BSD-3-clause Copyright (c) 2013-2017, The PurpleI2P Project . @@ -33,11 +49,29 @@ License: BSD-3-clause 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. -Files: debian/* -Copyright: 2016-2017 R4SAS - 2014-2016 hagen - 2013-2015 Kill Your TV -License: GPL-2.0+ +License: BSD-2-Clause + 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 COPYRIGHT HOLDERS AND CONTRIBUTORS + ``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 HOLDERS OR + CONTRIBUTORS 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. + +License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or diff --git a/debian/lintian-overrides b/debian/lintian-overrides new file mode 100644 index 00000000..af3d61c6 --- /dev/null +++ b/debian/lintian-overrides @@ -0,0 +1,2 @@ +# GPL come from debian/ +i2pd: possible-gpl-code-linked-with-openssl \ No newline at end of file From 13d174c09c37a8e5eadf4c57f61390675619030c Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 30 Jan 2018 18:14:54 +0300 Subject: [PATCH 045/134] add tunconf in systemctl service file --- contrib/debian/i2pd.service | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/debian/i2pd.service b/contrib/debian/i2pd.service index 89562ff5..37f26f14 100644 --- a/contrib/debian/i2pd.service +++ b/contrib/debian/i2pd.service @@ -8,7 +8,7 @@ Group=i2pd RuntimeDirectory=i2pd RuntimeDirectoryMode=0700 Type=simple -ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service +ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service ExecReload=/bin/kill -HUP $MAINPID PIDFile=/var/run/i2pd/i2pd.pid ### Uncomment, if auto restart needed @@ -19,7 +19,7 @@ PIDFile=/var/run/i2pd/i2pd.pid KillSignal=SIGINT TimeoutStopSec=10m -# If you have problems with hunging i2pd, you can try enable this +# If you have problems with hanging i2pd, you can try enable this #LimitNOFILE=4096 PrivateDevices=yes From 49014342098c97ab05a3b36de4a0e45be8a8696d Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2018 10:41:35 -0500 Subject: [PATCH 046/134] 2.18.0 --- ChangeLog | 17 +++++++++++++++++ Win32/installer.iss | 2 +- android/AndroidManifest.xml | 2 +- appveyor.yml | 2 +- contrib/rpm/i2pd.spec | 7 +++++-- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- qt/i2pd_qt/android/AndroidManifest.xml | 2 +- 8 files changed, 34 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2468f808..d2bfe7bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,23 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.18.0] - 2018-01-30 +### Added +- Show tunnel nicknames for I2CP destination in WebUI +- Re-create HTTP and SOCKS proxy by tunnel reload +- Graceful shutdown as soon as no more transit tunnels +### Changed +- Regenerate shared local destination by tunnel reload +- Use transient local destination by default if not specified +- Return correct code if pid file can't be created +- Timing and number of attempts for adressbook requests +- Certificates list +### Fixed +- Malformed addressbook subsctiption request +- Build with boost 1.66 +- Few race conditions for SAM +- Check LeaseSet's signature before update + ## [2.17.0] - 2017-12-04 ### Added - Reseed through HTTP and SOCKS proxy diff --git a/Win32/installer.iss b/Win32/installer.iss index 03b0842b..15ce4372 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.17.0" +#define I2Pd_ver "2.18.0" #define I2Pd_Publisher "PurpleI2P" [Setup] diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 1f9d3b91..3ae952b3 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,7 +2,7 @@ diff --git a/appveyor.yml b/appveyor.yml index 6c0470d1..ac632141 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.17.{build} +version: 2.18.{build} pull_requests: do_not_increment_build_number: true branches: diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 2efe8838..316be961 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,7 +1,7 @@ %define build_timestamp %(date +"%Y%m%d") Name: i2pd -Version: 2.17.0 +Version: 2.18.0 Release: %{build_timestamp}git%{?dist} Summary: I2P router written in C++ Obsoletes: %{name}-systemd @@ -98,7 +98,10 @@ getent passwd i2pd >/dev/null || \ %changelog -* Sat Jan 30 2018 l-n-s - 2.17.0-1 +* Tue Jan 30 2018 orignal > - 2.18.0 +- update to 2.18.0 + +* Sat Jan 27 2018 l-n-s - 2.17.0-1 - Added certificates and default configuration files - Merge i2pd with i2pd-systemd package - Fixed package changelogs to comply with guidelines diff --git a/debian/changelog b/debian/changelog index 94105535..5f298646 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.18.0-1) unstable; urgency=low + + * updated to version 2.18.0/0.9.38 + + -- orignal Tue, 30 Jan 2018 16:00:00 +0000 + i2pd (2.17.0-1) unstable; urgency=low * updated to version 2.17.0/0.9.32 diff --git a/libi2pd/version.h b/libi2pd/version.h index b443ea6f..36e7eb6e 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 17 +#define I2PD_VERSION_MINOR 18 #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 32 +#define I2P_VERSION_MICRO 33 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml index 20061963..56b37e6a 100644 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ b/qt/i2pd_qt/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + From b6e75e9c5ad6c981419ca376625d78de7b4c0355 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2018 11:14:29 -0500 Subject: [PATCH 047/134] Update changelog --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 5f298646..afddc797 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,6 @@ i2pd (2.18.0-1) unstable; urgency=low - * updated to version 2.18.0/0.9.38 + * updated to version 2.18.0/0.9.33 -- orignal Tue, 30 Jan 2018 16:00:00 +0000 From fca2693488823f5b02f770eb2fa08e1ed9461327 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 1 Feb 2018 01:12:06 +0300 Subject: [PATCH 048/134] add centos/fedora build status --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 40948b34..67b82ceb 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ Build instructions: * GNU/Linux x86/x64 - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) * Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd) * Mac OS X - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) +* CentOS / Fedora - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/) * FreeBSD * Android * iOS From 180730f9cf3138f347f764e598a5880652197d25 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 1 Feb 2018 19:37:38 +0300 Subject: [PATCH 049/134] fix rpm spec's (#1084) * added spec for git package * fixed double slashes * changed versioning for stable builds --- contrib/rpm/i2pd-git.spec | 103 ++++++++++++++++++++++++++++++++++++++ contrib/rpm/i2pd.spec | 22 ++++---- 2 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 contrib/rpm/i2pd-git.spec diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec new file mode 100644 index 00000000..2bde7289 --- /dev/null +++ b/contrib/rpm/i2pd-git.spec @@ -0,0 +1,103 @@ +%define git_hash %(git rev-parse HEAD | cut -c -7) + +Name: i2pd-git +Version: 2.18.0 +Release: %{git_hash}.git%{?dist} +Summary: I2P router written in C++ +Obsoletes: %{name}-systemd +Conflicts: i2pd + +License: BSD +URL: https://github.com/PurpleI2P/i2pd +Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz + +%if 0%{?rhel} == 7 +BuildRequires: cmake3 +%else +BuildRequires: cmake +%endif + +BuildRequires: chrpath +BuildRequires: gcc-c++ +BuildRequires: zlib-devel +BuildRequires: boost-devel +BuildRequires: openssl-devel +BuildRequires: miniupnpc-devel +BuildRequires: systemd-units + +Requires: systemd +Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd + +%description +C++ implementation of I2P. + +%prep +%setup -q + + +%build +cd build +%if 0%{?rhel} == 7 +%cmake3 \ + -DWITH_LIBRARY=OFF \ + -DWITH_UPNP=ON \ + -DWITH_HARDENING=ON \ + -DBUILD_SHARED_LIBS:BOOL=OFF +%else +%cmake \ + -DWITH_LIBRARY=OFF \ + -DWITH_UPNP=ON \ + -DWITH_HARDENING=ON \ + -DBUILD_SHARED_LIBS:BOOL=OFF +%endif + +make %{?_smp_mflags} + + +%install +cd build +chrpath -d i2pd +install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd +install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf +install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf +install -d -m 755 %{buildroot}%{_datadir}/i2pd +%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates +install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service +install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd +install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd +ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates + + +%pre +getent group i2pd >/dev/null || %{_sbindir}/groupadd -r i2pd +getent passwd i2pd >/dev/null || \ + %{_sbindir}/useradd -r -g i2pd -s %{_sbindir}/nologin \ + -d %{_sharedstatedir}/i2pd -c 'I2P Service' i2pd + + +%post +%systemd_post i2pd.service + + +%preun +%systemd_preun i2pd.service + + +%postun +%systemd_postun_with_restart i2pd.service + + +%files +%doc LICENSE README.md +%{_sbindir}/i2pd +%{_datadir}/i2pd/certificates +%config(noreplace) %{_sysconfdir}/i2pd/* +/%{_unitdir}/i2pd.service +%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd +%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd +%{_sharedstatedir}/i2pd/certificates + + +%changelog +* Thu Feb 01 2018 r4sas - 2.18.0 +- Initial i2pd-git based on i2pd 2.18.0-1 spec \ No newline at end of file diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 316be961..ba4e3890 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,10 +1,9 @@ -%define build_timestamp %(date +"%Y%m%d") - Name: i2pd Version: 2.18.0 -Release: %{build_timestamp}git%{?dist} +Release: 1%{?dist} Summary: I2P router written in C++ Obsoletes: %{name}-systemd +Conflicts: i2pd-git License: BSD URL: https://github.com/PurpleI2P/i2pd @@ -59,12 +58,12 @@ chrpath -d i2pd install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf -install -d -m 755 %{buildroot}/%{_datadir}/i2pd +install -d -m 755 %{buildroot}%{_datadir}/i2pd %{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates -install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}/%{_unitdir}/i2pd.service -install -d -m 700 %{buildroot}/%{_sharedstatedir}/i2pd -install -d -m 700 %{buildroot}/%{_localstatedir}/log/i2pd -ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/%{name}/certificates +install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service +install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd +install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd +ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates %pre @@ -98,7 +97,12 @@ getent passwd i2pd >/dev/null || \ %changelog -* Tue Jan 30 2018 orignal > - 2.18.0 +* Thu Feb 01 2018 r4sas - 2.18.0-1 +- Added to conflicts i2pd-git package +- Fixed release versioning +- Fixed paths with double slashes + +* Tue Jan 30 2018 orignal - 2.18.0 - update to 2.18.0 * Sat Jan 27 2018 l-n-s - 2.17.0-1 From 80567312ed83c0221b6adac9f61919d312f4149b Mon Sep 17 00:00:00 2001 From: BOPOHA Date: Thu, 1 Feb 2018 22:11:14 +0100 Subject: [PATCH 050/134] i2pd.spec delete obsoletes tag https://github.com/PurpleI2P/i2pd/pull/1084#issuecomment-362215861 ``` Resolving Dependencies --> Running transaction check ---> Package i2pd.x86_64 0:2.17.0-20171206git.el7.centos will be updated ---> Package i2pd.x86_64 0:2.18.0-1.el7.centos will be obsoleting ---> Package i2pd-systemd.x86_64 0:2.17.0-20171206git.el7.centos will be obsoleted --> Finished Dependency Resolution Dependencies Resolved ========================================================================== Package Arch Version Repository Size ========================================================================== Installing: i2pd x86_64 2.18.0-1.el7.centos vorona-i2pd 915 k replacing i2pd-systemd.x86_64 2.17.0-20171206git.el7.centos Transaction Summary ========================================================================== Install 1 Package Total download size: 915 k Is this ok [y/d/N]: ``` @l-n-s thx, obsoletes tag is unneeded in next release) --- contrib/rpm/i2pd.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index ba4e3890..469740ce 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -2,7 +2,6 @@ Name: i2pd Version: 2.18.0 Release: 1%{?dist} Summary: I2P router written in C++ -Obsoletes: %{name}-systemd Conflicts: i2pd-git License: BSD From ce57a130fc885d342f8e6f1354d3b9f59af26bc5 Mon Sep 17 00:00:00 2001 From: BOPOHA Date: Thu, 1 Feb 2018 23:21:20 +0100 Subject: [PATCH 051/134] systemd issue in centos 7 Not working pre-create pid-file dir (/run/i2pd). It fixed with one of this ways: > PermissionsStartOnly=True or > ExecStartPre=/bin/mkdir -p -m 0700 /var/run/i2pd > ExecStartPre=/bin/chown i2pd: /var/run/i2pd First way is prefer because RuntimeDirectory's options already used. --- contrib/rpm/i2pd.service | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service index ec5949ff..8a9c9584 100644 --- a/contrib/rpm/i2pd.service +++ b/contrib/rpm/i2pd.service @@ -5,6 +5,7 @@ After=network.target [Service] User=i2pd Group=i2pd +PermissionsStartOnly=True RuntimeDirectory=i2pd RuntimeDirectoryMode=0700 Type=simple From fbb99911285c46931e543409ac6149f86141efdb Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 2 Feb 2018 10:35:07 +0300 Subject: [PATCH 052/134] remove obsoletes tag for rpm git package --- contrib/rpm/i2pd-git.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 2bde7289..b2be3b9f 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -4,7 +4,6 @@ Name: i2pd-git Version: 2.18.0 Release: %{git_hash}.git%{?dist} Summary: I2P router written in C++ -Obsoletes: %{name}-systemd Conflicts: i2pd License: BSD From 4f84d687e413f5945bd12861187ea5af9dd950ec Mon Sep 17 00:00:00 2001 From: yangfl Date: Sat, 3 Feb 2018 02:27:22 +0800 Subject: [PATCH 053/134] add endian detection for glibc --- libi2pd/I2PEndian.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/I2PEndian.h b/libi2pd/I2PEndian.h index e5271233..d08e90cb 100644 --- a/libi2pd/I2PEndian.h +++ b/libi2pd/I2PEndian.h @@ -5,7 +5,7 @@ #if defined(__FreeBSD__) #include -#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) +#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__) #include #elif defined(__APPLE__) && defined(__MACH__) From 319d748639e870d34700ebcdc9c44a9c7d65a932 Mon Sep 17 00:00:00 2001 From: yangfl Date: Sat, 3 Feb 2018 02:29:28 +0800 Subject: [PATCH 054/134] i2pd.service: do not block system shutdown for 10 min --- contrib/debian/i2pd.service | 28 +--------------------------- contrib/i2pd.service | 29 +++++++++++++++++++++++++++++ contrib/rpm/i2pd.service | 29 +---------------------------- 3 files changed, 31 insertions(+), 55 deletions(-) mode change 100644 => 120000 contrib/debian/i2pd.service create mode 100644 contrib/i2pd.service mode change 100644 => 120000 contrib/rpm/i2pd.service diff --git a/contrib/debian/i2pd.service b/contrib/debian/i2pd.service deleted file mode 100644 index 37f26f14..00000000 --- a/contrib/debian/i2pd.service +++ /dev/null @@ -1,27 +0,0 @@ -[Unit] -Description=I2P Router written in C++ -After=network.target - -[Service] -User=i2pd -Group=i2pd -RuntimeDirectory=i2pd -RuntimeDirectoryMode=0700 -Type=simple -ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service -ExecReload=/bin/kill -HUP $MAINPID -PIDFile=/var/run/i2pd/i2pd.pid -### Uncomment, if auto restart needed -#Restart=on-failure - -### Use SIGINT for graceful stop daemon. -# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die. -KillSignal=SIGINT -TimeoutStopSec=10m - -# If you have problems with hanging i2pd, you can try enable this -#LimitNOFILE=4096 -PrivateDevices=yes - -[Install] -WantedBy=multi-user.target diff --git a/contrib/debian/i2pd.service b/contrib/debian/i2pd.service new file mode 120000 index 00000000..ca477e3b --- /dev/null +++ b/contrib/debian/i2pd.service @@ -0,0 +1 @@ +../i2pd.service \ No newline at end of file diff --git a/contrib/i2pd.service b/contrib/i2pd.service new file mode 100644 index 00000000..5ed31d41 --- /dev/null +++ b/contrib/i2pd.service @@ -0,0 +1,29 @@ +[Unit] +Description=I2P Router written in C++ +Documentation=man:i2pd(1) https://i2pd.readthedocs.io/en/latest/ +After=network.target + +[Service] +User=i2pd +Group=i2pd +RuntimeDirectory=i2pd +RuntimeDirectoryMode=0700 +Type=simple +ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service +ExecReload=/bin/kill -HUP $MAINPID +PIDFile=/var/run/i2pd/i2pd.pid +### Uncomment, if auto restart needed +#Restart=on-failure + +KillSignal=SIGQUIT +# If you have the patience waiting 10 min on restarting/stopping it, uncomment this. +# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die. +#KillSignal=SIGINT +#TimeoutStopSec=10m + +# If you have problems with hanging i2pd, you can try enable this +#LimitNOFILE=4096 +PrivateDevices=yes + +[Install] +WantedBy=multi-user.target diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service deleted file mode 100644 index 8a9c9584..00000000 --- a/contrib/rpm/i2pd.service +++ /dev/null @@ -1,28 +0,0 @@ -[Unit] -Description=I2P Router written in C++ -After=network.target - -[Service] -User=i2pd -Group=i2pd -PermissionsStartOnly=True -RuntimeDirectory=i2pd -RuntimeDirectoryMode=0700 -Type=simple -ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service -ExecReload=/bin/kill -HUP $MAINPID -PIDFile=/var/run/i2pd/i2pd.pid -### Uncomment, if auto restart needed -#Restart=on-failure - -### Use SIGINT for graceful stop daemon. -# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die. -KillSignal=SIGINT -TimeoutStopSec=10m - -# If you have problems with hunging i2pd, you can try enable this -#LimitNOFILE=4096 -PrivateDevices=yes - -[Install] -WantedBy=multi-user.target diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service new file mode 120000 index 00000000..ca477e3b --- /dev/null +++ b/contrib/rpm/i2pd.service @@ -0,0 +1 @@ +../i2pd.service \ No newline at end of file From 87f2eefd35585dbfab375cf62b9e16b670ebecf1 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sat, 3 Feb 2018 19:55:32 +0800 Subject: [PATCH 055/134] quit features replaced by stop --- .../org/purplei2p/i2pd/DaemonSingleton.java | 6 +- .../org/purplei2p/i2pd/ForegroundService.java | 2 +- .../i2pd/{I2PD.java => I2PDActivity.java} | 56 ++++++++----------- 3 files changed, 29 insertions(+), 35 deletions(-) rename android/src/org/purplei2p/i2pd/{I2PD.java => I2PDActivity.java} (85%) diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index 65afd0f5..64568f83 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -32,7 +32,7 @@ public class DaemonSingleton { private boolean startedOkay; - public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress}; + public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress,stopped}; private State state = State.uninitialized; @@ -121,6 +121,10 @@ public class DaemonSingleton { if(isStartedOkay()){ try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);} setStartedOkay(false); + synchronized (DaemonSingleton.this) { + state = State.stopped; + fireStateUpdate(); + } } } } diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index bfd650c8..74761b07 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -75,7 +75,7 @@ public class ForegroundService extends Service { // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - new Intent(this, I2PD.class), 0); + new Intent(this, I2PDActivity.class), 0); // Set the info for the views that show in the notification panel. Notification notification = new Notification.Builder(this) diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java similarity index 85% rename from android/src/org/purplei2p/i2pd/I2PD.java rename to android/src/org/purplei2p/i2pd/I2PDActivity.java index a2494b2b..36e992b3 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -5,13 +5,11 @@ import java.io.StringWriter; import java.util.Timer; import java.util.TimerTask; -import android.annotation.SuppressLint; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.util.Log; @@ -20,7 +18,7 @@ import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; -public class I2PD extends Activity { +public class I2PDActivity extends Activity { private static final String TAG = "i2pd"; private TextView textView; @@ -81,11 +79,11 @@ public class I2PD extends Activity { gracefulQuitTimer.cancel(); setGracefulQuitTimer(null); } - try{ - doUnbindService(); - }catch(Throwable tr){ - Log.e(TAG, "", tr); - } +// try{ +// doUnbindService(); +// }catch(Throwable tr){ +// Log.e(TAG, "", tr); +// } } private CharSequence throwableToString(Throwable tr) { @@ -126,7 +124,8 @@ public class I2PD extends Activity { private boolean mIsBound; - private void doBindService() { + private synchronized void doBindService() { + if(mIsBound)return; // 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 @@ -159,48 +158,39 @@ public class I2PD extends Activity { int id = item.getItemId(); switch(id){ - case R.id.action_quit: - quit(); + case R.id.action_stop: + i2pdStop(); return true; - case R.id.action_graceful_quit: - gracefulQuit(); + case R.id.action_graceful_stop: + i2pdGracefulStop(); return true; } return super.onOptionsItemSelected(item); } - @SuppressLint("NewApi") - private void quit() { - try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - finishAndRemoveTask(); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - finishAffinity(); - } else { - //moveTaskToBack(true); - finish(); - } - }catch (Throwable tr) { - Log.e(TAG, "", tr); - } + private void i2pdStop() { try{ daemon.stopDaemon(); }catch (Throwable tr) { Log.e(TAG, "", tr); } - System.exit(0); } private Timer gracefulQuitTimer; private final Object gracefulQuitTimerLock = new Object(); - private void gracefulQuit() { + private synchronized void i2pdGracefulStop() { + if(daemon.getState()==DaemonSingleton.State.stopped){ + Toast.makeText(this, R.string.already_stopped, + Toast.LENGTH_SHORT).show(); + return; + } if(getGracefulQuitTimer()!=null){ - Toast.makeText(this, R.string.graceful_quit_is_already_in_progress, + Toast.makeText(this, R.string.graceful_stop_is_already_in_progress, Toast.LENGTH_SHORT).show(); return; } - Toast.makeText(this, R.string.graceful_quit_is_in_progress, + Toast.makeText(this, R.string.graceful_stop_is_in_progress, Toast.LENGTH_SHORT).show(); new Thread(new Runnable(){ @@ -216,12 +206,12 @@ public class I2PD extends Activity { @Override public void run() { - quit(); + i2pdStop(); } }, 10*60*1000/*milliseconds*/); }else{ - quit(); + i2pdStop(); } } catch(Throwable tr) { Log.e(TAG,"",tr); From 1d0791dbf53f84881b8478f6265aa33b588e7014 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sat, 3 Feb 2018 19:56:17 +0800 Subject: [PATCH 056/134] quit features replaced by stop - more --- android/res/menu/options_main.xml | 10 +++++----- android/res/values/strings.xml | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/android/res/menu/options_main.xml b/android/res/menu/options_main.xml index f66caa2a..aef67c51 100644 --- a/android/res/menu/options_main.xml +++ b/android/res/menu/options_main.xml @@ -2,15 +2,15 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - tools:context=".I2PD"> + tools:context=".I2PDActivity"> diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 0b8bef38..c147a808 100755 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -4,8 +4,9 @@ i2pd started i2pd service started i2pd service stopped - Quit - Graceful Quit - Graceful quit is already in progress - Graceful quit is in progress + Stop + Graceful Stop + Graceful stop is already in progress + Graceful stop is in progress + Already stopped From b88b82a85c9a22d668c84f3fd4ce4509722e9d8d Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sat, 3 Feb 2018 19:57:21 +0800 Subject: [PATCH 057/134] quit features replaced by stop - more 2 --- android/AndroidManifest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 3ae952b3..95fff3ff 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,20 +1,20 @@ + android:versionName="2.18.0"> - + - From eb3f703b46e895169e7eda5dcd5a677f00b265ef Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sat, 3 Feb 2018 19:58:09 +0800 Subject: [PATCH 058/134] gradle upgraded; i2pd version name updated --- android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index a88403fd..821dbc16 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -4,7 +4,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.2' + classpath 'com.android.tools.build:gradle:2.3.3' } } @@ -18,7 +18,7 @@ android { targetSdkVersion 25 minSdkVersion 14 versionCode 1 - versionName "2.17.1" + versionName "2.18.0" } sourceSets { main { From 21c35f770b26ebf00f94365769bab74753fa06d1 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Feb 2018 13:46:22 -0500 Subject: [PATCH 059/134] fix federoa rawhide build with gcc 8 --- libi2pd/TunnelBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h index 8b7fb408..97fb2b51 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -59,7 +59,7 @@ namespace tunnel struct TunnelCreationTimeCmp { - bool operator() (std::shared_ptr t1, std::shared_ptr t2) const + bool operator() (const std::shared_ptr & t1, const std::shared_ptr & t2) const { if (t1->GetCreationTime () != t2->GetCreationTime ()) return t1->GetCreationTime () > t2->GetCreationTime (); From 4af0caa50639c9c080034b2ea8239eb7e06f0ba3 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 5 Feb 2018 05:07:26 +0300 Subject: [PATCH 060/134] fix build on GCC 8.0.1 https://bugzilla.redhat.com/show_bug.cgi?id=1541688 --- libi2pd/TunnelBase.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h index 97fb2b51..dce3debe 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -59,7 +59,8 @@ namespace tunnel struct TunnelCreationTimeCmp { - bool operator() (const std::shared_ptr & t1, const std::shared_ptr & t2) const + template + bool operator() (const std::shared_ptr & t1, const std::shared_ptr & t2) const { if (t1->GetCreationTime () != t2->GetCreationTime ()) return t1->GetCreationTime () > t2->GetCreationTime (); From f3488be7afcb261502fa95639894193e5204e3a8 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 5 Feb 2018 05:52:12 +0300 Subject: [PATCH 061/134] update rpm, increase release version for Fedora and CentOS --- contrib/rpm/i2pd-git.spec | 2 +- contrib/rpm/i2pd.spec | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index b2be3b9f..6e02779d 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -2,7 +2,7 @@ Name: i2pd-git Version: 2.18.0 -Release: %{git_hash}.git%{?dist} +Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 469740ce..22c31192 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,6 +1,6 @@ Name: i2pd Version: 2.18.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -96,6 +96,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Feb 05 2018 r4sas - 2.18.0-2 +- Fixed blocking system shutdown for 10 minutes (#1089) + * Thu Feb 01 2018 r4sas - 2.18.0-1 - Added to conflicts i2pd-git package - Fixed release versioning From 5a657cff892fd8075a77d32556f5d1999fd6bf7a Mon Sep 17 00:00:00 2001 From: l-n-s Date: Sun, 4 Feb 2018 23:44:49 -0500 Subject: [PATCH 062/134] Remove broken Dockerfile and it's entrypoint --- Dockerfile | 54 --------------------------------------------------- entrypoint.sh | 24 ----------------------- 2 files changed, 78 deletions(-) delete mode 100644 Dockerfile delete mode 100644 entrypoint.sh diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 4931a709..00000000 --- a/Dockerfile +++ /dev/null @@ -1,54 +0,0 @@ -FROM alpine:latest - -MAINTAINER Mikal Villa - -ENV GIT_BRANCH="master" -ENV I2PD_PREFIX="/opt/i2pd-${GIT_BRANCH}" -ENV PATH=${I2PD_PREFIX}/bin:$PATH - -ENV GOSU_VERSION=1.7 -ENV GOSU_SHASUM="34049cfc713e8b74b90d6de49690fa601dc040021980812b2f1f691534be8a50 /usr/local/bin/gosu" - -RUN mkdir /user && adduser -S -h /user i2pd && chown -R i2pd:nobody /user - - -# -# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the -# image under 20mb we need to remove all the build dependencies in the same "RUN" / layer. -# - -# 1. install deps, clone and build. -# 2. strip binaries. -# 3. Purge all dependencies and other unrelated packages, including build directory. -RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boost-dev build-base openssl-dev openssl git \ - && mkdir -p /tmp/build \ - && cd /tmp/build && git clone -b ${GIT_BRANCH} https://github.com/PurpleI2P/i2pd.git \ - && cd i2pd \ - && make -j4 \ - && mkdir -p ${I2PD_PREFIX}/bin \ - && mv i2pd ${I2PD_PREFIX}/bin/ \ - && cd ${I2PD_PREFIX}/bin \ - && strip i2pd \ - && rm -fr /tmp/build && apk --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \ - boost-python3 python3 gdbm boost-unit_test_framework boost-python linux-headers boost-prg_exec_monitor \ - boost-serialization boost-signals boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre \ - libtool g++ gcc pkgconfig - -# 2. Adding required libraries to run i2pd to ensure it will run. -RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl musl-utils libstdc++ - -# Gosu is a replacement for su/sudo in docker and not a backdoor :) See https://github.com/tianon/gosu -RUN wget -O /usr/local/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64 \ - && echo "${GOSU_SHASUM}" | sha256sum -c && chmod +x /usr/local/bin/gosu - -COPY entrypoint.sh /entrypoint.sh - -RUN chmod a+x /entrypoint.sh -RUN echo "export PATH=${PATH}" >> /etc/profile - -VOLUME [ "/var/lib/i2pd" ] - -EXPOSE 7070 4444 4447 7656 2827 7654 7650 - -ENTRYPOINT [ "/entrypoint.sh" ] - diff --git a/entrypoint.sh b/entrypoint.sh deleted file mode 100644 index 24a415aa..00000000 --- a/entrypoint.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -ARGS="" -if [ "${ENABLE_IPV6}" != "" ]; then - ARGS="${ARGS} –ipv6" -fi - -if [ "${LOGLEVEL}" != "" ]; then - ARGS="${ARGS} –loglevel=${LOGLEVEL}" -fi - -if [ "${ENABLE_AUTH}" != "" ]; then - ARGS="${ARGS} –http.auth" -fi - - -# To make ports exposeable -DEFAULT_ARGS=" –http.address=0.0.0.0 –httpproxy.address=0.0.0.0 -socksproxy.address=0.0.0.0 –sam.address=0.0.0.0 –bob.address=0.0.0.0 –i2cp.address=0.0.0.0 –i2pcontrol.port=0.0.0.0 –upnp.enabled=false -service " - -mkdir -p /var/lib/i2pd && chown -R i2pd:nobody /var/lib/i2pd && chmod u+rw /var/lib/i2pd - -gosu i2pd i2pd $DEFAULT_ARGS $ARGS - - From e77037c2b83d1dc446bf2130effa0861f75d58e6 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 5 Feb 2018 11:13:25 -0500 Subject: [PATCH 063/134] fixed warning --- libi2pd/TunnelBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h index dce3debe..53782ae3 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -66,7 +66,7 @@ namespace tunnel return t1->GetCreationTime () > t2->GetCreationTime (); else return t1 < t2; - }; + } }; } } From 62d9a47c3d60cb5cf224f0159135ef02c3568cc3 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 18:23:05 +0800 Subject: [PATCH 064/134] android work 1 --- .../org/purplei2p/i2pd/DaemonSingleton.java | 58 ++++++-------- .../org/purplei2p/i2pd/ForegroundService.java | 8 +- .../src/org/purplei2p/i2pd/I2PDActivity.java | 79 +++++++++---------- 3 files changed, 63 insertions(+), 82 deletions(-) diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index 64568f83..cba29a18 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -8,8 +8,8 @@ import android.util.Log; public class DaemonSingleton { private static final String TAG="i2pd"; private static final DaemonSingleton instance = new DaemonSingleton(); - public static interface StateUpdateListener { void daemonStateUpdate(); } - private final Set stateUpdateListeners = new HashSet(); + public interface StateUpdateListener { void daemonStateUpdate(); } + private final Set stateUpdateListeners = new HashSet<>(); public static DaemonSingleton getInstance() { return instance; @@ -18,63 +18,54 @@ public class DaemonSingleton { public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); } public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); } + private synchronized void setState(State newState) { + if(newState==null)throw new NullPointerException(); + State oldState = state; + if(oldState==null)throw new NullPointerException(); + if(oldState.equals(newState))return; + state=newState; + fireStateUpdate1(); + } public synchronized void stopAcceptingTunnels() { if(isStartedOkay()){ - state=State.gracefulShutdownInProgress; - fireStateUpdate(); + setState(State.gracefulShutdownInProgress); I2PD_JNI.stopAcceptingTunnels(); } } - public void onNetworkStateChange(boolean isConnected) { - I2PD_JNI.onNetworkStateChanged(isConnected); - } + private volatile boolean startedOkay; - private boolean startedOkay; + public enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress,stopped}; - public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress,stopped}; - - private State state = State.uninitialized; + private volatile State state = State.uninitialized; public State getState() { return state; } - public synchronized void start() { - if(state != State.uninitialized)return; - state = State.starting; - fireStateUpdate(); + { + setState(State.starting); new Thread(new Runnable(){ @Override public void run() { try { I2PD_JNI.loadLibraries(); - synchronized (DaemonSingleton.this) { - state = State.jniLibraryLoaded; - fireStateUpdate(); - } + setState(State.jniLibraryLoaded); } catch (Throwable tr) { lastThrowable=tr; - synchronized (DaemonSingleton.this) { - state = State.startFailed; - fireStateUpdate(); - } + setState(State.startFailed); return; } try { synchronized (DaemonSingleton.this) { daemonStartResult = I2PD_JNI.startDaemon(); if("ok".equals(daemonStartResult)){ - state=State.startedOkay; + setState(State.startedOkay); setStartedOkay(true); - }else state=State.startFailed; - fireStateUpdate(); + }else setState(State.startFailed); } } catch (Throwable tr) { lastThrowable=tr; - synchronized (DaemonSingleton.this) { - state = State.startFailed; - fireStateUpdate(); - } + setState(State.startFailed); return; } } @@ -84,7 +75,7 @@ public class DaemonSingleton { private Throwable lastThrowable; private String daemonStartResult="N/A"; - private synchronized void fireStateUpdate() { + private void fireStateUpdate1() { Log.i(TAG, "daemon state change: "+state); for(StateUpdateListener listener : stateUpdateListeners) { try { @@ -121,10 +112,7 @@ public class DaemonSingleton { if(isStartedOkay()){ try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);} setStartedOkay(false); - synchronized (DaemonSingleton.this) { - state = State.stopped; - fireStateUpdate(); - } + setState(State.stopped); } } } diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index 74761b07..07254439 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -34,15 +34,13 @@ public class ForegroundService extends Service { // Display a notification about us starting. We put an icon in the status bar. showNotification(); - daemon.start(); // Tell the user we started. - Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); +// 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); - daemon.start(); return START_STICKY; } @@ -54,7 +52,7 @@ public class ForegroundService extends Service { stopForeground(true); // Tell the user we stopped. - Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show(); +// Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show(); } @Override @@ -92,6 +90,6 @@ public class ForegroundService extends Service { startForeground(NOTIFICATION, notification); } - private 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 36e992b3..64316112 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -23,9 +23,9 @@ public class I2PDActivity extends Activity { private TextView textView; - private final DaemonSingleton daemon = DaemonSingleton.getInstance(); + private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); - private DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = + private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() { @Override @@ -58,7 +58,7 @@ public class I2PDActivity extends Activity { textView = new TextView(this); setContentView(textView); - DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); + daemon.addStateChangeListener(daemonStateUpdatedListener); daemonStateUpdatedListener.daemonStateUpdate(); //set the app be foreground @@ -68,22 +68,18 @@ public class I2PDActivity extends Activity { @Override protected void onDestroy() { super.onDestroy(); - localDestroy(); - } - - private void localDestroy() { - textView = null; - DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener); - Timer gracefulQuitTimer = getGracefulQuitTimer(); - if(gracefulQuitTimer!=null) { - gracefulQuitTimer.cancel(); - setGracefulQuitTimer(null); + textView = null; + daemon.removeStateChangeListener(daemonStateUpdatedListener); + Timer gracefulQuitTimer = getGracefulQuitTimer(); + if(gracefulQuitTimer!=null) { + gracefulQuitTimer.cancel(); + setGracefulQuitTimer(null); + } + try{ + doUnbindService(); + }catch(Throwable tr){ + Log.e(TAG, "", tr); } -// try{ -// doUnbindService(); -// }catch(Throwable tr){ -// Log.e(TAG, "", tr); -// } } private CharSequence throwableToString(Throwable tr) { @@ -122,24 +118,27 @@ public class I2PDActivity extends Activity { }; - private boolean mIsBound; + private static volatile boolean mIsBound; - private synchronized void doBindService() { - if(mIsBound)return; - // 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, - ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE); - mIsBound = true; + private void doBindService() { + synchronized (I2PDActivity.class) { + if (mIsBound) return; + // 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, ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE); + mIsBound = true; + } } private void doUnbindService() { - if (mIsBound) { - // Detach our existing connection. - unbindService(mConnection); - mIsBound = false; + synchronized (I2PDActivity.class) { + if (mIsBound) { + // Detach our existing connection. + unbindService(mConnection); + mIsBound = false; + } } } @@ -177,9 +176,9 @@ public class I2PDActivity extends Activity { } } - private Timer gracefulQuitTimer; - private final Object gracefulQuitTimerLock = new Object(); - private synchronized void i2pdGracefulStop() { + private volatile Timer gracefulQuitTimer; + + private void i2pdGracefulStop() { if(daemon.getState()==DaemonSingleton.State.stopped){ Toast.makeText(this, R.string.already_stopped, Toast.LENGTH_SHORT).show(); @@ -218,18 +217,14 @@ public class I2PDActivity extends Activity { } } - },"gracQuitInit").start(); + },"gracInit").start(); } private Timer getGracefulQuitTimer() { - synchronized (gracefulQuitTimerLock) { - return gracefulQuitTimer; - } + return gracefulQuitTimer; } private void setGracefulQuitTimer(Timer gracefulQuitTimer) { - synchronized (gracefulQuitTimerLock) { - this.gracefulQuitTimer = gracefulQuitTimer; - } + this.gracefulQuitTimer = gracefulQuitTimer; } } From 0994211a48a77329282f0deeec4e37b67ffcd120 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 18:24:51 +0800 Subject: [PATCH 065/134] android gitignore --- android/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/.gitignore b/android/.gitignore index d9fa5a57..efb83e7b 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,4 +5,5 @@ ant.properties local.properties build.sh bin -log* \ No newline at end of file +log* +.gradle android.iml build gradle gradlew gradlew.bat From 1b56d66fc80147e0e91b6774ef63bfa81e05aa48 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 18:25:36 +0800 Subject: [PATCH 066/134] android gitignore --- android/.gitignore | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/android/.gitignore b/android/.gitignore index efb83e7b..90cd315e 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -6,4 +6,10 @@ local.properties build.sh bin log* -.gradle android.iml build gradle gradlew gradlew.bat +.gradle +android.iml +build +gradle +gradlew +gradlew.bat + From 33735b343d1205d5d4ead28d537146ba66e94334 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 19:24:43 +0800 Subject: [PATCH 067/134] fixes 1094; fixes grac stop --- android/res/values/strings.xml | 11 ++- .../org/purplei2p/i2pd/DaemonSingleton.java | 20 ++++- .../org/purplei2p/i2pd/ForegroundService.java | 40 ++++++++-- .../src/org/purplei2p/i2pd/I2PDActivity.java | 73 ++++++++++++++----- 4 files changed, 118 insertions(+), 26 deletions(-) diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index c147a808..1421b261 100755 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -1,12 +1,17 @@ i2pd - i2pd started - i2pd service started - i2pd service stopped Stop 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 + remaining diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index cba29a18..4f3e62f7 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -35,7 +35,25 @@ public class DaemonSingleton { private volatile boolean startedOkay; - public enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress,stopped}; + 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); + + State(int statusStringResourceId) { + this.statusStringResourceId = statusStringResourceId; + } + + private final int 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 07254439..6116b982 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -11,11 +11,32 @@ import android.util.Log; import android.widget.Toast; public class ForegroundService extends Service { + private static final String TAG="FgService"; + + private volatile boolean shown; + + 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); + } + } + }; + + private NotificationManager notificationManager; // Unique Identification Number for the Notification. // We use it on Notification start, and to cancel it. - private int NOTIFICATION = R.string.i2pd_started; + private int NOTIFICATION = 1; /** * Class for clients to access. Because we know this service always @@ -32,8 +53,10 @@ public class ForegroundService extends Service { public void onCreate() { notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - // Display a notification about us starting. We put an icon in the status bar. - showNotification(); + 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(); } @@ -46,6 +69,11 @@ public class ForegroundService extends Service { @Override public void onDestroy() { + DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener); + cancelNotification(); + } + + private synchronized void cancelNotification() { // Cancel the persistent notification. notificationManager.cancel(NOTIFICATION); @@ -53,6 +81,7 @@ public class ForegroundService extends Service { // Tell the user we stopped. // Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show(); + shown=false; } @Override @@ -67,9 +96,9 @@ public class ForegroundService extends Service { /** * Show a notification while this service is running. */ - private void showNotification() { + private synchronized void showNotification() { // In this sample, we'll use the same text for the ticker and the expanded notification - CharSequence text = getText(R.string.i2pd_started); + 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, @@ -88,6 +117,7 @@ public class ForegroundService extends Service { // Send the notification. //mNM.notify(NOTIFICATION, notification); startForeground(NOTIFICATION, notification); + shown=true; } 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 64316112..af0c8000 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -19,9 +19,10 @@ import android.widget.TextView; import android.widget.Toast; public class I2PDActivity extends Activity { - private static final String TAG = "i2pd"; + private static final String TAG = "i2pdActvt"; + public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; - private TextView textView; + private TextView textView; private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); @@ -42,8 +43,11 @@ public class I2PDActivity extends Activity { return; } DaemonSingleton.State state = daemon.getState(); - textView.setText(String.valueOf(state)+ - (DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")); + textView.setText( + String.valueOf(state)+ + (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); } @@ -51,6 +55,18 @@ public class I2PDActivity extends Activity { }); } }; + private volatile long graceStartedMillis; + private final Object graceStartedMillis_LOCK=new Object(); + + private String formatGraceTimeRemaining() { + long remainingSeconds; + synchronized (graceStartedMillis_LOCK){ + remainingSeconds=Math.round(Math.max(0,graceStartedMillis+GRACEFUL_DELAY_MILLIS-System.currentTimeMillis())/1000.0D); + } + long remainingMinutes=(long)Math.floor(remainingSeconds/60.0D); + long remSec=remainingSeconds-remainingMinutes*60; + return remainingMinutes+":"+(remSec/10)+remSec%10; + } @Override public void onCreate(Bundle savedInstanceState) { @@ -70,11 +86,7 @@ public class I2PDActivity extends Activity { super.onDestroy(); textView = null; daemon.removeStateChangeListener(daemonStateUpdatedListener); - Timer gracefulQuitTimer = getGracefulQuitTimer(); - if(gracefulQuitTimer!=null) { - gracefulQuitTimer.cancel(); - setGracefulQuitTimer(null); - } + cancelGracefulStop(); try{ doUnbindService(); }catch(Throwable tr){ @@ -82,7 +94,15 @@ public class I2PDActivity extends Activity { } } - private CharSequence throwableToString(Throwable tr) { + private void cancelGracefulStop() { + Timer gracefulQuitTimer = getGracefulQuitTimer(); + if(gracefulQuitTimer!=null) { + gracefulQuitTimer.cancel(); + setGracefulQuitTimer(null); + } + } + + private CharSequence throwableToString(Throwable tr) { StringWriter sw = new StringWriter(8192); PrintWriter pw = new PrintWriter(sw); tr.printStackTrace(pw); @@ -169,11 +189,20 @@ public class I2PDActivity extends Activity { } private void i2pdStop() { - try{ - daemon.stopDaemon(); - }catch (Throwable tr) { - Log.e(TAG, "", tr); - } + cancelGracefulStop(); + new Thread(new Runnable(){ + + @Override + public void run() { + Log.d(TAG, "stopping"); + try{ + daemon.stopDaemon(); + }catch (Throwable tr) { + Log.e(TAG, "", tr); + } + } + + },"stop").start(); } private volatile Timer gracefulQuitTimer; @@ -199,8 +228,11 @@ public class I2PDActivity extends Activity { Log.d(TAG, "grac stopping"); if(daemon.isStartedOkay()) { daemon.stopAcceptingTunnels(); - Timer gracefulQuitTimer = new Timer(true); + final Timer gracefulQuitTimer = new Timer(true); setGracefulQuitTimer(gracefulQuitTimer); + synchronized (graceStartedMillis_LOCK) { + graceStartedMillis = System.currentTimeMillis(); + } gracefulQuitTimer.schedule(new TimerTask(){ @Override @@ -208,7 +240,14 @@ public class I2PDActivity extends Activity { i2pdStop(); } - }, 10*60*1000/*milliseconds*/); + }, GRACEFUL_DELAY_MILLIS); + final TimerTask tickerTask = new TimerTask() { + @Override + public void run() { + daemonStateUpdatedListener.daemonStateUpdate(); + } + }; + gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/); }else{ i2pdStop(); } From 56f6e57118a58bc2d7c2a6ab73b6ad627bbb036a Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 19:54:19 +0800 Subject: [PATCH 068/134] fixes grac stop --- .../src/org/purplei2p/i2pd/I2PDActivity.java | 70 ++++++++++++------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index af0c8000..840e0bfa 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -20,7 +20,7 @@ import android.widget.Toast; public class I2PDActivity extends Activity { private static final String TAG = "i2pdActvt"; - public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; + public static final int GRACEFUL_DELAY_MILLIS = 120 * 1000; private TextView textView; @@ -55,10 +55,10 @@ public class I2PDActivity extends Activity { }); } }; - private volatile long graceStartedMillis; - private final Object graceStartedMillis_LOCK=new Object(); + private static volatile long graceStartedMillis; + private static final Object graceStartedMillis_LOCK=new Object(); - private String formatGraceTimeRemaining() { + private static String formatGraceTimeRemaining() { long remainingSeconds; synchronized (graceStartedMillis_LOCK){ remainingSeconds=Math.round(Math.max(0,graceStartedMillis+GRACEFUL_DELAY_MILLIS-System.currentTimeMillis())/1000.0D); @@ -79,6 +79,15 @@ public class I2PDActivity extends Activity { //set the app be foreground doBindService(); + + final Timer gracefulQuitTimer = getGracefulQuitTimer(); + if(gracefulQuitTimer!=null){ + long gracefulStopAtMillis; + synchronized (graceStartedMillis_LOCK) { + gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS; + } + rescheduleGraceStop(gracefulQuitTimer, gracefulStopAtMillis); + } } @Override @@ -86,7 +95,7 @@ public class I2PDActivity extends Activity { super.onDestroy(); textView = null; daemon.removeStateChangeListener(daemonStateUpdatedListener); - cancelGracefulStop(); + //cancelGracefulStop(); try{ doUnbindService(); }catch(Throwable tr){ @@ -94,7 +103,7 @@ public class I2PDActivity extends Activity { } } - private void cancelGracefulStop() { + private static void cancelGracefulStop() { Timer gracefulQuitTimer = getGracefulQuitTimer(); if(gracefulQuitTimer!=null) { gracefulQuitTimer.cancel(); @@ -205,7 +214,7 @@ public class I2PDActivity extends Activity { },"stop").start(); } - private volatile Timer gracefulQuitTimer; + private static volatile Timer gracefulQuitTimer; private void i2pdGracefulStop() { if(daemon.getState()==DaemonSingleton.State.stopped){ @@ -228,26 +237,12 @@ public class I2PDActivity extends Activity { Log.d(TAG, "grac stopping"); if(daemon.isStartedOkay()) { daemon.stopAcceptingTunnels(); - final Timer gracefulQuitTimer = new Timer(true); - setGracefulQuitTimer(gracefulQuitTimer); + long gracefulStopAtMillis; synchronized (graceStartedMillis_LOCK) { graceStartedMillis = System.currentTimeMillis(); + gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS; } - gracefulQuitTimer.schedule(new TimerTask(){ - - @Override - public void run() { - i2pdStop(); - } - - }, GRACEFUL_DELAY_MILLIS); - final TimerTask tickerTask = new TimerTask() { - @Override - public void run() { - daemonStateUpdatedListener.daemonStateUpdate(); - } - }; - gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/); + rescheduleGraceStop(null,gracefulStopAtMillis); }else{ i2pdStop(); } @@ -259,11 +254,32 @@ public class I2PDActivity extends Activity { },"gracInit").start(); } - private Timer getGracefulQuitTimer() { + private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) { + if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel(); + final Timer gracefulQuitTimer = new Timer(true); + setGracefulQuitTimer(gracefulQuitTimer); + gracefulQuitTimer.schedule(new TimerTask(){ + + @Override + public void run() { + i2pdStop(); + } + + }, Math.max(0,gracefulStopAtMillis-System.currentTimeMillis())); + final TimerTask tickerTask = new TimerTask() { + @Override + public void run() { + daemonStateUpdatedListener.daemonStateUpdate(); + } + }; + gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/); + } + + private static Timer getGracefulQuitTimer() { return gracefulQuitTimer; } - private void setGracefulQuitTimer(Timer gracefulQuitTimer) { - this.gracefulQuitTimer = gracefulQuitTimer; + private static void setGracefulQuitTimer(Timer gracefulQuitTimer) { + I2PDActivity.gracefulQuitTimer = gracefulQuitTimer; } } From ac495da5fe6c8e688329bab0142392e56fe51dac Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 19:56:44 +0800 Subject: [PATCH 069/134] fixes grac stop --- android/src/org/purplei2p/i2pd/I2PDActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 840e0bfa..99672eb7 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -20,7 +20,7 @@ import android.widget.Toast; public class I2PDActivity extends Activity { private static final String TAG = "i2pdActvt"; - public static final int GRACEFUL_DELAY_MILLIS = 120 * 1000; + public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; private TextView textView; From badb837b46b299419ac1d3091d0bbebdcb90be33 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 23:20:50 +0800 Subject: [PATCH 070/134] fixed #1088 --- android/AndroidManifest.xml | 10 +- android/build.gradle | 22 +++- android/res/layout/activity_perms_asker.xml | 27 ++++ android/res/values/template-dimens.xml | 16 +++ .../src/org/purplei2p/i2pd/I2PDActivity.java | 3 +- .../i2pd/I2PDPermsAskerActivity.java | 121 ++++++++++++++++++ 6 files changed, 190 insertions(+), 9 deletions(-) create mode 100644 android/res/layout/activity_perms_asker.xml create mode 100644 android/res/values/template-dimens.xml create mode 100644 android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 95fff3ff..df817b82 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -6,21 +6,21 @@ android:versionName="2.18.0"> - - - + + + - + + diff --git a/android/build.gradle b/android/build.gradle index 821dbc16..750ae008 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,15 +1,31 @@ buildscript { repositories { - mavenCentral() - jcenter() + mavenCentral() + jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:2.3.3' } } apply plugin: 'com.android.application' +repositories { + jcenter() + maven { + url 'https://maven.google.com' + } +} + +dependencies { +// compile "com.android.support:support-v4:26.1.0" +// compile "com.android.support:support-v13:26.1.0" +// compile "com.android.support:cardview-v7:26.1.0" +// compile "com.android.support:appcompat-v7:26.1.0" + compile 'com.android.support:support-v4:25.3.1' + compile 'com.android.support:design:25.3.1' +} + android { compileSdkVersion 25 buildToolsVersion "25.0.2" diff --git a/android/res/layout/activity_perms_asker.xml b/android/res/layout/activity_perms_asker.xml new file mode 100644 index 00000000..d2d12cb6 --- /dev/null +++ b/android/res/layout/activity_perms_asker.xml @@ -0,0 +1,27 @@ + + + + +