From 3167ae21b0d95a9445e8ea96957811ac91eed2fe Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Oct 2016 20:08:15 -0400 Subject: [PATCH 01/65] send own LeasetSet through a stalled stream --- Garlic.h | 3 ++- Streaming.cpp | 26 ++++++++++++++++++++++++++ Streaming.h | 24 ++++++++++++++++++------ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/Garlic.h b/Garlic.h index 76d8eaf3..0fa5403c 100644 --- a/Garlic.h +++ b/Garlic.h @@ -105,7 +105,8 @@ namespace garlic if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; }; bool IsLeaseSetNonConfirmed () const { return m_LeaseSetUpdateStatus == eLeaseSetSubmitted; }; - + bool IsLeaseSetUpdated () const { return m_LeaseSetUpdateStatus == eLeaseSetUpdated; }; + std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); diff --git a/Streaming.cpp b/Streaming.cpp index 02e738c8..78465b87 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -659,6 +659,29 @@ namespace stream LogPrint (eLogWarning, "Streaming: All leases are expired, sSID=", m_SendStreamID); } + void Stream::SendUpdatedLeaseSet () + { + if (m_RoutingSession && m_RoutingSession->IsLeaseSetUpdated ()) + { + if (!m_CurrentRemoteLease) + UpdateCurrentRemoteLease (true); + if (m_CurrentRemoteLease) + { + auto msg = m_RoutingSession->WrapSingleMessage (nullptr); + auto outboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (); + if (outboundTunnel) + m_CurrentOutboundTunnel->SendTunnelDataMsg ( + { + i2p::tunnel::TunnelMessageBlock + { + i2p::tunnel::eDeliveryTypeTunnel, + m_CurrentRemoteLease->tunnelGateway, m_CurrentRemoteLease->tunnelID, + msg + } + }); + } + } + } void Stream::ScheduleResend () { @@ -760,7 +783,10 @@ namespace stream { m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); if (!m_RemoteLeaseSet) + { LogPrint (eLogWarning, "Streaming: LeaseSet ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " not found"); + m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ()); // try to request for a next attempt + } } if (m_RemoteLeaseSet) { diff --git a/Streaming.h b/Streaming.h index efa4d69e..75ce4c56 100644 --- a/Streaming.h +++ b/Streaming.h @@ -51,6 +51,7 @@ namespace stream const int INITIAL_RTO = 9000; // in milliseconds const size_t MAX_PENDING_INCOMING_BACKLOG = 128; const int PENDING_INCOMING_TIMEOUT = 10; // in seconds + const int MAX_RECEIVE_TIMEOUT = 60; // in seconds /** i2cp option for limiting inbound stremaing connections */ const char I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN[] = "maxconns"; @@ -161,6 +162,7 @@ namespace stream void SendClose (); bool SendPacket (Packet * packet); void SendPackets (const std::vector& packets); + void SendUpdatedLeaseSet (); void SavePacket (Packet * packet); void ProcessPacket (Packet * packet); @@ -170,7 +172,7 @@ namespace stream void UpdateCurrentRemoteLease (bool expired = false); template - void HandleReceiveTimer (const boost::system::error_code& ecode, const Buffer& buffer, ReceiveHandler handler); + void HandleReceiveTimer (const boost::system::error_code& ecode, const Buffer& buffer, ReceiveHandler handler, int remainingTimeout); void ScheduleResend (); void HandleResendTimer (const boost::system::error_code& ecode); @@ -282,18 +284,19 @@ namespace stream m_Service.post ([=](void) { if (!m_ReceiveQueue.empty () || m_Status == eStreamStatusReset) - s->HandleReceiveTimer (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), buffer, handler); + s->HandleReceiveTimer (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), buffer, handler, 0); else { - s->m_ReceiveTimer.expires_from_now (boost::posix_time::seconds(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); }); + { s->HandleReceiveTimer (ecode, buffer, handler, timeout - t); }); } }); } template - void Stream::HandleReceiveTimer (const boost::system::error_code& ecode, const Buffer& buffer, ReceiveHandler handler) + void Stream::HandleReceiveTimer (const boost::system::error_code& ecode, const Buffer& buffer, ReceiveHandler handler, int remainingTimeout) { size_t received = ConcatenatePackets (boost::asio::buffer_cast(buffer), boost::asio::buffer_size(buffer)); if (received > 0) @@ -307,8 +310,17 @@ namespace stream handler (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), 0); } else + { // timeout expired - handler (boost::asio::error::make_error_code (boost::asio::error::timed_out), received); + if (remainingTimeout <= 0) + handler (boost::asio::error::make_error_code (boost::asio::error::timed_out), received); + else + { + // itermediate iterrupt + SendUpdatedLeaseSet (); // send our leaseset if applicable + AsyncReceive (buffer, handler, remainingTimeout); + } + } } } } From 6688f9a5ef85e8cd59e61f66b02945b1f46b8e69 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 23 Oct 2016 08:14:21 -0400 Subject: [PATCH 02/65] update cmake for i2lua --- build/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 00048942..f6697612 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -18,6 +18,7 @@ option(WITH_GUI "Include GUI (currently MS Windows only)" ON) option(WITH_MESHNET "Build for cjdns test network" OFF) option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF) option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF) +option(WITH_I2LUA "Build for i2lua" OFF) # paths set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" ) @@ -64,6 +65,10 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR MSYS) list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp") endif () +if (WITH_I2LUA) + add_definitions(-DI2LUA) +endif() + add_library(libi2pd ${LIBI2PD_SRC}) set_target_properties(libi2pd PROPERTIES PREFIX "") install(TARGETS libi2pd @@ -361,6 +366,7 @@ message(STATUS " PCH : ${WITH_PCH}") message(STATUS " MESHNET : ${WITH_MESHNET}") message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}") message(STATUS " THEADSANITIZER : ${WITH_THREADSANITIZER}") +message(STATUS " I2LUA : ${WITH_I2LUA}") message(STATUS "---------------------------------------") #Handle paths nicely From c5e2ec5e00c282a3be9a4809236189c8bb616dbc Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Oct 2016 16:16:08 -0400 Subject: [PATCH 03/65] random remote lease selection for LeaseSet update --- Streaming.cpp | 23 ++++++++++++++++------- Streaming.h | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index 78465b87..31787087 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -661,25 +661,34 @@ namespace stream void Stream::SendUpdatedLeaseSet () { - if (m_RoutingSession && m_RoutingSession->IsLeaseSetUpdated ()) + if (m_RoutingSession && m_RemoteLeaseSet && + (m_RoutingSession->IsLeaseSetUpdated () || m_RoutingSession->IsLeaseSetNonConfirmed ())) { - if (!m_CurrentRemoteLease) - UpdateCurrentRemoteLease (true); - if (m_CurrentRemoteLease) + auto leases = m_RemoteLeaseSet->GetNonExpiredLeases (true); // with threshold + if (leases.empty ()) { - auto msg = m_RoutingSession->WrapSingleMessage (nullptr); auto outboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (); if (outboundTunnel) - m_CurrentOutboundTunnel->SendTunnelDataMsg ( + { + auto lease = leases[rand () % leases.size ()]; + auto msg = m_RoutingSession->WrapSingleMessage (nullptr); + outboundTunnel->SendTunnelDataMsg ( { i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeTunnel, - m_CurrentRemoteLease->tunnelGateway, m_CurrentRemoteLease->tunnelID, + lease->tunnelGateway, lease->tunnelID, msg } }); + LogPrint (eLogDebug, "Streaming: Updated LeaseSet sent. sSID=", m_SendStreamID); + } } + else + { + LogPrint (eLogWarning, "Streaming: Can't sent updated LeaseSet. Remote LeaseSet expired. sSID=", m_SendStreamID); + m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ()); + } } } diff --git a/Streaming.h b/Streaming.h index 75ce4c56..2be724ed 100644 --- a/Streaming.h +++ b/Streaming.h @@ -51,7 +51,7 @@ namespace stream const int INITIAL_RTO = 9000; // in milliseconds const size_t MAX_PENDING_INCOMING_BACKLOG = 128; const int PENDING_INCOMING_TIMEOUT = 10; // in seconds - const int MAX_RECEIVE_TIMEOUT = 60; // in seconds + const int MAX_RECEIVE_TIMEOUT = 30; // in seconds /** i2cp option for limiting inbound stremaing connections */ const char I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN[] = "maxconns"; From 28cf351878f41215ea091bf4768c5b8d3bd5afac Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 24 Oct 2016 07:11:18 -0400 Subject: [PATCH 04/65] fixed typo --- Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Streaming.cpp b/Streaming.cpp index 31787087..5eae1628 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -665,7 +665,7 @@ namespace stream (m_RoutingSession->IsLeaseSetUpdated () || m_RoutingSession->IsLeaseSetNonConfirmed ())) { auto leases = m_RemoteLeaseSet->GetNonExpiredLeases (true); // with threshold - if (leases.empty ()) + if (!leases.empty ()) { auto outboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (); if (outboundTunnel) From 4ee9b4524d416660dcd09e023bc7b4d650ea3b36 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 24 Oct 2016 10:33:46 -0400 Subject: [PATCH 05/65] correct netid handling --- Daemon.cpp | 3 +++ RouterContext.cpp | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Daemon.cpp b/Daemon.cpp index 7dec30a9..e0c45ac3 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -138,6 +138,9 @@ namespace i2p uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); SetMaxNumTransitTunnels (transitTunnels); + int netID; i2p::config::GetOption("netid", netID); + i2p::context.SetNetID (netID); + bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); if (isFloodfill) { LogPrint(eLogInfo, "Daemon: router will be floodfill"); diff --git a/RouterContext.cpp b/RouterContext.cpp index b4bbefb6..309e1104 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -77,7 +77,6 @@ namespace i2p } routerInfo.SetCaps (i2p::data::RouterInfo::eReachable | i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC - i2p::config::GetOption("netid", m_NetID); routerInfo.SetProperty ("netId", std::to_string (m_NetID)); routerInfo.SetProperty ("router.version", I2P_VERSION); routerInfo.CreateBuffer (m_Keys); From c74db4b81c962563a51a6813bf7e8a4fe62097b8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 24 Oct 2016 20:58:25 -0400 Subject: [PATCH 06/65] resubmit non-confirmed LeaseSet --- Garlic.h | 1 + Streaming.cpp | 42 +++++++++++++++++------------------------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/Garlic.h b/Garlic.h index 0fa5403c..a3ab7d92 100644 --- a/Garlic.h +++ b/Garlic.h @@ -106,6 +106,7 @@ namespace garlic }; bool IsLeaseSetNonConfirmed () const { return m_LeaseSetUpdateStatus == eLeaseSetSubmitted; }; bool IsLeaseSetUpdated () const { return m_LeaseSetUpdateStatus == eLeaseSetUpdated; }; + uint64_t GetLeaseSetSubmissionTime () const { return m_LeaseSetSubmissionTime; } std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); diff --git a/Streaming.cpp b/Streaming.cpp index 5eae1628..077adce4 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -661,33 +661,25 @@ namespace stream void Stream::SendUpdatedLeaseSet () { - if (m_RoutingSession && m_RemoteLeaseSet && - (m_RoutingSession->IsLeaseSetUpdated () || m_RoutingSession->IsLeaseSetNonConfirmed ())) - { - auto leases = m_RemoteLeaseSet->GetNonExpiredLeases (true); // with threshold - if (!leases.empty ()) - { - auto outboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (); - if (outboundTunnel) - { - auto lease = leases[rand () % leases.size ()]; - auto msg = m_RoutingSession->WrapSingleMessage (nullptr); - outboundTunnel->SendTunnelDataMsg ( - { - i2p::tunnel::TunnelMessageBlock - { - i2p::tunnel::eDeliveryTypeTunnel, - lease->tunnelGateway, lease->tunnelID, - msg - } - }); - LogPrint (eLogDebug, "Streaming: Updated LeaseSet sent. sSID=", m_SendStreamID); + if (m_RoutingSession) + { + if (m_RoutingSession->IsLeaseSetNonConfirmed ()) + { + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + if (ts > m_RoutingSession->GetLeaseSetSubmissionTime () + i2p::garlic::LEASET_CONFIRMATION_TIMEOUT) + { + // LeaseSet was not confirmed, should try other tunnels + LogPrint (eLogWarning, "Streaming: LeaseSet was not confrimed in ", i2p::garlic::LEASET_CONFIRMATION_TIMEOUT, " milliseconds. Trying to resubmit"); + m_RoutingSession->SetSharedRoutingPath (nullptr); + m_CurrentOutboundTunnel = nullptr; + m_CurrentRemoteLease = nullptr; + SendQuickAck (); } - } - else + } + else if (m_RoutingSession->IsLeaseSetUpdated ()) { - LogPrint (eLogWarning, "Streaming: Can't sent updated LeaseSet. Remote LeaseSet expired. sSID=", m_SendStreamID); - m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ()); + LogPrint (eLogDebug, "Streaming: sending updated LeaseSet"); + SendQuickAck (); } } } From d8510ead43482723216b5952cdd7c04a3ee8313e Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 25 Oct 2016 14:07:34 -0400 Subject: [PATCH 07/65] don't return expired LeaseSet --- Destination.cpp | 25 +++++++++++++++++-------- Destination.h | 1 + 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index d020d96e..5c81a64b 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -202,7 +202,12 @@ namespace client return remoteLS; } else + { LogPrint (eLogWarning, "Destination: remote LeaseSet expired"); + std::lock_guard lock(m_RemoteLeaseSetsMutex); + m_RemoteLeaseSets.erase (ident); + return nullptr; + } } else { @@ -223,12 +228,16 @@ namespace client if (!m_Pool) return nullptr; if (!m_LeaseSet) UpdateLeaseSet (); + std::lock_guard l(m_LeaseSetMutex); return m_LeaseSet; } void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet) { - m_LeaseSet.reset (newLeaseSet); + { + std::lock_guard l(m_LeaseSetMutex); + m_LeaseSet.reset (newLeaseSet); + } i2p::garlic::GarlicDestination::SetLeaseSetUpdated (); if (m_IsPublic) { @@ -371,14 +380,14 @@ namespace client if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) { for (int i = 0; i < num; i++) + { + i2p::data::IdentHash peerHash (buf + 33 + i*32); + if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash)) { - i2p::data::IdentHash peerHash (buf + 33 + i*32); - if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash)) - { - LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); // TODO: recheck this message - i2p::data::netdb.RequestDestination (peerHash); - } - } + LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); // TODO: recheck this message + i2p::data::netdb.RequestDestination (peerHash); + } + } auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded); if (floodfill) diff --git a/Destination.h b/Destination.h index e2d532e8..ba19a32a 100644 --- a/Destination.h +++ b/Destination.h @@ -131,6 +131,7 @@ namespace client std::map > m_LeaseSetRequests; std::shared_ptr m_Pool; + std::mutex m_LeaseSetMutex; std::shared_ptr m_LeaseSet; bool m_IsPublic; uint32_t m_PublishReplyToken; From 8e1687e7b3dcc482c9919473a7dbdf6f6716cc81 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 26 Oct 2016 00:00:00 +0000 Subject: [PATCH 08/65] * reorganize docs in build-notes*.md --- docs/build_requirements.md | 15 --------------- .../android.md} | 0 docs/{build_notes_cross.md => building/cross.md} | 0 docs/{build_notes_ios.md => building/ios.md} | 0 docs/building/requirements.md | 14 ++++++++++++++ docs/{build_notes_unix.md => building/unix.md} | 0 .../windows.md} | 4 +--- docs/index.rst | 13 ++++++------- 8 files changed, 21 insertions(+), 25 deletions(-) delete mode 100644 docs/build_requirements.md rename docs/{build_notes_android.md => building/android.md} (100%) rename docs/{build_notes_cross.md => building/cross.md} (100%) rename docs/{build_notes_ios.md => building/ios.md} (100%) create mode 100644 docs/building/requirements.md rename docs/{build_notes_unix.md => building/unix.md} (100%) rename docs/{build_notes_windows.md => building/windows.md} (98%) diff --git a/docs/build_requirements.md b/docs/build_requirements.md deleted file mode 100644 index 3e0dfea9..00000000 --- a/docs/build_requirements.md +++ /dev/null @@ -1,15 +0,0 @@ -Build requirements -============ - -Linux/FreeBSD/OSX ------------------ - -GCC 4.7 or newer, Boost 1.49 or newer, openssl, zlib. Clang can be used instead of GCC. - -Windows -------- - -VS2013 (known to work with 12.0.21005.1 or newer), Boost 1.46 or newer, -crypto++ 5.62. See Win32/README-Build.txt for instructions on how to build i2pd -and its dependencies. - diff --git a/docs/build_notes_android.md b/docs/building/android.md similarity index 100% rename from docs/build_notes_android.md rename to docs/building/android.md diff --git a/docs/build_notes_cross.md b/docs/building/cross.md similarity index 100% rename from docs/build_notes_cross.md rename to docs/building/cross.md diff --git a/docs/build_notes_ios.md b/docs/building/ios.md similarity index 100% rename from docs/build_notes_ios.md rename to docs/building/ios.md diff --git a/docs/building/requirements.md b/docs/building/requirements.md new file mode 100644 index 00000000..8712a03d --- /dev/null +++ b/docs/building/requirements.md @@ -0,0 +1,14 @@ +Build requirements +================== + +In general, for building i2pd you need several things: + +* compiler with c++11 support (for example: gcc >= 4.7, clang) +* boost >= 1.49 +* openssl library +* zlib library (openssl already depends on it) + +Optional tools: + +* cmake >= 2.8 (or 3.3+ if you want to use precompiled headers on windows) +* miniupnp library (for upnp support) diff --git a/docs/build_notes_unix.md b/docs/building/unix.md similarity index 100% rename from docs/build_notes_unix.md rename to docs/building/unix.md diff --git a/docs/build_notes_windows.md b/docs/building/windows.md similarity index 98% rename from docs/build_notes_windows.md rename to docs/building/windows.md index 2b4b96b6..5c9fda5a 100644 --- a/docs/build_notes_windows.md +++ b/docs/building/windows.md @@ -3,7 +3,7 @@ Building on Windows There are two approaches available to build i2pd on Windows. The best one depends on your needs and personal preferences. One is to use -msys2 and [unix alike infrastructure](build_notes_unix.md). Another +msys2 and [unix alike infrastructure](unix.md). Another one is to use Visual Studio. While there might be no difference for end users of i2pd daemon, developers, however, shall be wary of differences in C++ name mangling between the two compilers when making @@ -20,8 +20,6 @@ development location for the sake of convenience. Adjust paths accordingly if it is not the case. Note that msys uses unix-alike paths like /c/dev/ for C:\dev\. - - msys2 ----- diff --git a/docs/index.rst b/docs/index.rst index 8cfddb24..c1061171 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,14 +29,13 @@ Contents: .. toctree:: :maxdepth: 2 - build_requirements - build_notes_unix - build_notes_windows - build_notes_cross - build_notes_android - build_notes_ios + building/requirements + building/unix + building/windows + building/cross + building/android + building/ios configuration family usage - From 890807b8d71bb849b9b005615790ed211f45868e Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 26 Oct 2016 00:00:00 +0000 Subject: [PATCH 09/65] * build docs : markdown cleanup & reformatting --- docs/building/android.md | 62 ++++++++------- docs/building/cross.md | 123 ++++++++++++++-------------- docs/building/ios.md | 48 +++++------ docs/building/unix.md | 167 ++++++++++++++++++--------------------- docs/building/windows.md | 148 +++++++++++++--------------------- 5 files changed, 253 insertions(+), 295 deletions(-) diff --git a/docs/building/android.md b/docs/building/android.md index 93b8b77e..3e9ab089 100644 --- a/docs/building/android.md +++ b/docs/building/android.md @@ -8,50 +8,58 @@ Pre-requesties You need to install Android SDK, NDK and QT with android support. -- [SDK](https://developer.android.com/studio/index.html) (choose command line tools only) -- [NDK](https://developer.android.com/ndk/downloads/index.html) -- [QT](https://www.qt.io/download-open-source/)(for QT only). Choose one for your platform for android. For example QT 5.6 under Linux would be [this file](http://download.qt.io/official_releases/qt/5.6/5.6.1-1/qt-opensource-linux-x64-android-5.6.1-1.run ) +- [SDK](https://developer.android.com/studio/index.html) (choose command line tools only) +- [NDK](https://developer.android.com/ndk/downloads/index.html) +- [QT](https://www.qt.io/download-open-source/)(for QT only). + Choose one for your platform for android. For example QT 5.6 under Linux would be [this file](http://download.qt.io/official_releases/qt/5.6/5.6.1-1/qt-opensource-linux-x64-android-5.6.1-1.run) You also need Java JDK and Ant. QT-Creator (for QT only) ------------------------ -Open QT-creator that should be installed with QT. + +Open QT-creator that should be installed with QT. Go to Settings/Anndroid and specify correct paths to SDK and NDK. -If everything is correct you will see two set avaiable: +If everything is correct you will see two set avaiable: Android for armeabi-v7a (gcc, qt) and Android for x86 (gcc, qt). Dependencies -------------- -Take following pre-compiled binaries from PurpleI2P's repositories. -```bash -git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git -git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git -git clone https://github.com/PurpleI2P/android-ifaddrs.git -``` +Take following pre-compiled binaries from PurpleI2P's repositories. + + git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git + git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git + git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git + git clone https://github.com/PurpleI2P/android-ifaddrs.git Building the app with QT ------------------------ -- Open qt/i2pd_qt/i2pd_qt.pro in the QT-creator -- Change line MAIN_PATH = /path/to/libraries to an actual path where you put the dependancies to -- Select appropriate project (usually armeabi-v7a) and build -- You will find an .apk file in android-build/bin folder + +- Open `qt/i2pd_qt/i2pd_qt.pro` in the QT-creator +- Change line `MAIN_PATH = /path/to/libraries` to an actual path where you put the dependancies to +- Select appropriate project (usually armeabi-v7a) and build +- You will find an .apk file in `android-build/bin` folder Building the app without QT --------------------------- -- Change line I2PD_LIBS_PATH in android/jni/Application.mk to an actual path where you put the dependancies to -- Run 'ndk-build -j4' from andorid folder -- Create or edit file 'local.properties'. Place 'sdk.dir=' and 'ndk.dir=' -- Run 'ant clean debug' + +- Change line `I2PD_LIBS_PATH` in `android/jni/Application.mk` to an actual path where you put the dependancies to +- Run `ndk-build -j4` from andorid folder +- Create or edit file 'local.properties'. Place 'sdk.dir=' and 'ndk.dir=' +- Run `ant clean debug` Creating release .apk ---------------------- -In order to create release .apk you must obtain a Java keystore file(.jks). Either you have in already, or you can generate it yourself using keytool, or from one of you existing well-know ceritificates. For example, i2pd release are signed with this [certificate](https://github.com/PurpleI2P/i2pd/blob/openssl/contrib/certificates/router/orignal_at_mail.i2p.crt). -Create file 'ant.propeties' -key.store='path to keystore file' -key.alias='alias name' -key.store.password='keystore password' -key.alias.password='alias password' -Run 'ant clean release' + +In order to create release .apk you must obtain a Java keystore file(.jks). Either you have in already, or you can generate it yourself using keytool, or from one of you existing well-know ceritificates. +For example, i2pd release are signed with this [certificate](https://github.com/PurpleI2P/i2pd/blob/openssl/contrib/certificates/router/orignal_at_mail.i2p.crt). + +Create file 'ant.propeties': + + key.store='path to keystore file' + key.alias='alias name' + key.store.password='keystore password' + key.alias.password='alias password' + +Run `ant clean release` diff --git a/docs/building/cross.md b/docs/building/cross.md index 78d60e6a..fc884cad 100644 --- a/docs/building/cross.md +++ b/docs/building/cross.md @@ -2,74 +2,73 @@ Cross compilation notes ======================= Static 64 bit windows binary on Ubuntu 15.10 (Wily Werewolf) ---------------------------------------------------------------------- +------------------------------------------------------------ Install cross compiler and friends -```sh -sudo apt-get install g++-mingw-w64-x86-64 -``` + + sudo apt-get install g++-mingw-w64-x86-64 + Default is to use Win32 threading model which lacks std::mutex and such. So we change defaults -```sh -sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix -``` -From now on we assume we have everything in `~/dev/`. Get Boost sources unpacked into `~/dev/boost_1_60_0/` -and change directory to it. + + sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix + +From now on we assume we have everything in `~/dev/`. Get Boost sources unpacked into `~/dev/boost_1_60_0/` and change directory to it. Now add out cross compiler configuration. Warning: the following will wipe out whatever you had in there. -```sh -echo "using gcc : mingw : x86_64-w64-mingw32-g++ ;" > ~/user-config.jam -``` + + echo "using gcc : mingw : x86_64-w64-mingw32-g++ ;" > ~/user-config.jam + Proceed with building Boost normal way, but let's define dedicated staging directory -```sh -./bootstrap.sh -./b2 toolset=gcc-mingw target-os=windows variant=release link=static runtime-link=static address-model=64 \ - --build-type=minimal --with-filesystem --with-program_options --with-date_time \ - --stagedir=stage-mingw-64 -cd .. -``` + + ./bootstrap.sh + ./b2 toolset=gcc-mingw target-os=windows variant=release link=static runtime-link=static address-model=64 \ + --build-type=minimal --with-filesystem --with-program_options --with-date_time \ + --stagedir=stage-mingw-64 + cd .. + Now we get & build OpenSSL -```sh -git clone https://github.com/openssl/openssl -cd openssl -git checkout OpenSSL_1_0_2g -./Configure mingw64 no-rc2 no-rc4 no-rc5 no-idea no-bf no-cast no-whirlpool no-md2 no-md4 no-ripemd no-mdc2 \ - no-camellia no-seed no-comp no-krb5 no-gmp no-rfc3779 no-ec2m no-ssl2 no-jpake no-srp no-sctp no-srtp \ - --prefix=~/dev/stage --cross-compile-prefix=x86_64-w64-mingw32- -make depend -make -make install -cd .. -``` -and Zlib -```sh -git clone https://github.com/madler/zlib -cd zlib -git checkout v1.2.8 -CC=x86_64-w64-mingw32-gcc CFLAGS=-O3 ./configure --static --64 --prefix=~/dev/stage -make -make install -cd .. -``` + + git clone https://github.com/openssl/openssl + cd openssl + git checkout OpenSSL_1_0_2g + ./Configure mingw64 no-rc2 no-rc4 no-rc5 no-idea no-bf no-cast no-whirlpool no-md2 no-md4 no-ripemd no-mdc2 \ + no-camellia no-seed no-comp no-krb5 no-gmp no-rfc3779 no-ec2m no-ssl2 no-jpake no-srp no-sctp no-srtp \ + --prefix=~/dev/stage --cross-compile-prefix=x86_64-w64-mingw32- + make depend + make + make install + cd .. + +...and zlib + + git clone https://github.com/madler/zlib + cd zlib + git checkout v1.2.8 + CC=x86_64-w64-mingw32-gcc CFLAGS=-O3 ./configure --static --64 --prefix=~/dev/stage + make + make install + cd .. + Now we prepare cross toolchain hint file for CMake, let's name it `~/dev/toolchain-mingw.cmake` -```cmake -SET(CMAKE_SYSTEM_NAME Windows) -SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) -SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) -SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) -SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -``` -Download miniupnpc, unpack, and symlink it into `~/dev/miniupnpc/`. + + set(CMAKE_SYSTEM_NAME Windows) + set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) + set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) + set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) + set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +Download miniupnpc, unpack and symlink it into `~/dev/miniupnpc/`. Finally, we can build i2pd with all that goodness -```sh -git clone https://github.com/PurpleI2P/i2pd -mkdir i2pd-mingw-64-build -cd i2pd-mingw-64-build -BOOST_ROOT=~/dev/boost_1_60_0 cmake -G 'Unix Makefiles' ~/dev/i2pd/build -DBUILD_TYPE=Release \ - -DCMAKE_TOOLCHAIN_FILE=~/dev/toolchain-mingw.cmake -DWITH_AESNI=ON -DWITH_UPNP=ON -DWITH_STATIC=ON \ - -DWITH_HARDENING=ON -DCMAKE_INSTALL_PREFIX:PATH=~/dev/i2pd-mingw-64-static \ - -DZLIB_ROOT=~/dev/stage -DBOOST_LIBRARYDIR:PATH=~/dev/boost_1_60_0/stage-mingw-64/lib \ - -DOPENSSL_ROOT_DIR:PATH=~/dev/stage -make -x86_64-w64-mingw32-strip i2pd.exe -``` + + git clone https://github.com/PurpleI2P/i2pd + mkdir i2pd-mingw-64-build + cd i2pd-mingw-64-build + BOOST_ROOT=~/dev/boost_1_60_0 cmake -G 'Unix Makefiles' ~/dev/i2pd/build -DBUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE=~/dev/toolchain-mingw.cmake -DWITH_AESNI=ON -DWITH_UPNP=ON -DWITH_STATIC=ON \ + -DWITH_HARDENING=ON -DCMAKE_INSTALL_PREFIX:PATH=~/dev/i2pd-mingw-64-static \ + -DZLIB_ROOT=~/dev/stage -DBOOST_LIBRARYDIR:PATH=~/dev/boost_1_60_0/stage-mingw-64/lib \ + -DOPENSSL_ROOT_DIR:PATH=~/dev/stage + make + x86_64-w64-mingw32-strip i2pd.exe + By now, you should have a release build with stripped symbols. diff --git a/docs/building/ios.md b/docs/building/ios.md index 26688d21..c1753569 100644 --- a/docs/building/ios.md +++ b/docs/building/ios.md @@ -9,31 +9,30 @@ Prerequisites XCode7+, cmake 3.2+ Dependencies --------------- +------------ + - precompiled openssl - precompiled boost with modules `filesystem`, `program_options`, `date_time` and `system` -- ios-cmake toolchain from https://github.com/vovasty/ios-cmake.git +- ios-cmake toolchain from `https://github.com/vovasty/ios-cmake.git` Building ------------------------- -Assume you have folder structure +-------- -``` -lib - libboost_date_time.a - libboost_filesystem.a - libboost_program_options.a - libboost_system.a - libboost.a - libcrypto.a - libssl.a -include - boost - openssl -ios-cmake -i2pd -``` +Assume you have folder structure + lib/ + libboost_date_time.a + libboost_filesystem.a + libboost_program_options.a + libboost_system.a + libboost.a + libcrypto.a + libssl.a + include/ + boost/ + openssl/ + ios-cmake/ + i2pd/ ```bash mkdir -p build/simulator/lib build/ios/lib include/i2pd @@ -77,9 +76,10 @@ cp i2pd/*.h include/i2pd ``` Include into project ---------------------------- -1. add all libraries in `lib` folder to `Project linked frameworks`. -2. add `libc++` and `libz` libraries from system libraries to `Project linked frameworks`. -3. add path to i2p headers to your `Headers search paths` +-------------------- + +- add all libraries in `lib` folder to `Project linked frameworks`. +- add `libc++` and `libz` libraries from system libraries to `Project linked frameworks`. +- add path to i2p headers to your `Headers search paths` -Alternatively you may use swift wrapper https://github.com/vovasty/SwiftyI2P.git \ No newline at end of file +Alternatively you may use swift wrapper `https://github.com/vovasty/SwiftyI2P.git` diff --git a/docs/building/unix.md b/docs/building/unix.md index b1cc4148..b7a638f5 100644 --- a/docs/building/unix.md +++ b/docs/building/unix.md @@ -4,117 +4,124 @@ Building on Unix systems First of all we need to make sure that all dependencies are satisfied. This doc is trying to cover: + * [Debian/Ubuntu](#debian-ubuntu) (contains packaging instructions) * [Fedora/Centos](#fedora-centos) * [Fedora/Centos](#mac-os-x) * [FreeBSD](#freebsd) Make sure you have all required dependencies for your system successfully installed. +See [this](requirements.md) page for common requirements. If so then we are ready to go! Let's clone the repository and start building the i2pd: -```bash -git clone https://github.com/PurpleI2P/i2pd.git -cd i2pd/build -cmake -DCMAKE_BUILD_TYPE=Release # more options could be passed, see "CMake Options" -make # you may add VERBOSE=1 to cmdline for debugging -``` + + git clone https://github.com/PurpleI2P/i2pd.git + +Generic build process looks like this (with cmake): + + cd i2pd/build + cmake . # see "CMake Options" section below + make # you may add VERBOSE=1 to cmdline for debugging + +..or with quick-and-dirty way with just make: + + cd i2pd/ + make After successfull build i2pd could be installed with: -```bash -make install -``` -or you can just use 'make' once you have all dependencies (boost and openssl) installed -```bash -git clone https://github.com/PurpleI2P/i2pd.git -cd i2pd -make -``` + make install + +CMake Options +------------- + +Available CMake options(each option has a form of `=`, for more information see `man 1 cmake`): + +* `CMAKE_BUILD_TYPE` build profile (Debug/Release) +* `WITH_BINARY` build i2pd itself +* `WITH_LIBRARY` build libi2pd +* `WITH_STATIC` build static versions of library and i2pd binary +* `WITH_UPNP` build with UPnP support (requires libminiupnp) +* `WITH_AESNI` build with AES-NI support (ON/OFF) +* `WITH_HARDENING` enable hardening features (ON/OFF) (gcc only) +* `WITH_PCH` use pre-compiled header (experimental, speeds up build) + +Also there is `-L` flag for CMake that could be used to list current cached options: + + cmake -L Debian/Ubuntu ------------- You will need a compiler and other tools that could be installed with `build-essential` package: -```bash -sudo apt-get install build-essential -``` + + sudo apt-get install build-essential Also you will need a bunch of development libraries: -```bash -sudo apt-get install \ - libboost-chrono-dev \ - libboost-date-time-dev \ - libboost-filesystem-dev \ - libboost-program-options-dev \ - libboost-system-dev \ - libboost-thread-dev \ - libssl-dev -``` - -If you need UPnP support (don't forget to run CMake with `WITH_UPNP=ON`) miniupnpc development library should be installed: -```bash -sudo apt-get install libminiupnpc-dev -``` + + sudo apt-get install \ + libboost-chrono-dev \ + libboost-date-time-dev \ + libboost-filesystem-dev \ + libboost-program-options-dev \ + libboost-system-dev \ + libboost-thread-dev \ + libssl-dev + +If you need UPnP support miniupnpc development library should be installed (don't forget to rerun CMake with needed option): + + sudo apt-get install libminiupnpc-dev You may also build deb-package with the following: -```bash -sudo apt-get install fakeroot devscripts -cd i2pd -debuild --no-tgz-check -``` + + sudo apt-get install fakeroot devscripts + cd i2pd + debuild --no-tgz-check Fedora/Centos ------------- You will need a compiler and other tools to perform a build: -```bash -sudo yum install make cmake gcc gcc-c++ -``` -*Latest Fedora system using [DNF](https://en.wikipedia.org/wiki/DNF_(software)) instead of YUM by default, you may prefer to use DNF, but YUM should be ok* + sudo yum install make cmake gcc gcc-c++ Also you will need a bunch of development libraries -```bash -sudo yum install boost-devel openssl-devel -``` - -If you need UPnP support (don't forget to run CMake with `WITH_UPNP=ON`) miniupnpc development library should be installed: -```bash -miniupnpc-devel -``` -> *Centos 7 has CMake 2.8.11 in the official repositories that too old to build i2pd, CMake >=2.8.12 is required.* -> -> But you can use cmake3 from the epel repository: -> ```bash -> yum install epel-release -y -> yum install make cmake3 gcc gcc-c++ miniupnpc-devel boost-devel openssl-devel -y -> cmake3 -DWITH_LIBRARY=OFF -DWITH_UPNP=ON -DWITH_HARDENING=ON -DBUILD_SHARED_LIBS:BOOL=OFF -> make -> ``` + + sudo yum install boost-devel openssl-devel + +If you need UPnP support miniupnpc development library should be installed (don't forget to rerun CMake with needed option): + + sudo yum install miniupnpc-devel + +Latest Fedora systems using [DNF](https://en.wikipedia.org/wiki/DNF_(software)) instead of YUM by default, you may prefer to use DNF, but YUM should be ok + +Centos 7 has CMake 2.8.11 in the official repositories that too old to build i2pd, CMake >=2.8.12 is required. +But you can use cmake3 from the epel repository: + + yum install epel-release -y + yum install make cmake3 gcc gcc-c++ miniupnpc-devel boost-devel openssl-devel -y + +...and then use 'cmake3' instead 'cmake'. MAC OS X -------- -Requires [homebrew](http://brew.sh/) +Requires [homebrew](http://brew.sh) -```bash -brew install libressl boost -``` + brew install boost libressl Then build: -```bash -make HOMEBREW=1 -``` + make HOMEBREW=1 FreeBSD ------- -For 10.X use clang. You would also need boost and openssl ports. +For 10.X use clang. You would also need devel/boost-libs, security/openssl and devel/gmake ports. Type gmake, it invokes Makefile.bsd, make necessary changes there is required. -Branch 9.X has gcc v4.2, that knows nothing about required c++11 standart. +Branch 9.X has gcc v4.2, that is too old (not supports -std=c++11) Required ports: @@ -123,26 +130,6 @@ Required ports: * `lang/gcc47`(or later version) To use newer compiler you should set these variables(replace "47" with your actual gcc version): -```bash -export CC=/usr/local/bin/gcc47 -export CXX=/usr/local/bin/g++47 -``` -CMake Options -------------- - -Available CMake options(each option has a form of `=`, for more information see `man 1 cmake`): - -* `CMAKE_BUILD_TYPE` build profile (Debug/Release) -* `WITH_BINARY` build i2pd itself -* `WITH_LIBRARY` build libi2pd -* `WITH_STATIC` build static versions of library and i2pd binary -* `WITH_UPNP` build with UPnP support (requires libupnp) -* `WITH_AESNI` build with AES-NI support (ON/OFF) -* `WITH_HARDENING` enable hardening features (ON/OFF) (gcc only) -* `WITH_PCH` use pre-compiled header (experimental, speeds up build) - -Also there is `-L` flag for CMake that could be used to list current cached options: -```bash -cmake -L -``` + export CC=/usr/local/bin/gcc47 + export CXX=/usr/local/bin/g++47 diff --git a/docs/building/windows.md b/docs/building/windows.md index 5c9fda5a..0aa76877 100644 --- a/docs/building/windows.md +++ b/docs/building/windows.md @@ -23,81 +23,55 @@ paths like /c/dev/ for C:\dev\. msys2 ----- -### x86 (32-bit architecture) +Get install file `msys2-$ARCH-*.exe` from `https://msys2.github.io` -Get install file msys2-i686-*.exe from https://msys2.github.io. -open MSYS2 Shell (from Start menu). -Install all prerequisites and download i2pd source: +Where $ARCH is `i686` or `x86_64` (matching your system). -```bash -pacman -S mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-gcc git make -mkdir -p /c/dev/i2pd -cd /c/dev/i2pd -git clone https://github.com/PurpleI2P/i2pd.git -cd i2pd -export PATH=/mingw32/bin:/usr/bin # we need compiler on PATH which is usually heavily cluttered on Windows -make -``` - - -### x64 (64-bit architecture) - -Get install file msys2-x86_64-*.exe from https://msys2.github.io. -open MSYS2 Shell (from Start menu). -Install all prerequisites and download i2pd source: - -```bash -pacman -S mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-gcc git make -mkdir -p /c/dev/i2pd -cd /c/dev/i2pd -git clone https://github.com/PurpleI2P/i2pd.git -cd i2pd -export PATH=/mingw64/bin:/usr/bin # we need compiler on PATH which is usually heavily cluttered on Windows -make -``` +- Open MSYS2 Shell (from Start menu). +- Install all prerequisites and download i2pd source: + export ARCH='i686' # or 'x86_64' + export MINGW='mingw32' # or 'mingw64' + pacman -S mingw-w64-$ARCH-boost mingw-w64-$ARCH-openssl mingw-w64-$ARCH-gcc git make + mkdir -p /c/dev/i2pd + cd /c/dev/i2pd + git clone https://github.com/PurpleI2P/i2pd.git + cd i2pd + # we need compiler on PATH which is usually heavily cluttered on Windows + export PATH=/$MINGW/bin:/usr/bin + make ### Caveats -It is important to restrict PATH as described above. If you have -Strawberry Perl and/or Mercurial installed, it will pick up gcc & -openssl from the wrong places. - -If you do use precompiled headers to speed up compilation -(recommended), things can go wrong if compiler options have changed -for whatever reason. Just delete `stdafx.h.gch` found in your build -folder, note the file extension. +It is important to restrict PATH as described above. +If you have Strawberry Perl and/or Mercurial installed, +it will pick up gcc & openssl from the wrong places. -If you are an Arch Linux user, refrain from updating system with -`pacman -Syu`. Always update runtime separately as described on the -home page, otherwise you might end up with DLLs incompatibility -problems. +If you do use precompiled headers to speed up compilation (recommended), +things can go wrong if compiler options have changed for whatever reason. +Just delete `stdafx.h.gch` found in your build folder, note the file extension. +If you are an Arch Linux user, refrain from updating system with `pacman -Syu`. +Always update runtime separately as described on the home page, +otherwise you might end up with DLLs incompatibility problems. ### AES-NI -If your processor has -[AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set), -you use `make USE_AESNI=1`. No check is done however, it -will compile, but it might crash with `Illegal instruction` if not supported. +If your processor has [AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set), +use `make USE_AESNI=1` instead just `make`. No check is done however, it will compile, +but it might crash with `Illegal instruction` if this feature is not supported by your processor. -You should be able to run ./i2pd . If you need to start from the new -shell, consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* as -it adds`/minw32/bin` to the PATH. +You should be able to run ./i2pd . If you need to start from the new shell, +consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* +as it adds `/minw32/bin` to the PATH. ### UPnP -You can install it through the MSYS2 -and build with USE_UPNP key. - -```bash -pacman -S mingw-w64-i686-miniupnpc -make USE_UPNP=yes -``` -or -```bash -pacman -S mingw-w64-x86_64-miniupnpc -make USE_UPNP=yes -``` + +You can install it through the MSYS2 and build with `USE_UPNP` key. + + export ARCH='i686' # or 'x86_64' + pacman -S mingw-w64-$ARCH-miniupnpc + make USE_UPNP=yes Using Visual Studio ------------------- @@ -112,7 +86,6 @@ Requirements for building: * [Netwide assembler](http://www.nasm.us/) * Strawberry Perl or ActiveState Perl, do NOT try msys2 perl, it won't work - ### Building Boost Open a Command Prompt (there is no need to start Visual Studio command @@ -129,11 +102,9 @@ If you are on 64-bit Windows and you want to build 64-bit version as well After Boost is compiled, set the environment variable `BOOST_ROOT` to the directory Boost was unpacked to, e.g., C:\dev\boost. -If you are planning on building only particular variant, e.g. Debug -only and static linking, and/or you are out of space/time, you might -consider `--build-type=minimal`. Take a look at -[appveyor.yml](../appveyor.yml) for details on how test builds are done. - +If you are planning on building only particular variant, e.g. Debug only and static linking, +and/or you are out of space/time, you might consider `--build-type=minimal`. +Take a look at [appveyor.yml](../appveyor.yml) for details on how test builds are done. ### Building OpenSSL @@ -153,23 +124,19 @@ Now open Visual Studio command prompt and change directory to that with OpenSSL You should have it installed into C:\OpenSSL-Win32 by now. -Note that you might consider providing `-DOPENSSL_ROOT_DIR` to CMake -and/or create a symlink (with mklink /J) to C:\OpenSSL if you plan on -maintaining multiple versions, e.g. 64 bit and/or -static/shared. Consult `C:\Program Files -(x86)\CMake\share\cmake-3.3\Modules\FindOpenSSL.cmake` for details. - +Note that you might consider providing `-DOPENSSL_ROOT_DIR` to CMake and/or +create a symlink (with mklink /J) to C:\OpenSSL if you plan on maintain +multiple versions, e.g. 64 bit and/or static/shared. +See `C:\Program Files (x86)\CMake\share\cmake-3.3\Modules\FindOpenSSL.cmake` for details. ### Get miniupnpc -If you are behind a UPnP enabled router and don't feel like manually -configuring port forwarding, you should consider using -[MiniUPnP](http://miniupnp.free.fr) client. I2pd can be built capable -of using miniupnpc shared library (DLL) to open up necessary -port. You'd want to have include headers around to build i2pd with -support for this. Unpack client source code in a sibling folder, -e.g. C:\dev\miniupnpc . You may want to remove version number from -folder name included in downloaded archive. +If you are behind a UPnP enabled router and don't feel like manually configuring port forwarding, +you should consider using [MiniUPnP](http://miniupnp.free.fr) client. +I2pd can be built capable of using miniupnpc shared library (DLL) to open up necessary port. +You'd want to have include headers around to build i2pd with support for this. +Unpack client source code to subdir, e.g. `C:\dev\miniupnpc`. +You may want to remove version number from folder name included in downloaded archive. ### Creating Visual Studio project @@ -177,19 +144,16 @@ Start CMake GUI, navigate to i2pd directory, choose building directory, e.g. ./ Alternatively, if you feel adventurous, try that from the command line -``` -cd -mkdir out -cd out -cmake ..\build -G "Visual Studio 12 2013" -DWITH_UPNP=ON -DWITH_PCH=ON -DCMAKE_INSTALL_PREFIX:PATH=C:\dev\Debug_Win32_stage -``` - -WITH_UPNP will stay off, if necessary files are not found. + mkdir i2pd\out + cd i2pd\out + cmake ..\build -G "Visual Studio 12 2013" -DWITH_UPNP=ON -DWITH_PCH=ON -DCMAKE_INSTALL_PREFIX:PATH=C:\dev\Debug_Win32_stage +If necessary files are not found `WITH_UPNP` will stay off. ### Building i2pd -You can open generated solution/project with Visual Studio and build -from there, alternatively you can use `cmake --build . --config Release --target install` or +You can open generated solution/project with Visual Studio and build from there, +alternatively you can use `cmake --build . --config Release --target install` or [MSBuild tool](https://msdn.microsoft.com/en-us/library/dd293626.aspx) -`msbuild i2pd.sln /p:Configuration=Release`. + + msbuild i2pd.sln /p:Configuration=Release From be7f4c5da757dc5af833e2d4f92c68eec4797706 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 26 Oct 2016 00:00:00 +0000 Subject: [PATCH 10/65] * update changelog --- ChangeLog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2fdc0082..98b33e81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,21 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.10.0] - 2016-10-17 +### Added +- Datagram i2p tunnels +- Unique local addresses for server tunnels +- Configurable list of reseed servers and initial addressbook +- Configurable netid +- Initial iOS support + +### Changed +- Reduced file descriptiors usage +- Strict reseed checks enabled by default + +## Fixed +- Multiple fixes in I2CP and BOB implementations + ## [2.9.0] - 2016-08-12 ### Changed - Proxy refactoring & speedup From b8dcdece387c0df4033d9abad58bf437a4cb535e Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 26 Oct 2016 00:00:00 +0000 Subject: [PATCH 11/65] * Destination.cpp : drop use of i2p::util::lexical_cast(), make more compact code --- Destination.cpp | 110 +++++++++++++++++------------------------------- 1 file changed, 38 insertions(+), 72 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 5c81a64b..ee44b6f4 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -1,6 +1,5 @@ #include #include -#include #include "Crypto.h" #include "Log.h" #include "FS.h" @@ -18,83 +17,50 @@ namespace client m_PublishReplyToken (0), m_PublishConfirmationTimer (m_Service), m_PublishVerificationTimer (m_Service), m_CleanupTimer (m_Service) { - int inboundTunnelLen = DEFAULT_INBOUND_TUNNEL_LENGTH; - int outboundTunnelLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH; - int inboundTunnelsQuantity = DEFAULT_INBOUND_TUNNELS_QUANTITY; - int outboundTunnelsQuantity = DEFAULT_OUTBOUND_TUNNELS_QUANTITY; + int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH; + int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY; + int outLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH; + int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY; int numTags = DEFAULT_TAGS_TO_SEND; std::shared_ptr > explicitPeers; - if (params) - { - auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH); - if (it != params->end ()) - { - - int len = i2p::util::lexical_cast(it->second, inboundTunnelLen); - if (len >= 0) - { - inboundTunnelLen = len; - } - LogPrint (eLogInfo, "Destination: Inbound tunnel length set to ", inboundTunnelLen); - } - it = params->find (I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH); - if (it != params->end ()) - { - - int len = i2p::util::lexical_cast(it->second, outboundTunnelLen); - if (len >= 0) - { - outboundTunnelLen = len; - } - LogPrint (eLogInfo, "Destination: Outbound tunnel length set to ", outboundTunnelLen); - } - it = params->find (I2CP_PARAM_INBOUND_TUNNELS_QUANTITY); - if (it != params->end ()) - { - int quantity = i2p::util::lexical_cast(it->second, inboundTunnelsQuantity); - if (quantity > 0) - { - inboundTunnelsQuantity = quantity; - LogPrint (eLogInfo, "Destination: Inbound tunnels quantity set to ", quantity); - } - } - it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY); - if (it != params->end ()) - { - int quantity = i2p::util::lexical_cast(it->second, outboundTunnelsQuantity); - if (quantity > 0) - { - outboundTunnelsQuantity = quantity; - LogPrint (eLogInfo, "Destination: Outbound tunnels quantity set to ", quantity); - } - } - it = params->find (I2CP_PARAM_TAGS_TO_SEND); - if (it != params->end ()) - { - int tagsToSend = i2p::util::lexical_cast(it->second, numTags); - if (tagsToSend > 0) - { - numTags = tagsToSend; - LogPrint (eLogInfo, "Destination: Tags to send set to ", tagsToSend); - } - } - it = params->find (I2CP_PARAM_EXPLICIT_PEERS); - if (it != params->end ()) - { - explicitPeers = std::make_shared >(); - std::stringstream ss(it->second); - std::string b64; - while (std::getline (ss, b64, ',')) + try { + if (params) { + auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH); + if (it != params->end ()) + inLen = std::stoi(it->second); + it = params->find (I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH); + if (it != params->end ()) + outLen = std::stoi(it->second); + it = params->find (I2CP_PARAM_INBOUND_TUNNELS_QUANTITY); + if (it != params->end ()) + inQty = std::stoi(it->second); + it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY); + if (it != params->end ()) + outQty = std::stoi(it->second); + it = params->find (I2CP_PARAM_TAGS_TO_SEND); + if (it != params->end ()) + numTags = std::stoi(it->second); + LogPrint (eLogInfo, "Destination: parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags"); + it = params->find (I2CP_PARAM_EXPLICIT_PEERS); + if (it != params->end ()) { - i2p::data::IdentHash ident; - ident.FromBase64 (b64); - explicitPeers->push_back (ident); + explicitPeers = std::make_shared >(); + std::stringstream ss(it->second); + std::string b64; + while (std::getline (ss, b64, ',')) + { + i2p::data::IdentHash ident; + ident.FromBase64 (b64); + explicitPeers->push_back (ident); + LogPrint (eLogInfo, "Destination: Added to explicit peers list: ", b64); + } } - LogPrint (eLogInfo, "Destination: Explicit peers set to ", it->second); } - } + } catch (std::exception & ex) { + LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what()); + } SetNumTags (numTags); - m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inboundTunnelLen, outboundTunnelLen, inboundTunnelsQuantity, outboundTunnelsQuantity); + m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty); if (explicitPeers) m_Pool->SetExplicitPeers (explicitPeers); } From 143aaa2d28d939e598204035d7fabaee418f0ed7 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 26 Oct 2016 00:00:00 +0000 Subject: [PATCH 12/65] * util.h : drop i2p::util::lexical_cast(), not used anymore (#314) --- util.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/util.h b/util.h index 77b94995..ee4aade6 100644 --- a/util.h +++ b/util.h @@ -5,9 +5,9 @@ #include #include #include -#include #ifdef ANDROID +#include namespace std { template @@ -22,18 +22,6 @@ namespace i2p { namespace util { - /** - wrapper arround boost::lexical_cast that "never" fails - */ - template - T lexical_cast(const std::string & str, const T fallback) { - try { - return boost::lexical_cast(str); - } catch ( ... ) { - return fallback; - } - } - namespace net { int GetMTU (const boost::asio::ip::address& localAddress); From 9368a93279a2142a846140e066ee0739b4ee20e3 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 26 Oct 2016 00:00:00 +0000 Subject: [PATCH 13/65] * fgrep can't be used with regex --- Makefile | 2 +- Makefile.linux | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5cb32004..0e50364b 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ARLIB := libi2pd.a SHLIB_CLIENT := libi2pdclient.so ARLIB_CLIENT := libi2pdclient.a I2PD := i2pd -GREP := fgrep +GREP := grep DEPS := obj/make.dep include filelist.mk diff --git a/Makefile.linux b/Makefile.linux index ddff76a7..072fa685 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -55,7 +55,7 @@ IS_64 := $(shell $(CXX) -dumpmachine 2>&1 | $(GREP) -c "64") ifeq ($(USE_AESNI),yes) ifeq ($(IS_64),1) #check if AES-NI is supported by CPU -ifneq ($(shell grep -c aes /proc/cpuinfo),0) +ifneq ($(shell $(GREP) -c aes /proc/cpuinfo),0) CPU_FLAGS = -maes -DAESNI endif endif From 1286f1c968b8f7f4499dd4ab18525f0346d373a5 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 26 Oct 2016 13:02:19 -0400 Subject: [PATCH 14/65] inalidate shared routing path --- Destination.cpp | 14 +++++++------- Streaming.cpp | 10 +++++++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index ee44b6f4..c8384ff9 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -280,7 +280,7 @@ namespace client std::shared_ptr leaseSet; if (buf[DATABASE_STORE_TYPE_OFFSET] == 1) // LeaseSet { - LogPrint (eLogDebug, "Remote LeaseSet"); + LogPrint (eLogDebug, "Destination: Remote LeaseSet"); std::lock_guard lock(m_RemoteLeaseSetsMutex); auto it = m_RemoteLeaseSets.find (buf + DATABASE_STORE_KEY_OFFSET); if (it != m_RemoteLeaseSets.end ()) @@ -290,16 +290,16 @@ namespace client { leaseSet->Update (buf + offset, len - offset); if (leaseSet->IsValid ()) - LogPrint (eLogDebug, "Remote LeaseSet updated"); + LogPrint (eLogDebug, "Destination: Remote LeaseSet updated"); else { - LogPrint (eLogDebug, "Remote LeaseSet update failed"); + LogPrint (eLogDebug, "Destination: Remote LeaseSet update failed"); m_RemoteLeaseSets.erase (it); leaseSet = nullptr; } } else - LogPrint (eLogDebug, "Remote LeaseSet is older. Not updated"); + LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated"); } else { @@ -308,15 +308,15 @@ namespace client { if (leaseSet->GetIdentHash () != GetIdentHash ()) { - LogPrint (eLogDebug, "New remote LeaseSet added"); + LogPrint (eLogDebug, "Destination: New remote LeaseSet added"); m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet; } else - LogPrint (eLogDebug, "Own remote LeaseSet dropped"); + LogPrint (eLogDebug, "Destination: Own remote LeaseSet dropped"); } else { - LogPrint (eLogError, "New remote LeaseSet failed"); + LogPrint (eLogError, "Destination: New remote LeaseSet failed"); leaseSet = nullptr; } } diff --git a/Streaming.cpp b/Streaming.cpp index 077adce4..a98edc69 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -656,7 +656,11 @@ namespace stream m_CurrentOutboundTunnel->SendTunnelDataMsg (msgs); } else - LogPrint (eLogWarning, "Streaming: All leases are expired, sSID=", m_SendStreamID); + { + LogPrint (eLogWarning, "Streaming: Remote lease is not available, sSID=", m_SendStreamID); + if (m_RoutingSession) + m_RoutingSession->SetSharedRoutingPath (nullptr); // invalidate routing path + } } void Stream::SendUpdatedLeaseSet () @@ -824,13 +828,17 @@ namespace stream } else { + LogPrint (eLogWarning, "Streaming: All remote leases are expired"); m_RemoteLeaseSet = nullptr; m_CurrentRemoteLease = nullptr; // we have requested expired before, no need to do it twice } } else + { + LogPrint (eLogWarning, "Streaming: Remote LeaseSet not found"); m_CurrentRemoteLease = nullptr; + } } StreamingDestination::StreamingDestination (std::shared_ptr owner, uint16_t localPort, bool gzip): From a8a4ef82cd3eda269eab635d52c1319db5a847c3 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 26 Oct 2016 16:19:32 -0400 Subject: [PATCH 15/65] fixed android build --- util.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/util.h b/util.h index ee4aade6..b8de8b5a 100644 --- a/util.h +++ b/util.h @@ -15,6 +15,11 @@ std::string to_string(T value) { return boost::lexical_cast(value); } + +inline int stoi(const std::string& str) +{ + return boost::lexical_cast(str); +} } #endif From d708e7f682a1f8345c25e4e58463e7663e417194 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 26 Oct 2016 21:40:06 -0400 Subject: [PATCH 16/65] check if a lease has been excluded from LeaseSet --- Streaming.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Streaming.cpp b/Streaming.cpp index a98edc69..f1ceb7c9 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -637,7 +637,8 @@ namespace stream } auto ts = i2p::util::GetMillisecondsSinceEpoch (); - if (!m_CurrentRemoteLease || ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD) + if (!m_CurrentRemoteLease || !m_CurrentRemoteLease->endDate || // excluded from LeaseSet + ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD) UpdateCurrentRemoteLease (true); if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD) { From 2dcb91b28450d60bb4bb6c3dc3c66d0fd0bbe766 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 27 Oct 2016 20:46:05 -0400 Subject: [PATCH 17/65] don't create same incoming stream twice --- Streaming.cpp | 12 +++++++++++- Streaming.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Streaming.cpp b/Streaming.cpp index f1ceb7c9..852d11a6 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -844,6 +844,7 @@ namespace stream StreamingDestination::StreamingDestination (std::shared_ptr owner, uint16_t localPort, bool gzip): m_Owner (owner), m_LocalPort (localPort), m_Gzip (gzip), + m_LastIncomingReceiveStreamID (0), m_PendingIncomingTimer (m_Owner->GetService ()), m_ConnTrackTimer(m_Owner->GetService()), m_ConnsPerMinute(DEFAULT_MAX_CONNS_PER_MIN), @@ -899,8 +900,15 @@ namespace stream { if (packet->IsSYN () && !packet->GetSeqn ()) // new incoming stream { - auto incomingStream = CreateNewIncomingStream (); uint32_t receiveStreamID = packet->GetReceiveStreamID (); + if (receiveStreamID == m_LastIncomingReceiveStreamID) + { + // already pending + LogPrint(eLogWarning, "Streaming: Incoming streaming with rSID=", receiveStreamID, " already exists"); + delete packet; // drop it, because previous should be connected + return; + } + auto incomingStream = CreateNewIncomingStream (); incomingStream->HandleNextPacket (packet); // SYN auto ident = incomingStream->GetRemoteIdentity(); if(ident) @@ -914,6 +922,8 @@ namespace stream return; } } + m_LastIncomingReceiveStreamID = receiveStreamID; + // handle saved packets if any { auto it = m_SavedPackets.find (receiveStreamID); diff --git a/Streaming.h b/Streaming.h index 2be724ed..e4a1562c 100644 --- a/Streaming.h +++ b/Streaming.h @@ -253,6 +253,7 @@ namespace stream std::mutex m_StreamsMutex; std::map > m_Streams; // sendStreamID->stream Acceptor m_Acceptor; + uint32_t m_LastIncomingReceiveStreamID; std::list > m_PendingIncomingStreams; boost::asio::deadline_timer m_PendingIncomingTimer; std::map > m_SavedPackets; // receiveStreamID->packets, arrived before SYN From 5c64c2ff42dc478058095a18daed640e873628e0 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 28 Oct 2016 11:33:11 -0400 Subject: [PATCH 18/65] handle stream ternimation properly --- SAM.cpp | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/SAM.cpp b/SAM.cpp index 2864cd6f..6707a6dc 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -587,10 +587,28 @@ namespace client void SAMSocket::I2PReceive () { if (m_Stream) - m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE), - std::bind (&SAMSocket::HandleI2PReceive, shared_from_this (), - std::placeholders::_1, std::placeholders::_2), - SAM_SOCKET_CONNECTION_MAX_IDLE); + { + if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || + 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::placeholders::_1, std::placeholders::_2), + SAM_SOCKET_CONNECTION_MAX_IDLE); + } + else // closed by peer + { + // get remaning data + auto len = m_Stream->ReadSome (m_StreamBuffer, 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)); + } + else // no more data + Terminate (); + } + } } void SAMSocket::HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) @@ -599,6 +617,14 @@ namespace client { LogPrint (eLogError, "SAM: stream read error: ", ecode.message ()); 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 + else + Terminate (); + } + else Terminate (); } else From 5f396d6311949cf08eb5d0ba209cac2313b0073b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 28 Oct 2016 12:50:26 -0400 Subject: [PATCH 19/65] add option to only connect to certain routers --- Config.cpp | 1 + Daemon.cpp | 36 +++++++++++++++++--- NetDb.cpp | 11 +++--- Transports.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++-------- Transports.h | 10 +++++- Tunnel.cpp | 8 +++-- 6 files changed, 130 insertions(+), 26 deletions(-) diff --git a/Config.cpp b/Config.cpp index 924f244b..80a2ef8a 100644 --- a/Config.cpp +++ b/Config.cpp @@ -184,6 +184,7 @@ namespace config { trust.add_options() ("trust.enabled", value()->default_value(false), "enable explicit trust options") ("trust.family", value()->default_value(""), "Router Familiy to trust for first hops") + ("trust.routers", value()->default_value(""), "Only Connect to these routers") ("trust.hidden", value()->default_value(false), "should we hide our router from other routers?"); m_OptionsDesc diff --git a/Daemon.cpp b/Daemon.cpp index e0c45ac3..ce2f4173 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -194,12 +194,40 @@ namespace i2p { LogPrint(eLogInfo, "Daemon: explicit trust enabled"); std::string fam; i2p::config::GetOption("trust.family", fam); + std::string routers; i2p::config::GetOption("trust.routers", routers); + bool restricted = false; if (fam.length() > 0) { - LogPrint(eLogInfo, "Daemon: setting restricted routes to use family ", fam); - i2p::transport::transports.RestrictRoutes({fam}); - } else - LogPrint(eLogError, "Daemon: no family specified for restricted routes"); + std::set fams; + size_t pos = 0, comma; + do + { + comma = fam.find (',', pos); + fams.insert (fam.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos)); + pos = comma + 1; + } + while (comma != std::string::npos); + i2p::transport::transports.RestrictRoutesToFamilies(fams); + restricted = fams.size() > 0; + } + if (routers.length() > 0) { + std::set idents; + size_t pos = 0, comma; + do + { + comma = routers.find (',', pos); + i2p::data::IdentHash ident; + ident.FromBase64 (routers.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos)); + idents.insert (ident); + pos = comma + 1; + } + while (comma != std::string::npos); + LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routesrs"); + i2p::transport::transports.RestrictRoutesToRouters(idents); + restricted = idents.size() > 0; + } + if(!restricted) + LogPrint(eLogError, "Daemon: no trusted routers of families specififed"); } bool hidden; i2p::config::GetOption("trust.hidden", hidden); if (hidden) diff --git a/NetDb.cpp b/NetDb.cpp index 2c9c4395..dbfa4bcb 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -126,10 +126,8 @@ namespace data i2p::context.CleanupDestination (); lastDestinationCleanup = ts; } - // if we're in hidden mode don't publish or explore - // if (m_HiddenMode) continue; - - if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL) // publish + + if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish { Publish (); lastPublish = ts; @@ -147,8 +145,9 @@ namespace data numRouters = 800/numRouters; if (numRouters < 1) numRouters = 1; if (numRouters > 9) numRouters = 9; - m_Requests.ManageRequests (); - Explore (numRouters); + m_Requests.ManageRequests (); + if(!m_HiddenMode) + Explore (numRouters); lastExploratory = ts; } } diff --git a/Transports.cpp b/Transports.cpp index a29cac15..2efcbedf 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -240,7 +240,8 @@ namespace transport for (auto& it: msgs) i2p::HandleI2NPMessage (it); return; - } + } + if(RoutesRestricted() && ! IsRestrictedPeer(ident)) return; auto it = m_Peers.find (ident); if (it == m_Peers.end ()) { @@ -494,6 +495,12 @@ namespace transport void Transports::DetectExternalIP () { + if (RoutesRestricted()) + { + LogPrint(eLogInfo, "Transports: restricted routes enabled, not detecting ip"); + i2p::context.SetStatus (eRouterStatusFirewalled); + return; + } if (m_SSUServer) { #ifndef MESHNET @@ -520,8 +527,10 @@ namespace transport void Transports::PeerTest () { + if (RoutesRestricted()) return; if (m_SSUServer) { + bool statusChanged = false; for (int i = 0; i < 5; i++) { @@ -578,6 +587,12 @@ namespace transport } else // incoming connection { + if(RoutesRestricted() && ! IsRestrictedPeer(ident)) { + // not trusted + LogPrint(eLogWarning, "Transports: closing untrusted inbound connection from ", ident.ToBase64()); + session->Done(); + return; + } session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore std::unique_lock l(m_PeersMutex); m_Peers.insert (std::make_pair (ident, Peer{ 0, nullptr, { session }, i2p::util::GetSecondsSinceEpoch (), {} })); @@ -655,7 +670,7 @@ namespace transport std::advance (it, rand () % m_Peers.size ()); return it != m_Peers.end () ? it->second.router : nullptr; } - void Transports::RestrictRoutes(std::vector families) + void Transports::RestrictRoutesToFamilies(std::set families) { std::lock_guard lock(m_FamilyMutex); m_TrustedFamilies.clear(); @@ -663,22 +678,71 @@ namespace transport m_TrustedFamilies.push_back(fam); } + void Transports::RestrictRoutesToRouters(std::set routers) + { + std::unique_lock lock(m_TrustedRoutersMutex); + m_TrustedRouters.clear(); + for (const auto & ri : routers ) + m_TrustedRouters.push_back(ri); + } + bool Transports::RoutesRestricted() const { - std::lock_guard lock(m_FamilyMutex); - return m_TrustedFamilies.size() > 0; + std::unique_lock famlock(m_FamilyMutex); + std::unique_lock routerslock(m_TrustedRoutersMutex); + return m_TrustedFamilies.size() > 0 || m_TrustedRouters.size() > 0; } /** XXX: if routes are not restricted this dies */ - std::shared_ptr Transports::GetRestrictedPeer() const { - std::string fam; - { - std::lock_guard lock(m_FamilyMutex); - // TODO: random family (?) - fam = m_TrustedFamilies[0]; - } - boost::to_lower(fam); - return i2p::data::netdb.GetRandomRouterInFamily(fam); + std::shared_ptr Transports::GetRestrictedPeer() const + { + { + std::lock_guard l(m_FamilyMutex); + std::string fam; + auto sz = m_TrustedFamilies.size(); + if(sz > 1) + { + auto it = m_TrustedFamilies.begin (); + std::advance(it, rand() % sz); + fam = *it; + boost::to_lower(fam); + } + else if (sz == 1) + { + fam = m_TrustedFamilies[0]; + } + if (fam.size()) + return i2p::data::netdb.GetRandomRouterInFamily(fam); + } + { + std::unique_lock l(m_TrustedRoutersMutex); + auto sz = m_TrustedRouters.size(); + if (sz) + { + if(sz == 1) + return i2p::data::netdb.FindRouter(m_TrustedRouters[0]); + auto it = m_TrustedRouters.begin(); + std::advance(it, rand() % sz); + return i2p::data::netdb.FindRouter(*it); + } + } + return nullptr; } + + bool Transports::IsRestrictedPeer(const i2p::data::IdentHash & ih) const + { + { + std::unique_lock l(m_TrustedRoutersMutex); + for (const auto & r : m_TrustedRouters ) + if ( r == ih ) return true; + } + { + std::unique_lock l(m_FamilyMutex); + auto ri = i2p::data::netdb.FindRouter(ih); + for (const auto & fam : m_TrustedFamilies) + if(ri->IsFamily(fam)) return true; + } + return false; + } } } diff --git a/Transports.h b/Transports.h index 81063916..9ecfd719 100644 --- a/Transports.h +++ b/Transports.h @@ -110,7 +110,11 @@ namespace transport /** do we want to use restricted routes? */ bool RoutesRestricted() const; /** restrict routes to use only these router families for first hops */ - void RestrictRoutes(std::vector families); + void RestrictRoutesToFamilies(std::set families); + /** restrict routes to use only these routers for first hops */ + void RestrictRoutesToRouters(std::set routers); + + bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const; void PeerTest (); @@ -157,6 +161,10 @@ namespace transport /** which router families to trust for first hops */ std::vector m_TrustedFamilies; mutable std::mutex m_FamilyMutex; + + /** which routers for first hop to trust */ + std::vector m_TrustedRouters; + mutable std::mutex m_TrustedRoutersMutex; public: diff --git a/Tunnel.cpp b/Tunnel.cpp index 7d2e6735..44d92d75 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -644,7 +644,9 @@ namespace tunnel { // trying to create one more oubound tunnel auto inboundTunnel = GetNextInboundTunnel (); - auto router = i2p::data::netdb.GetRandomRouter (); + auto router = i2p::transport::transports.RoutesRestricted() ? + i2p::transport::transports.GetRestrictedPeer() : + i2p::data::netdb.GetRandomRouter (); if (!inboundTunnel || !router) return; LogPrint (eLogDebug, "Tunnel: creating one hop outbound tunnel"); CreateTunnel ( @@ -706,7 +708,9 @@ namespace tunnel if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 5) { // trying to create one more inbound tunnel - auto router = i2p::data::netdb.GetRandomRouter (); + auto router = i2p::transport::transports.RoutesRestricted() ? + i2p::transport::transports.GetRestrictedPeer() : + i2p::data::netdb.GetRandomRouter (); if (!router) { LogPrint (eLogWarning, "Tunnel: can't find any router, skip creating tunnel"); return; From c5e1823f1588c8904ab5f0b1ffbcd682f19ef476 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 28 Oct 2016 13:11:50 -0400 Subject: [PATCH 20/65] dont't set to firewalled, ssu will try introducers --- Transports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Transports.cpp b/Transports.cpp index 2efcbedf..cfbc3739 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -498,7 +498,7 @@ namespace transport if (RoutesRestricted()) { LogPrint(eLogInfo, "Transports: restricted routes enabled, not detecting ip"); - i2p::context.SetStatus (eRouterStatusFirewalled); + i2p::context.SetStatus (eRouterStatusOK); return; } if (m_SSUServer) From 578083df3ef5ba5e2babd1a88e2b3a459a91e4a2 Mon Sep 17 00:00:00 2001 From: l-n-s Date: Fri, 28 Oct 2016 13:18:35 -0400 Subject: [PATCH 21/65] Add libdl (-ldl) flag. Fixes openssl errors when building statically. --- Makefile.linux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.linux b/Makefile.linux index 072fa685..28081c81 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -39,7 +39,7 @@ ifeq ($(USE_STATIC),yes) LDLIBS += $(LIBDIR)/libssl.a LDLIBS += $(LIBDIR)/libcrypto.a LDLIBS += $(LIBDIR)/libz.a - LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt + LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt -ldl USE_AESNI := no else LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread From 4f4748b8dfdaba6563672adf5cd73908444fe2e9 Mon Sep 17 00:00:00 2001 From: l-n-s Date: Fri, 28 Oct 2016 15:57:18 -0400 Subject: [PATCH 22/65] Update nat option: if nat=false, skip reachability testing --- Config.cpp | 10 +--------- Transports.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Config.cpp b/Config.cpp index 924f244b..6a4c20d1 100644 --- a/Config.cpp +++ b/Config.cpp @@ -27,10 +27,6 @@ namespace config { variables_map m_Options; void Init() { - bool nat = true; -#ifdef MESHNET - nat = false; -#endif options_description general("General options"); general.add_options() @@ -45,7 +41,7 @@ namespace config { ("datadir", value()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)") ("host", value()->default_value("0.0.0.0"), "External IP") ("ifname", value()->default_value(""), "network interface to bind to") - ("nat", value()->zero_tokens()->default_value(nat), "should we assume we are behind NAT?") + ("nat", value()->zero_tokens()->default_value(true), "should we assume we are behind NAT?") ("port", value()->default_value(0), "Port to listen for incoming connections (default: auto)") ("ipv4", value()->zero_tokens()->default_value(true), "Enable communication through ipv4") ("ipv6", value()->zero_tokens()->default_value(false), "Enable communication through ipv6") @@ -153,9 +149,6 @@ namespace config { reseed.add_options() ("reseed.verify", value()->default_value(false), "Verify .su3 signature") ("reseed.file", value()->default_value(""), "Path to .su3 file") -#ifdef MESHNET - ("reseed.urls", value()->default_value("https://reseed.i2p.rocks:8443/"), "Reseed URLs, separated by comma") -#else ("reseed.urls", value()->default_value( "https://reseed.i2p-projekt.de/," "https://i2p.mooo.com/netDb/," @@ -169,7 +162,6 @@ namespace config { "https://reseed-ru.lngserv.ru/," "https://reseed.atomike.ninja/" ), "Reseed URLs, separated by comma") -#endif ; options_description addressbook("AddressBook options"); diff --git a/Transports.cpp b/Transports.cpp index a29cac15..adb8da06 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -4,6 +4,7 @@ #include "I2NPProtocol.h" #include "NetDb.h" #include "Transports.h" +#include "Config.h" using namespace i2p::data; @@ -496,9 +497,9 @@ namespace transport { if (m_SSUServer) { -#ifndef MESHNET - i2p::context.SetStatus (eRouterStatusTesting); -#endif + bool nat; i2p::config::GetOption("nat", nat); + if (nat) + i2p::context.SetStatus (eRouterStatusTesting); for (int i = 0; i < 5; i++) { From df36b0eb7ea4406a0d0910b1794ff91aec86ac78 Mon Sep 17 00:00:00 2001 From: l-n-s Date: Fri, 28 Oct 2016 16:17:48 -0400 Subject: [PATCH 23/65] Uppercase first letters in config help --- Config.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Config.cpp b/Config.cpp index 6a4c20d1..8ac6d7d3 100644 --- a/Config.cpp +++ b/Config.cpp @@ -40,8 +40,8 @@ namespace config { ("family", value()->default_value(""), "Specify a family, router belongs to") ("datadir", value()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)") ("host", value()->default_value("0.0.0.0"), "External IP") - ("ifname", value()->default_value(""), "network interface to bind to") - ("nat", value()->zero_tokens()->default_value(true), "should we assume we are behind NAT?") + ("ifname", value()->default_value(""), "Network interface to bind to") + ("nat", value()->zero_tokens()->default_value(true), "Should we assume we are behind NAT?") ("port", value()->default_value(0), "Port to listen for incoming connections (default: auto)") ("ipv4", value()->zero_tokens()->default_value(true), "Enable communication through ipv4") ("ipv6", value()->zero_tokens()->default_value(false), "Enable communication through ipv6") @@ -51,8 +51,8 @@ namespace config { ("notransit", value()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup") ("floodfill", value()->zero_tokens()->default_value(false), "Router will be floodfill") ("bandwidth", value()->default_value(""), "Bandwidth limit: integer in kbps or letters: L (32), O (256), P (2048), X (>9000)") - ("ntcp", value()->zero_tokens()->default_value(true), "enable ntcp transport") - ("ssu", value()->zero_tokens()->default_value(true), "enable ssu transport") + ("ntcp", value()->zero_tokens()->default_value(true), "Enable NTCP transport") + ("ssu", value()->zero_tokens()->default_value(true), "Enable SSU transport") #ifdef _WIN32 ("svcctl", value()->default_value(""), "Windows service management ('install' or 'remove')") ("insomnia", value()->zero_tokens()->default_value(false), "Prevent system from sleeping") @@ -174,9 +174,9 @@ namespace config { options_description trust("Trust options"); trust.add_options() - ("trust.enabled", value()->default_value(false), "enable explicit trust options") + ("trust.enabled", value()->default_value(false), "Enable explicit trust options") ("trust.family", value()->default_value(""), "Router Familiy to trust for first hops") - ("trust.hidden", value()->default_value(false), "should we hide our router from other routers?"); + ("trust.hidden", value()->default_value(false), "Should we hide our router from other routers?"); m_OptionsDesc .add(general) From 647175cf12bfb08fea148ae4904e4fdaa250c28e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 30 Oct 2016 09:29:43 -0400 Subject: [PATCH 24/65] correct RTO reset --- Streaming.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index 852d11a6..97cfad0a 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -693,8 +693,7 @@ namespace stream { m_ResendTimer.cancel (); // check for invalid value - if (m_RTO <= 0) - m_RTO = 1; + if (m_RTO <= 0) m_RTO = INITIAL_RTO; m_ResendTimer.expires_from_now (boost::posix_time::milliseconds(m_RTO)); m_ResendTimer.async_wait (std::bind (&Stream::HandleResendTimer, shared_from_this (), std::placeholders::_1)); @@ -901,13 +900,13 @@ namespace stream if (packet->IsSYN () && !packet->GetSeqn ()) // new incoming stream { uint32_t receiveStreamID = packet->GetReceiveStreamID (); - if (receiveStreamID == m_LastIncomingReceiveStreamID) + /* if (receiveStreamID == m_LastIncomingReceiveStreamID) { // already pending LogPrint(eLogWarning, "Streaming: Incoming streaming with rSID=", receiveStreamID, " already exists"); delete packet; // drop it, because previous should be connected return; - } + } */ auto incomingStream = CreateNewIncomingStream (); incomingStream->HandleNextPacket (packet); // SYN auto ident = incomingStream->GetRemoteIdentity(); From 754ad20effbf8558529d2c855b011467bc6a2bc8 Mon Sep 17 00:00:00 2001 From: Lehi Toskin Date: Mon, 31 Oct 2016 03:27:27 -0700 Subject: [PATCH 25/65] gracefull -> graceful --- Daemon.h | 2 +- DaemonLinux.cpp | 14 +++++++------- HTTPServer.cpp | 14 +++++++------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Daemon.h b/Daemon.h index 85b31240..2bc05462 100644 --- a/Daemon.h +++ b/Daemon.h @@ -97,7 +97,7 @@ namespace i2p public: - int gracefullShutdownInterval; // in seconds + int gracefulShutdownInterval; // in seconds }; #endif diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 87e50a72..7d791bf2 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -25,11 +25,11 @@ void handle_signal(int sig) i2p::client::context.ReloadConfig(); break; case SIGINT: - if (i2p::context.AcceptsTunnels () && !Daemon.gracefullShutdownInterval) + if (i2p::context.AcceptsTunnels () && !Daemon.gracefulShutdownInterval) { i2p::context.SetAcceptsTunnels (false); - Daemon.gracefullShutdownInterval = 10*60; // 10 minutes - LogPrint(eLogInfo, "Graceful shutdown after ", Daemon.gracefullShutdownInterval, " seconds"); + Daemon.gracefulShutdownInterval = 10*60; // 10 minutes + LogPrint(eLogInfo, "Graceful shutdown after ", Daemon.gracefulShutdownInterval, " seconds"); } else Daemon.running = 0; @@ -110,7 +110,7 @@ namespace i2p return false; } } - gracefullShutdownInterval = 0; // not specified + gracefulShutdownInterval = 0; // not specified // Signal handler struct sigaction sa; @@ -137,10 +137,10 @@ namespace i2p while (running) { std::this_thread::sleep_for (std::chrono::seconds(1)); - if (gracefullShutdownInterval) + if (gracefulShutdownInterval) { - gracefullShutdownInterval--; // - 1 second - if (gracefullShutdownInterval <= 0) + gracefulShutdownInterval--; // - 1 second + if (gracefulShutdownInterval <= 0) { LogPrint(eLogInfo, "Graceful shutdown"); return; diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 487e9c83..890daf9e 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -196,7 +196,7 @@ namespace http { } s << "
\r\n"; #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) - if (auto remains = Daemon.gracefullShutdownInterval) { + if (auto remains = Daemon.gracefulShutdownInterval) { s << "Stopping in: "; s << remains << " seconds"; s << "
\r\n"; @@ -416,13 +416,13 @@ namespace http { else s << " Accept transit tunnels
\r\n"; #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) - if (Daemon.gracefullShutdownInterval) - s << " Cancel gracefull shutdown
"; + if (Daemon.gracefulShutdownInterval) + s << " Cancel graceful shutdown
"; else - s << " Start gracefull shutdown
\r\n"; + s << " Start graceful shutdown
\r\n"; #endif #ifdef WIN32_APP - s << " Gracefull shutdown
\r\n"; + s << " Graceful shutdown
\r\n"; #endif s << " Force shutdown
\r\n"; } @@ -755,7 +755,7 @@ namespace http { else if (cmd == HTTP_COMMAND_SHUTDOWN_START) { i2p::context.SetAcceptsTunnels (false); #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) - Daemon.gracefullShutdownInterval = 10*60; + Daemon.gracefulShutdownInterval = 10*60; #endif #ifdef WIN32_APP i2p::win32::GracefulShutdown (); @@ -763,7 +763,7 @@ namespace http { } else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) { i2p::context.SetAcceptsTunnels (true); #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) - Daemon.gracefullShutdownInterval = 0; + Daemon.gracefulShutdownInterval = 0; #endif } else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) { Daemon.running = false; From bef628212efcae396cf345b0d747287534bc300c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 31 Oct 2016 09:46:59 -0400 Subject: [PATCH 26/65] fixed corrupted buffer duing IRC handshake --- I2PTunnel.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 0ce9a7e3..8756da8b 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -275,26 +275,24 @@ namespace client void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len) { - if (m_NeedsWebIrc) { + m_OutPacket.str (""); + if (m_NeedsWebIrc) + { m_NeedsWebIrc = false; - m_OutPacket.str (""); - m_OutPacket << "WEBIRC " << this->m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " 127.0.0.1\n"; - I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ()); + m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " 127.0.0.1\n"; } - std::string line; - m_OutPacket.str (""); m_InPacket.clear (); m_InPacket.write ((const char *)buf, len); while (!m_InPacket.eof () && !m_InPacket.fail ()) { + std::string line; std::getline (m_InPacket, line); - if (line.length () == 0 && m_InPacket.eof ()) { + if (line.length () == 0 && m_InPacket.eof ()) m_InPacket.str (""); - } auto pos = line.find ("USER"); - if (pos != std::string::npos && pos == 0) + if (!pos) // start of line { pos = line.find (" "); pos++; @@ -304,9 +302,9 @@ namespace client m_OutPacket << line.substr (0, pos); m_OutPacket << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()); m_OutPacket << line.substr (nextpos) << '\n'; - } else { + } + else m_OutPacket << line << '\n'; - } } I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ()); } From a41f1797851bcfc81e5fde2b57d91f3bfac241f8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 31 Oct 2016 14:00:31 -0400 Subject: [PATCH 27/65] get home directory from EXTERNAL_STORAGE for andorid --- FS.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/FS.cpp b/FS.cpp index 84b30f21..74da7ee9 100644 --- a/FS.cpp +++ b/FS.cpp @@ -45,18 +45,18 @@ namespace fs { return; } #if defined(WIN32) || defined(_WIN32) - char localAppData[MAX_PATH]; - // check executable directory first - GetModuleFileName (NULL, localAppData, MAX_PATH); - auto execPath = boost::filesystem::path(localAppData).parent_path(); - // if config file exists in .exe's folder use it - if(boost::filesystem::exists(execPath/"i2pd.conf")) // TODO: magic string - dataDir = execPath.string (); - else - { - // otherwise %appdata% - SHGetFolderPath(NULL, CSIDL_APPDATA, 0, NULL, localAppData); - dataDir = std::string(localAppData) + "\\" + appName; + char localAppData[MAX_PATH]; + // check executable directory first + GetModuleFileName (NULL, localAppData, MAX_PATH); + auto execPath = boost::filesystem::path(localAppData).parent_path(); + // if config file exists in .exe's folder use it + if(boost::filesystem::exists(execPath/"i2pd.conf")) // TODO: magic string + dataDir = execPath.string (); + else + { + // otherwise %appdata% + SHGetFolderPath(NULL, CSIDL_APPDATA, 0, NULL, localAppData); + dataDir = std::string(localAppData) + "\\" + appName; } return; #elif defined(MAC_OSX) @@ -66,9 +66,11 @@ namespace fs { return; #else /* other unix */ #if defined(ANDROID) - if (boost::filesystem::exists("/sdcard")) + const char * ext = getenv("EXTERNAL_STORAGE"); + if (!ext) ext = "/sdcard"; + if (boost::filesystem::exists(ext)) { - dataDir = "/sdcard/" + appName; + dataDir = ext + appName; return; } // otherwise use /data/files From a4883cfa15cb316441c2537d5425520bce3f86f8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 31 Oct 2016 15:13:43 -0400 Subject: [PATCH 28/65] print tunnel peers in direct order --- Tunnel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tunnel.cpp b/Tunnel.cpp index 44d92d75..0c1b278a 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -184,10 +184,11 @@ namespace tunnel void Tunnel::PrintHops (std::stringstream& s) const { - for (auto& it: m_Hops) + // hops are in inverted order, we must print in direct order + for (auto it = m_Hops.rbegin (); it != m_Hops.rend (); it++) { s << " ⇒ "; - s << i2p::data::GetIdentHashAbbreviation (it->ident->GetIdentHash ()); + s << i2p::data::GetIdentHashAbbreviation ((*it)->ident->GetIdentHash ()); } } From b526718846421bc98db4fdaf6e0255aa197b610b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 31 Oct 2016 15:42:50 -0400 Subject: [PATCH 29/65] show HTTP proxy as client tunnel --- ClientContext.h | 1 + HTTPServer.cpp | 9 +++++++++ I2PService.h | 1 + 3 files changed, 11 insertions(+) diff --git a/ClientContext.h b/ClientContext.h index 1a41acfc..d82058c6 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -110,6 +110,7 @@ namespace client const decltype(m_ServerTunnels)& GetServerTunnels () const { return m_ServerTunnels; }; const decltype(m_ClientForwards)& GetClientForwards () const { return m_ClientForwards; } const decltype(m_ServerForwards)& GetServerForwards () const { return m_ServerForwards; } + const i2p::proxy::HTTPProxy * GetHttpProxy () const { return m_HttpProxy; } }; extern ClientContext context; diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 890daf9e..99edf508 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -549,6 +549,15 @@ namespace http { s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; } + auto httpProxy = i2p::client::context.GetHttpProxy (); + if (httpProxy) + { + auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash(); + s << ""; + s << "HTTP Proxy" << " ⇐ "; + s << i2p::client::context.GetAddressBook ().ToAddress(ident); + s << "
\r\n"<< std::endl; + } s << "
\r\nServer Tunnels:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetServerTunnels ()) { diff --git a/I2PService.h b/I2PService.h index 2df11909..59746a6f 100644 --- a/I2PService.h +++ b/I2PService.h @@ -38,6 +38,7 @@ namespace client } inline std::shared_ptr GetLocalDestination () { return m_LocalDestination; } + inline std::shared_ptr GetLocalDestination () const { return m_LocalDestination; } inline void SetLocalDestination (std::shared_ptr dest) { m_LocalDestination = dest; } void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0); From 3d4e2a275c5be14014fd54b1c1ccb5590366379a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 31 Oct 2016 18:10:33 -0400 Subject: [PATCH 30/65] correct separator for android --- FS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FS.cpp b/FS.cpp index 74da7ee9..64484b15 100644 --- a/FS.cpp +++ b/FS.cpp @@ -70,7 +70,7 @@ namespace fs { if (!ext) ext = "/sdcard"; if (boost::filesystem::exists(ext)) { - dataDir = ext + appName; + dataDir = std::string (ext) + "/" + appName; return; } // otherwise use /data/files From b4e9ed7d18f076ed090ffb8912f6346e29c04285 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 20 Oct 2016 09:12:15 -0400 Subject: [PATCH 31/65] add web socket ui --- ClientContext.cpp | 2 +- ClientContext.h | 2 +- Config.cpp | 15 ++++- Daemon.cpp | 25 +++++++- Event.cpp | 28 +++++++++ Event.h | 37 ++++++++++++ I2NPProtocol.cpp | 1 - Log.h | 4 +- NTCPSession.cpp | 4 ++ SSUData.cpp | 8 +++ TransportSession.h | 4 +- Transports.cpp | 15 ++++- Websocket.cpp | 136 +++++++++++++++++++++++++++++++++++++++++++ Websocket.h | 30 ++++++++++ build/CMakeLists.txt | 20 +++++++ 15 files changed, 322 insertions(+), 9 deletions(-) create mode 100644 Event.cpp create mode 100644 Event.h create mode 100644 Websocket.cpp create mode 100644 Websocket.h diff --git a/ClientContext.cpp b/ClientContext.cpp index b7300ad2..215768c2 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -290,7 +290,7 @@ namespace client } return infos; } - + std::shared_ptr ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType, const std::map * params) { diff --git a/ClientContext.h b/ClientContext.h index d82058c6..356f28c4 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -68,7 +68,7 @@ namespace client const SAMBridge * GetSAMBridge () const { return m_SamBridge; }; std::vector > GetForwardInfosFor(const i2p::data::IdentHash & destination); - + private: void ReadTunnels (); diff --git a/Config.cpp b/Config.cpp index 4750a9e3..99f4b0bb 100644 --- a/Config.cpp +++ b/Config.cpp @@ -176,9 +176,21 @@ namespace config { trust.add_options() ("trust.enabled", value()->default_value(false), "Enable explicit trust options") ("trust.family", value()->default_value(""), "Router Familiy to trust for first hops") +<<<<<<< HEAD ("trust.routers", value()->default_value(""), "Only Connect to these routers") ("trust.hidden", value()->default_value(false), "Should we hide our router from other routers?"); +======= + ("trust.routerInfo", value()->default_value(""), "Path to routerInfo of floodfill to use with floodfill friend mode") + ("trust.hidden", value()->default_value(true), "should we hide our router from other routers?"); + + options_description websocket("Websocket Options"); + websocket.add_options() + ("websockets.enabled", value()->default_value(false), "enable websocket server") + ("websockets.address", value()->default_value("127.0.0.1"), "address to bind websocket server on") + ("websockets.port", value()->default_value(7666), "port to bind websocket server on"); + +>>>>>>> bda4170... add web socket ui m_OptionsDesc .add(general) .add(limits) @@ -193,7 +205,8 @@ namespace config { .add(precomputation) .add(reseed) .add(addressbook) - .add(trust) + .add(trust) + .add(websocket) ; } diff --git a/Daemon.cpp b/Daemon.cpp index ce2f4173..d8b501a3 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -25,6 +25,9 @@ #include "UPnP.h" #include "util.h" +#include "Event.h" +#include "Websocket.h" + namespace i2p { namespace util @@ -38,6 +41,7 @@ namespace i2p std::unique_ptr httpServer; std::unique_ptr m_I2PControlService; std::unique_ptr UPnP; + std::unique_ptr m_WebsocketServer; }; Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {} @@ -291,11 +295,23 @@ namespace i2p d.m_I2PControlService->Start (); } + bool websocket; i2p::config::GetOption("websockets.enabled", websocket); + if(websocket) { + std::string websocketAddr; i2p::config::GetOption("websockets.address", websocketAddr); + uint16_t websocketPort; i2p::config::GetOption("websockets.port", websocketPort); + LogPrint(eLogInfo, "Daemon: starting Websocket server at ", websocketAddr, ":", websocketPort); + d.m_WebsocketServer = std::unique_ptr(new i2p::event::WebsocketServer (websocketAddr, websocketPort)); + d.m_WebsocketServer->Start(); + i2p::event::core.SetListener(d.m_WebsocketServer->ToListener()); + } + + return true; } bool Daemon_Singleton::stop() { + i2p::event::core.SetListener(nullptr); LogPrint(eLogInfo, "Daemon: shutting down"); LogPrint(eLogInfo, "Daemon: stopping Client"); i2p::client::context.Stop(); @@ -321,7 +337,14 @@ namespace i2p LogPrint(eLogInfo, "Daemon: stopping I2PControl"); d.m_I2PControlService->Stop (); d.m_I2PControlService = nullptr; - } + } + + if (d.m_WebsocketServer) { + LogPrint(eLogInfo, "Daemon: stopping Websocket server"); + d.m_WebsocketServer->Stop(); + d.m_WebsocketServer = nullptr; + } + i2p::crypto::TerminateCrypto (); return true; diff --git a/Event.cpp b/Event.cpp new file mode 100644 index 00000000..45e4e09c --- /dev/null +++ b/Event.cpp @@ -0,0 +1,28 @@ +#include "Event.h" +#include "Log.h" + +namespace i2p +{ + namespace event + { + EventCore core; + + void EventCore::SetListener(EventListener * l) + { + m_listener = l; + LogPrint(eLogInfo, "Event: listener set"); + } + + void EventCore::QueueEvent(const EventType & ev) + { + if(m_listener) + m_listener->HandleEvent(ev); + } + } +} + +void EmitEvent(const EventType & e) +{ + i2p::event::core.QueueEvent(e); +} + diff --git a/Event.h b/Event.h new file mode 100644 index 00000000..e9830289 --- /dev/null +++ b/Event.h @@ -0,0 +1,37 @@ +#ifndef EVENT_H__ +#define EVENT_H__ +#include +#include +#include + +#include + +typedef std::map EventType; + +namespace i2p +{ + namespace event + { + class EventListener { + public: + virtual ~EventListener() {}; + virtual void HandleEvent(const EventType & ev) = 0; + }; + + class EventCore + { + public: + void QueueEvent(const EventType & ev); + void SetListener(EventListener * l); + + private: + EventListener * m_listener = nullptr; + }; + + extern EventCore core; + } +} + +void EmitEvent(const EventType & ev); + +#endif diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index cdc4fb9b..96b30cb6 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -547,7 +547,6 @@ namespace i2p uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET]; uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET); LogPrint (eLogDebug, "I2NP: msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID); - uint8_t * buf = msg + I2NP_HEADER_SIZE; int size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET); switch (typeID) diff --git a/Log.h b/Log.h index 79bbeb3f..b4eb70cd 100644 --- a/Log.h +++ b/Log.h @@ -152,13 +152,13 @@ namespace log { std::string text; /**< message text as single string */ LogLevel level; /**< message level */ std::thread::id tid; /**< id of thread that generated message */ - + LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {}; }; Log & Logger(); } // log -} // i2p +} /** internal usage only -- folding args array to single string */ template diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 20dc9ab0..876b8a4c 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -11,6 +11,7 @@ #include "Transports.h" #include "NetDb.h" #include "NTCPSession.h" +#include "Event.h" using namespace i2p::crypto; @@ -604,7 +605,10 @@ namespace transport if (!memcmp (m_NextMessage->buf + m_NextMessageOffset - 4, checksum, 4)) { if (!m_NextMessage->IsExpired ()) + { + EmitEvent({{"type", "transport.recvmsg"} , {"ident", GetIdentHashBase64()}, {"number", "1"}}); m_Handler.PutNextMessage (m_NextMessage); + } else LogPrint (eLogInfo, "NTCP: message expired"); } diff --git a/SSUData.cpp b/SSUData.cpp index e5abfd54..a1e18c0b 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -5,6 +5,7 @@ #include "NetDb.h" #include "SSU.h" #include "SSUData.h" +#include "Event.h" namespace i2p { @@ -233,9 +234,16 @@ namespace transport if (!m_ReceivedMessages.count (msgID)) { m_ReceivedMessages.insert (msgID); +<<<<<<< HEAD m_LastMessageReceivedTime = i2p::util::GetSecondsSinceEpoch (); if (!msg->IsExpired ()) +======= + m_LastMessageReceivedTime = i2p::util::GetSinceEpoch