From 46f62e1af952a5c0d9e4940c0f59604d40197c7c Mon Sep 17 00:00:00 2001 From: yangfl Date: Sat, 6 Jan 2018 11:48:51 +0800 Subject: [PATCH] remove trailing whitespaces --- ChangeLog | 6 +- Dockerfile | 8 +- Makefile.homebrew | 2 +- Makefile.linux | 2 +- Makefile.osx | 2 +- README.md | 34 +- android/AndroidManifest.xml | 2 +- android/res/menu/options_main.xml | 4 +- .../org/purplei2p/i2pd/DaemonSingleton.java | 28 +- .../org/purplei2p/i2pd/ForegroundService.java | 4 +- android/src/org/purplei2p/i2pd/I2PD.java | 20 +- android/src/org/purplei2p/i2pd/I2PD_JNI.java | 4 +- build/cmake_modules/FindMiniUPnPc.cmake | 2 +- build/docker/old-ubuntu-based/Dockerfile | 2 +- contrib/apparmor/usr.sbin.i2pd | 2 +- contrib/docker/Dockerfile | 8 +- contrib/i2pd.conf | 8 +- contrib/rpm/i2pd.spec | 4 +- daemon/Daemon.cpp | 2 +- daemon/HTTPServer.cpp | 2 +- daemon/HTTPServer.h | 12 +- daemon/I2PControl.cpp | 48 +- daemon/I2PControl.h | 2 +- daemon/UPnP.h | 8 +- daemon/UnixDaemon.cpp | 2 +- debian/changelog | 4 +- debian/i2pd.default | 2 +- debian/patches/01-tune-build-opts.patch | 5 +- libi2pd/Base.cpp | 64 +-- libi2pd/Base.h | 4 +- libi2pd/Config.h | 4 +- libi2pd/Crypto.h | 160 +++--- libi2pd/CryptoKey.cpp | 14 +- libi2pd/CryptoKey.h | 24 +- libi2pd/Datagram.cpp | 38 +- libi2pd/Destination.cpp | 26 +- libi2pd/Destination.h | 4 +- libi2pd/Event.cpp | 2 +- libi2pd/Event.h | 4 +- libi2pd/FS.cpp | 6 +- libi2pd/FS.h | 10 +- libi2pd/Family.cpp | 44 +- libi2pd/Family.h | 4 +- libi2pd/Garlic.cpp | 258 +++++----- libi2pd/Garlic.h | 100 ++-- libi2pd/Gost.cpp | 134 ++--- libi2pd/Gost.h | 18 +- libi2pd/Gzip.cpp | 14 +- libi2pd/HTTP.cpp | 42 +- libi2pd/HTTP.h | 16 +- libi2pd/I2NPProtocol.cpp | 302 +++++------ libi2pd/I2NPProtocol.h | 98 ++-- libi2pd/Identity.cpp | 14 +- libi2pd/Identity.h | 2 +- libi2pd/LeaseSet.cpp | 76 +-- libi2pd/LeaseSet.h | 50 +- libi2pd/Log.h | 6 +- libi2pd/NetDb.cpp | 474 +++++++++--------- libi2pd/NetDb.hpp | 40 +- libi2pd/NetDbRequests.cpp | 46 +- libi2pd/NetDbRequests.h | 10 +- libi2pd/Profiling.cpp | 70 +-- libi2pd/Profiling.h | 28 +- libi2pd/Queue.h | 40 +- libi2pd/Reseed.cpp | 118 ++--- libi2pd/Reseed.h | 20 +- libi2pd/RouterContext.cpp | 4 +- libi2pd/RouterContext.h | 50 +- libi2pd/RouterInfo.cpp | 312 ++++++------ libi2pd/RouterInfo.h | 64 +-- libi2pd/SSU.cpp | 300 +++++------ libi2pd/SSU.h | 30 +- libi2pd/SSUData.cpp | 158 +++--- libi2pd/SSUData.h | 50 +- libi2pd/SSUSession.cpp | 370 +++++++------- libi2pd/SSUSession.h | 48 +- libi2pd/Signature.cpp | 180 +++---- libi2pd/Signature.h | 138 ++--- libi2pd/Streaming.cpp | 32 +- libi2pd/Streaming.h | 120 ++--- libi2pd/Tag.h | 2 +- libi2pd/Timestamp.cpp | 2 +- libi2pd/TransitTunnel.cpp | 74 +-- libi2pd/TransitTunnel.h | 44 +- libi2pd/TransportSession.h | 46 +- libi2pd/Tunnel.cpp | 78 +-- libi2pd/Tunnel.h | 112 ++--- libi2pd/TunnelBase.h | 26 +- libi2pd/TunnelConfig.h | 112 ++--- libi2pd/TunnelEndpoint.cpp | 100 ++-- libi2pd/TunnelEndpoint.h | 18 +- libi2pd/TunnelGateway.cpp | 88 ++-- libi2pd/TunnelGateway.h | 18 +- libi2pd/api.cpp | 18 +- libi2pd/api.h | 8 +- libi2pd/util.cpp | 38 +- libi2pd/util.h | 22 +- libi2pd_client/AddressBook.cpp | 4 +- libi2pd_client/AddressBook.h | 26 +- libi2pd_client/BOB.cpp | 256 +++++----- libi2pd_client/BOB.h | 62 +-- libi2pd_client/ClientContext.cpp | 4 +- libi2pd_client/ClientContext.h | 4 +- libi2pd_client/I2CP.cpp | 174 +++---- libi2pd_client/I2CP.h | 46 +- libi2pd_client/I2PService.h | 6 +- libi2pd_client/SAM.cpp | 28 +- libi2pd_client/SAM.h | 4 +- libi2pd_client/SOCKS.cpp | 134 ++--- libi2pd_client/WebSocks.cpp | 6 +- libi2pd_client/Websocket.h | 4 +- qt/i2pd_qt/DaemonQT.cpp | 14 +- qt/i2pd_qt/DaemonQT.h | 10 +- .../org/purplei2p/i2pd/I2PDMainActivity.java | 8 +- .../src/org/purplei2p/i2pd/LocalService.java | 4 +- qt/i2pd_qt/docs/patch_openssl_so_libs.html | 2 +- qt/i2pd_qt/mainwindow.cpp | 8 +- 117 files changed, 3039 insertions(+), 3040 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2ff1af50..2468f808 100644 --- a/ChangeLog +++ b/ChangeLog @@ -37,7 +37,7 @@ ## [2.15.0] - 2017-08-17 ### Added -- QT GUI +- QT GUI - Ability to add and remove I2P tunnels without restart - Ability to disable SOCKS outproxy option ### Changed @@ -81,7 +81,7 @@ - Some stats in a main window for Windows version ### Changed - Reseed servers list -- MTU of 1488 for ipv6 +- MTU of 1488 for ipv6 - Android and Mac OS X versions use OpenSSL 1.1 - New logo for Android ### Fixed @@ -111,7 +111,7 @@ ## [2.10.2] - 2016-12-04 ### Fixed - Fixes UPnP discovery bug, producing excessive CPU usage -- Fixes sudden SSU thread stop for Windows. +- Fixes sudden SSU thread stop for Windows. ## [2.10.1] - 2016-11-07 ### Fixed diff --git a/Dockerfile b/Dockerfile index 229d0d53..4931a709 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,13 +13,13 @@ RUN mkdir /user && adduser -S -h /user i2pd && chown -R i2pd:nobody /user # -# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the +# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the # image under 20mb we need to remove all the build dependencies in the same "RUN" / layer. # -# 1. install deps, clone and build. -# 2. strip binaries. -# 3. Purge all dependencies and other unrelated packages, including build directory. +# 1. install deps, clone and build. +# 2. strip binaries. +# 3. Purge all dependencies and other unrelated packages, including build directory. RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boost-dev build-base openssl-dev openssl git \ && mkdir -p /tmp/build \ && cd /tmp/build && git clone -b ${GIT_BRANCH} https://github.com/PurpleI2P/i2pd.git \ diff --git a/Makefile.homebrew b/Makefile.homebrew index 287dea05..b3105c56 100644 --- a/Makefile.homebrew +++ b/Makefile.homebrew @@ -4,7 +4,7 @@ BOOSTROOT = ${BREWROOT}/opt/boost SSLROOT = ${BREWROOT}/opt/libressl UPNPROOT = ${BREWROOT}/opt/miniupnpc CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual -INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include +INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include ifndef TRAVIS CXX = clang++ diff --git a/Makefile.linux b/Makefile.linux index e628b63c..22d02af3 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -12,7 +12,7 @@ INCFLAGS ?= # detect proper flag for c++11 support by compilers CXXVER := $(shell $(CXX) -dumpversion) ifeq ($(shell expr match $(CXX) 'clang'),5) - NEEDED_CXXFLAGS += -std=c++11 + NEEDED_CXXFLAGS += -std=c++11 else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10 NEEDED_CXXFLAGS += -std=c++11 else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # >= 4.7 diff --git a/Makefile.osx b/Makefile.osx index f6a0847d..8bbf37f0 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -1,7 +1,7 @@ CXX = clang++ CXXFLAGS = -Os -Wall -std=c++11 -DMAC_OSX #CXXFLAGS = -g -O2 -Wall -std=c++11 -INCFLAGS = -I/usr/local/include +INCFLAGS = -I/usr/local/include LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib ifeq ($(USE_STATIC),yes) diff --git a/README.md b/README.md index d5d7ceb9..546cea64 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,13 @@ i2pd i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client. -I2P (Invisible Internet Protocol) is a universal anonymous network layer. +I2P (Invisible Internet Protocol) is a universal anonymous network layer. All communications over I2P are anonymous and end-to-end encrypted, participants -don't reveal their real IP addresses. +don't reveal their real IP addresses. -I2P client is a software used for building and using anonymous I2P -networks. Such networks are commonly used for anonymous peer-to-peer -applications (filesharing, cryptocurrencies) and anonymous client-server +I2P client is a software used for building and using anonymous I2P +networks. Such networks are commonly used for anonymous peer-to-peer +applications (filesharing, cryptocurrencies) and anonymous client-server applications (websites, instant messengers, chat-servers). I2P allows people from all around the world to communicate and share information @@ -38,9 +38,9 @@ Resources Installing ---------- -The easiest way to install i2pd is by using -[precompiled binaries](https://github.com/PurpleI2P/i2pd/releases/latest). -See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build +The easiest way to install i2pd is by using +[precompiled binaries](https://github.com/PurpleI2P/i2pd/releases/latest). +See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build i2pd from source on your OS. @@ -58,25 +58,25 @@ Build instructions: * Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd) * Mac OS X - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) * FreeBSD -* Android +* Android * iOS Using i2pd ---------- -See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and +See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and [example config file](https://github.com/PurpleI2P/i2pd/blob/openssl/contrib/i2pd.conf). Donations --------- -BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY -ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ -DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF -LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 -DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y -ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z -GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG +BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY +ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ +DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF +LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 +DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y +ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z +GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG License ------- diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index f175c0da..1f9d3b91 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -23,4 +23,4 @@ - + diff --git a/android/res/menu/options_main.xml b/android/res/menu/options_main.xml index 388dfd83..f66caa2a 100644 --- a/android/res/menu/options_main.xml +++ b/android/res/menu/options_main.xml @@ -1,7 +1,7 @@ - # diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 7c3edf24..5ca03f4c 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -17,13 +17,13 @@ RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \ && chown -R i2pd:nobody "$I2PD_HOME" # -# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the +# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the # image under 20mb we need to remove all the build dependencies in the same "RUN" / layer. # -# 1. install deps, clone and build. -# 2. strip binaries. -# 3. Purge all dependencies and other unrelated packages, including build directory. +# 1. install deps, clone and build. +# 2. strip binaries. +# 3. Purge all dependencies and other unrelated packages, including build directory. RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boost-dev build-base openssl-dev openssl git \ && mkdir -p /tmp/build \ && cd /tmp/build && git clone -b ${GIT_BRANCH} ${REPO_URL} \ diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index d9fe951b..c87a2c0b 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -54,7 +54,7 @@ ipv4 = true ipv6 = false ## Network interface to bind to -# ifname = +# ifname = ## Enable NTCP transport (default = true) # ntcp = true @@ -88,18 +88,18 @@ ipv6 = false [upnp] ## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID) -# enabled = false +# enabled = false ## Name i2pd appears in UPnP forwardings list (default = I2Pd) # name = I2Pd [reseed] -## Enable or disable reseed data verification. +## Enable or disable reseed data verification. verify = true ## URLs to request reseed data from, separated by comma ## Default: "mainline" I2P Network reseeds # urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/ -## Path to local reseed data file (.su3) for manual reseeding +## Path to local reseed data file (.su3) for manual reseeding # file = /path/to/i2pseeds.su3 ## or HTTPS URL to reseed from # file = https://legit-website.com/i2pseeds.su3 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 5eb78e34..0b6fa463 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -48,7 +48,7 @@ using dedicated user's permissions. %build cd build -%if 0%{?rhel} == 7 +%if 0%{?rhel} == 7 %cmake3 \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ @@ -133,7 +133,7 @@ getent passwd i2pd >/dev/null || \ - Fixed QT GUI issues * Thu Aug 17 2017 orignal - 2.15.0 -- Added QT GUI +- Added QT GUI - Added ability add and remove I2P tunnels without restart - Added ability to disable SOCKS outproxy option - Changed strip-out Accept-* hedaers in HTTP proxy diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 658bf011..54146d5d 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -123,7 +123,7 @@ namespace i2p LogPrint(eLogInfo, "AESNI enabled"); #endif #if defined(__AVX__) - LogPrint(eLogInfo, "AVX enabled"); + LogPrint(eLogInfo, "AVX enabled"); #endif LogPrint(eLogDebug, "FS: main config file: ", config); LogPrint(eLogDebug, "FS: data directory: ", datadir); diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 5faa8b7f..017bc8a4 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -505,7 +505,7 @@ namespace http { s << " Graceful shutdown
\r\n"; #endif s << " Force shutdown
\r\n"; - + s << "
\r\nLogging level
\r\n"; s << " [none] "; s << " [error] "; diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index ec718532..467522cf 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -10,12 +10,12 @@ #include #include "HTTP.h" -namespace i2p +namespace i2p { -namespace http +namespace http { - const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; - const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds + const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; + const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds class HTTPConnection: public std::enable_shared_from_this { @@ -23,7 +23,7 @@ namespace http HTTPConnection (std::shared_ptr socket); void Receive (); - + private: void HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); @@ -67,7 +67,7 @@ namespace http void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr newSocket); void CreateConnection(std::shared_ptr newSocket); - + private: bool m_IsRunning; diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index 7ba6ebea..be668183 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -67,7 +67,7 @@ namespace client m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler; // I2PControl - m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler; + m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler; // RouterInfo m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler; @@ -80,13 +80,13 @@ namespace client m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler; m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler; m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = -&I2PControlService::TunnelsSuccessRateHandler; +&I2PControlService::TunnelsSuccessRateHandler; m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes; m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes; - // RouterManager + // RouterManager m_RouterManagerHandlers["Reseed"] = &I2PControlService::ReseedHandler; - m_RouterManagerHandlers["Shutdown"] = &I2PControlService::ShutdownHandler; + m_RouterManagerHandlers["Shutdown"] = &I2PControlService::ShutdownHandler; m_RouterManagerHandlers["ShutdownGraceful"] = &I2PControlService::ShutdownGracefulHandler; // NetworkSetting @@ -133,8 +133,8 @@ namespace client m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "I2PControl: runtime exception: ", ex.what ()); - } - } + } + } } void I2PControlService::Accept () @@ -168,7 +168,7 @@ namespace client if (ecode) { LogPrint (eLogError, "I2PControl: handshake error: ", ecode.message ()); return; - } + } //std::this_thread::sleep_for (std::chrono::milliseconds(5)); ReadRequest (socket); } @@ -190,12 +190,12 @@ namespace client size_t bytes_transferred, std::shared_ptr socket, std::shared_ptr buf) { - if (ecode) + if (ecode) { LogPrint (eLogError, "I2PControl: read error: ", ecode.message ()); return; - } - else + } + else { bool isHtml = !memcmp (buf->data (), "POST", 4); try @@ -243,8 +243,8 @@ namespace client response << "{\"id\":" << id << ",\"result\":{"; (this->*(it->second))(pt.get_child ("params"), response); response << "},\"jsonrpc\":\"2.0\"}"; - } - else + } + else { LogPrint (eLogWarning, "I2PControl: unknown method ", method); response << "{\"id\":null,\"error\":"; @@ -337,9 +337,9 @@ namespace client InsertParam (results, "API", api); results << ","; std::string token = boost::lexical_cast(i2p::util::GetSecondsSinceEpoch ()); - m_Tokens.insert (token); + m_Tokens.insert (token); InsertParam (results, "Token", token); - } + } void I2PControlService::EchoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { @@ -364,7 +364,7 @@ namespace client } else LogPrint (eLogError, "I2PControl: I2PControl unknown request: ", it.first); - } + } } void I2PControlService::PasswordHandler (const std::string& value) @@ -394,28 +394,28 @@ namespace client void I2PControlService::UptimeHandler (std::ostringstream& results) { - InsertParam (results, "i2p.router.uptime", (int)i2p::context.GetUptime ()*1000); + InsertParam (results, "i2p.router.uptime", (int)i2p::context.GetUptime ()*1000); } void I2PControlService::VersionHandler (std::ostringstream& results) { InsertParam (results, "i2p.router.version", VERSION); - } + } void I2PControlService::StatusHandler (std::ostringstream& results) { auto dest = i2p::client::context.GetSharedLocalDestination (); - InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0"); + InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0"); } void I2PControlService::NetDbKnownPeersHandler (std::ostringstream& results) { - InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ()); + InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ()); } void I2PControlService::NetDbActivePeersHandler (std::ostringstream& results) { - InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ()); + InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ()); } void I2PControlService::NetStatusHandler (std::ostringstream& results) @@ -463,11 +463,11 @@ namespace client { for (auto it = params.begin (); it != params.end (); it++) { - if (it != params.begin ()) results << ","; + if (it != params.begin ()) results << ","; LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first); auto it1 = m_RouterManagerHandlers.find (it->first); if (it1 != m_RouterManagerHandlers.end ()) { - (this->*(it1->second))(results); + (this->*(it1->second))(results); } else LogPrint (eLogError, "I2PControl: RouterManager unknown request: ", it->first); } @@ -516,7 +516,7 @@ namespace client auto it1 = m_NetworkSettingHandlers.find (it->first); if (it1 != m_NetworkSettingHandlers.end ()) { if (it != params.begin ()) results << ","; - (this->*(it1->second))(it->second.data (), results); + (this->*(it1->second))(it->second.data (), results); } else LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first); } @@ -538,7 +538,7 @@ namespace client InsertParam (results, "i2p.router.net.bw.out", bw); } - // certificate + // certificate void I2PControlService::CreateCertificate (const char *crt_path, const char *key_path) { FILE *f = NULL; diff --git a/daemon/I2PControl.h b/daemon/I2PControl.h index 5d81c8f6..a7ed1eab 100644 --- a/daemon/I2PControl.h +++ b/daemon/I2PControl.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include namespace i2p diff --git a/daemon/UPnP.h b/daemon/UPnP.h index 7d67fdbf..5313a1c4 100644 --- a/daemon/UPnP.h +++ b/daemon/UPnP.h @@ -42,13 +42,13 @@ namespace transport std::string GetProto (std::shared_ptr address); private: - + bool m_IsRunning; std::unique_ptr m_Thread; - std::condition_variable m_Started; - std::mutex m_StartedMutex; + std::condition_variable m_Started; + std::mutex m_StartedMutex; boost::asio::io_service m_Service; - boost::asio::deadline_timer m_Timer; + boost::asio::deadline_timer m_Timer; struct UPNPUrls m_upnpUrls; struct IGDdatas m_upnpData; diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index f282f2d4..075aa7d8 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -163,7 +163,7 @@ namespace i2p sigaction(SIGABRT, &sa, 0); sigaction(SIGTERM, &sa, 0); sigaction(SIGINT, &sa, 0); - sigaction(SIGPIPE, &sa, 0); + sigaction(SIGPIPE, &sa, 0); return Daemon_Singleton::start(); } diff --git a/debian/changelog b/debian/changelog index c07926f3..94105535 100644 --- a/debian/changelog +++ b/debian/changelog @@ -62,7 +62,7 @@ i2pd (2.10.0-1) unstable; urgency=low * updated to version 2.10.0/0.9.27 * reseed.verify set to true by default - + -- orignal Sun, 16 Oct 2016 13:55:40 +0000 i2pd (2.9.0-1) unstable; urgency=low @@ -73,7 +73,7 @@ i2pd (2.9.0-1) unstable; urgency=low * removed all port assigments in services files * fixed logrotate * subscriptions.txt and tunnels.conf taken from docs folder - + -- orignal Fri, 12 Aug 2016 14:25:40 +0000 i2pd (2.7.0-1) unstable; urgency=low diff --git a/debian/i2pd.default b/debian/i2pd.default index 5ac311c3..bd1d073f 100644 --- a/debian/i2pd.default +++ b/debian/i2pd.default @@ -7,5 +7,5 @@ I2PD_ENABLED="yes" # see possible switches in /usr/share/doc/i2pd/configuration.md.gz DAEMON_OPTS="" -# If you have problems with hunging i2pd, you can try enable this +# If you have problems with hunging i2pd, you can try enable this ulimit -n 4096 diff --git a/debian/patches/01-tune-build-opts.patch b/debian/patches/01-tune-build-opts.patch index 4420d387..2dff9e09 100644 --- a/debian/patches/01-tune-build-opts.patch +++ b/debian/patches/01-tune-build-opts.patch @@ -1,12 +1,11 @@ diff --git a/Makefile b/Makefile index bdadfe0..2f71eec 100644 - --- a/Makefile +++ b/Makefile @@ -9,10 +9,10 @@ DEPS := obj/make.dep - + include filelist.mk - + -USE_AESNI := yes +USE_AESNI := no -USE_AVX := yes diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 35aae437..bb7cda90 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -43,8 +43,8 @@ namespace data const char * GetBase64SubstitutionTable () { return T64; - } - + } + /* * Reverse Substitution Table (built in run time) */ @@ -53,10 +53,10 @@ namespace data static int isFirstTime = 1; /* - * Padding + * Padding */ - static char P64 = '='; + static char P64 = '='; /* * @@ -68,11 +68,11 @@ namespace data */ size_t /* Number of bytes in the encoded buffer */ - ByteStreamToBase64 ( + ByteStreamToBase64 ( const uint8_t * InBuffer, /* Input buffer, binary data */ - size_t InCount, /* Number of bytes in the input buffer */ + size_t InCount, /* Number of bytes in the input buffer */ char * OutBuffer, /* output buffer */ - size_t len /* length of output buffer */ + size_t len /* length of output buffer */ ) { @@ -80,9 +80,9 @@ namespace data unsigned char * pd; unsigned char acc_1; unsigned char acc_2; - int i; - int n; - int m; + int i; + int n; + int m; size_t outCount; ps = (unsigned char *)InBuffer; @@ -96,7 +96,7 @@ namespace data pd = (unsigned char *)OutBuffer; for ( i = 0; i>= 2; /* base64 digit #1 */ *pd++ = T64[acc_1]; acc_1 = *ps++; @@ -109,7 +109,7 @@ namespace data *pd++ = T64[acc_1]; acc_2 &= 0x3f; /* base64 digit #4 */ *pd++ = T64[acc_2]; - } + } if ( m == 1 ){ acc_1 = *ps++; acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */ @@ -122,7 +122,7 @@ namespace data } else if ( m == 2 ){ acc_1 = *ps++; - acc_2 = (acc_1<<4)&0x3f; + acc_2 = (acc_1<<4)&0x3f; acc_1 >>= 2; /* base64 digit #1 */ *pd++ = T64[acc_1]; acc_1 = *ps++; @@ -133,7 +133,7 @@ namespace data *pd++ = T64[acc_1]; *pd++ = P64; } - + return outCount; } @@ -148,10 +148,10 @@ namespace data */ size_t /* Number of output bytes */ - Base64ToByteStream ( + Base64ToByteStream ( const char * InBuffer, /* BASE64 encoded buffer */ size_t InCount, /* Number of input bytes */ - uint8_t * OutBuffer, /* output buffer length */ + uint8_t * OutBuffer, /* output buffer length */ size_t len /* length of output buffer */ ) { @@ -159,28 +159,28 @@ namespace data unsigned char * pd; unsigned char acc_1; unsigned char acc_2; - int i; - int n; - int m; + int i; + int n; + int m; size_t outCount; if (isFirstTime) iT64Build(); n = InCount/4; m = InCount%4; - if (InCount && !m) + if (InCount && !m) outCount = 3*n; else { outCount = 0; return 0; } - + ps = (unsigned char *)(InBuffer + InCount - 1); while ( *ps-- == P64 ) outCount--; ps = (unsigned char *)InBuffer; - + if (outCount > len) return -1; pd = OutBuffer; - auto endOfOutBuffer = OutBuffer + outCount; + auto endOfOutBuffer = OutBuffer + outCount; for ( i = 0; i < n; i++ ){ acc_1 = iT64[*ps++]; acc_2 = iT64[*ps++]; @@ -193,7 +193,7 @@ namespace data acc_1 = iT64[*ps++]; acc_2 |= acc_1 >> 2; *pd++ = acc_2; - if (pd >= endOfOutBuffer) break; + if (pd >= endOfOutBuffer) break; acc_2 = iT64[*ps++]; acc_2 |= acc_1 << 6; @@ -203,13 +203,13 @@ namespace data return outCount; } - size_t Base64EncodingBufferSize (const size_t input_size) + size_t Base64EncodingBufferSize (const size_t input_size) { auto d = div (input_size, 3); if (d.rem) d.quot++; return 4*d.quot; } - + /* * * iT64 @@ -228,20 +228,20 @@ namespace data iT64[(int)P64] = 0; } - size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen) + size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen) { int tmp = 0, bits = 0; size_t ret = 0; for (size_t i = 0; i < len; i++) { - char ch = inBuf[i]; + char ch = inBuf[i]; if (ch >= '2' && ch <= '7') // digit ch = (ch - '2') + 26; // 26 means a-z else if (ch >= 'a' && ch <= 'z') ch = ch - 'a'; // a = 0 else return 0; // unexpected character - + tmp |= ch; bits += 5; if (bits >= 8) @@ -261,7 +261,7 @@ namespace data size_t ret = 0, pos = 1; int bits = 8, tmp = inBuf[0]; while (ret < outLen && (bits > 0 || pos < len)) - { + { if (bits < 5) { if (pos < len) @@ -276,8 +276,8 @@ namespace data tmp <<= (5 - bits); bits = 5; } - } - + } + bits -= 5; int ind = (tmp >> bits) & 0x1F; outBuf[ret] = (ind < 26) ? (ind + 'a') : ((ind - 26) + '2'); diff --git a/libi2pd/Base.h b/libi2pd/Base.h index 66192d1b..bc92376f 100644 --- a/libi2pd/Base.h +++ b/libi2pd/Base.h @@ -10,8 +10,8 @@ namespace data { size_t ByteStreamToBase64 (const uint8_t * InBuffer, size_t InCount, char * OutBuffer, size_t len); size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len ); const char * GetBase32SubstitutionTable (); - const char * GetBase64SubstitutionTable (); - + const char * GetBase64SubstitutionTable (); + size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); diff --git a/libi2pd/Config.h b/libi2pd/Config.h index c920c6fe..0bbcd5b1 100644 --- a/libi2pd/Config.h +++ b/libi2pd/Config.h @@ -79,10 +79,10 @@ namespace config { } template - bool GetOption(const std::string& name, T& value) + bool GetOption(const std::string& name, T& value) { return GetOption (name.c_str (), value); - } + } bool GetOptionAsAny(const char *name, boost::any& value); bool GetOptionAsAny(const std::string& name, boost::any& value); diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 2b1bf6a0..e495d2e6 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -24,7 +24,7 @@ namespace crypto bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len); // DSA - DSA * CreateDSA (); + DSA * CreateDSA (); // RSA const BIGNUM * GetRSAE (); @@ -33,20 +33,20 @@ namespace crypto class DHKeys { public: - + DHKeys (); ~DHKeys (); void GenerateKeys (); const uint8_t * GetPublicKey () const { return m_PublicKey; }; void Agree (const uint8_t * pub, uint8_t * shared); - + private: DH * m_DH; uint8_t m_PublicKey[256]; - }; - + }; + // ElGamal void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false); bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false); @@ -54,15 +54,15 @@ namespace crypto // ECIES void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); // 222 bytes data, 514 bytes encrypted - bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); + bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub); - + // HMAC - typedef i2p::data::Tag<32> MACKey; + typedef i2p::data::Tag<32> MACKey; void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest); // AES - struct ChipherBlock + struct ChipherBlock { uint8_t buf[16]; @@ -71,40 +71,40 @@ namespace crypto #if defined(__AVX__) // AVX __asm__ ( - "vmovups (%[buf]), %%xmm0 \n" - "vmovups (%[other]), %%xmm1 \n" + "vmovups (%[buf]), %%xmm0 \n" + "vmovups (%[other]), %%xmm1 \n" "vxorps %%xmm0, %%xmm1, %%xmm0 \n" - "vmovups %%xmm0, (%[buf]) \n" - : - : [buf]"r"(buf), [other]"r"(other.buf) + "vmovups %%xmm0, (%[buf]) \n" + : + : [buf]"r"(buf), [other]"r"(other.buf) : "%xmm0", "%xmm1", "memory" - ); + ); #elif defined(__SSE__) // SSE __asm__ ( - "movups (%[buf]), %%xmm0 \n" - "movups (%[other]), %%xmm1 \n" + "movups (%[buf]), %%xmm0 \n" + "movups (%[other]), %%xmm1 \n" "pxor %%xmm1, %%xmm0 \n" "movups %%xmm0, (%[buf]) \n" - : - : [buf]"r"(buf), [other]"r"(other.buf) + : + : [buf]"r"(buf), [other]"r"(other.buf) : "%xmm0", "%xmm1", "memory" - ); + ); #else // TODO: implement it better for (int i = 0; i < 16; i++) buf[i] ^= other.buf[i]; #endif - } + } }; typedef i2p::data::Tag<32> AESKey; - + template class AESAlignedBuffer // 16 bytes alignment { public: - + AESAlignedBuffer () { m_Buf = m_UnalignedBuffer; @@ -112,22 +112,22 @@ namespace crypto if (rem) m_Buf += (16 - rem); } - + operator uint8_t * () { return m_Buf; }; operator const uint8_t * () const { return m_Buf; }; ChipherBlock * GetChipherBlock () { return (ChipherBlock *)m_Buf; }; const ChipherBlock * GetChipherBlock () const { return (const ChipherBlock *)m_Buf; }; - + private: uint8_t m_UnalignedBuffer[sz + 15]; // up to 15 bytes alignment uint8_t * m_Buf; - }; + }; #ifdef AESNI class ECBCryptoAESNI - { + { public: uint8_t * GetKeySchedule () { return m_KeySchedule; }; @@ -135,27 +135,27 @@ namespace crypto protected: void ExpandKey (const AESKey& key); - + private: AESAlignedBuffer<240> m_KeySchedule; // 14 rounds for AES-256, 240 bytes - }; + }; class ECBEncryptionAESNI: public ECBCryptoAESNI { public: - + void SetKey (const AESKey& key) { ExpandKey (key); }; - void Encrypt (const ChipherBlock * in, ChipherBlock * out); - }; + void Encrypt (const ChipherBlock * in, ChipherBlock * out); + }; class ECBDecryptionAESNI: public ECBCryptoAESNI { public: - + void SetKey (const AESKey& key); - void Decrypt (const ChipherBlock * in, ChipherBlock * out); - }; + void Decrypt (const ChipherBlock * in, ChipherBlock * out); + }; typedef ECBEncryptionAESNI ECBEncryption; typedef ECBDecryptionAESNI ECBDecryption; @@ -165,46 +165,46 @@ namespace crypto class ECBEncryption { public: - - void SetKey (const AESKey& key) - { + + void SetKey (const AESKey& key) + { AES_set_encrypt_key (key, 256, &m_Key); } void Encrypt (const ChipherBlock * in, ChipherBlock * out) { AES_encrypt (in->buf, out->buf, &m_Key); - } + } private: AES_KEY m_Key; - }; + }; class ECBDecryption { public: - - void SetKey (const AESKey& key) - { - AES_set_decrypt_key (key, 256, &m_Key); + + void SetKey (const AESKey& key) + { + AES_set_decrypt_key (key, 256, &m_Key); } void Decrypt (const ChipherBlock * in, ChipherBlock * out) { AES_decrypt (in->buf, out->buf, &m_Key); - } + } private: AES_KEY m_Key; - }; + }; -#endif +#endif class CBCEncryption { public: - + CBCEncryption () { memset ((uint8_t *)m_LastBlock, 0, 16); }; void SetKey (const AESKey& key) { m_ECBEncryption.SetKey (key); }; // 32 bytes @@ -217,14 +217,14 @@ namespace crypto private: AESAlignedBuffer<16> m_LastBlock; - + ECBEncryption m_ECBEncryption; }; class CBCDecryption { public: - + CBCDecryption () { memset ((uint8_t *)m_IV, 0, 16); }; void SetKey (const AESKey& key) { m_ECBDecryption.SetKey (key); }; // 32 bytes @@ -238,7 +238,7 @@ namespace crypto AESAlignedBuffer<16> m_IV; ECBDecryption m_ECBDecryption; - }; + }; class TunnelEncryption // with double IV encryption { @@ -248,9 +248,9 @@ namespace crypto { m_LayerEncryption.SetKey (layerKey); m_IVEncryption.SetKey (ivKey); - } + } - void Encrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data) + void Encrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data) private: @@ -270,9 +270,9 @@ namespace crypto { m_LayerDecryption.SetKey (layerKey); m_IVDecryption.SetKey (ivKey); - } + } - void Decrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data) + void Decrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data) private: @@ -282,72 +282,72 @@ namespace crypto #else CBCDecryption m_LayerDecryption; #endif - }; - + }; + void InitCrypto (bool precomputation); void TerminateCrypto (); -} -} +} +} // take care about openssl version #include #if (OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER) // 1.1.0 or LibreSSL // define getters and setters introduced in 1.1.0 -inline int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) - { +inline int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) + { if (d->p) BN_free (d->p); if (d->q) BN_free (d->q); if (d->g) BN_free (d->g); - d->p = p; d->q = q; d->g = g; return 1; + d->p = p; d->q = q; d->g = g; return 1; } -inline int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) - { +inline int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) + { if (d->pub_key) BN_free (d->pub_key); if (d->priv_key) BN_free (d->priv_key); - d->pub_key = pub_key; d->priv_key = priv_key; return 1; - } -inline void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) + d->pub_key = pub_key; d->priv_key = priv_key; return 1; + } +inline void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) { *pub_key = d->pub_key; *priv_key = d->priv_key; } -inline int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) - { +inline int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) + { if (sig->r) BN_free (sig->r); if (sig->s) BN_free (sig->s); - sig->r = r; sig->s = s; return 1; + sig->r = r; sig->s = s; return 1; } -inline void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +inline void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { *pr = sig->r; *ps = sig->s; } inline int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) - { + { if (sig->r) BN_free (sig->r); if (sig->s) BN_free (sig->s); - sig->r = r; sig->s = s; return 1; + sig->r = r; sig->s = s; return 1; } inline void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { *pr = sig->r; *ps = sig->s; } -inline int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +inline int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { if (r->n) BN_free (r->n); if (r->e) BN_free (r->e); if (r->d) BN_free (r->d); - r->n = n; r->e = e; r->d = d; return 1; + r->n = n; r->e = e; r->d = d; return 1; } inline void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { *n = r->n; *e = r->e; *d = r->d; } inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) - { + { if (dh->p) BN_free (dh->p); if (dh->q) BN_free (dh->q); if (dh->g) BN_free (dh->g); - dh->p = p; dh->q = q; dh->g = g; return 1; + dh->p = p; dh->q = q; dh->g = g; return 1; } inline int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) - { - if (dh->pub_key) BN_free (dh->pub_key); + { + if (dh->pub_key) BN_free (dh->pub_key); if (dh->priv_key) BN_free (dh->priv_key); - dh->pub_key = pub_key; dh->priv_key = priv_key; return 1; + dh->pub_key = pub_key; dh->priv_key = priv_key; return 1; } inline void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) { *pub_key = dh->pub_key; *priv_key = dh->priv_key; } diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index b1adf2f0..4be230f7 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -72,7 +72,7 @@ namespace crypto void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub) { EC_GROUP * curve = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1); - EC_POINT * p = nullptr; + EC_POINT * p = nullptr; BIGNUM * key = nullptr; GenerateECIESKeyPair (curve, key, p); bn2buf (key, priv, 32); @@ -81,11 +81,11 @@ namespace crypto BIGNUM * x = BN_new (), * y = BN_new (); EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, NULL); bn2buf (x, pub, 32); - bn2buf (y, pub + 32, 32); + bn2buf (y, pub + 32, 32); RAND_bytes (pub + 64, 192); - EC_POINT_free (p); + EC_POINT_free (p); BN_free (x); BN_free (y); - EC_GROUP_free (curve); + EC_GROUP_free (curve); } ECIESGOSTR3410Encryptor::ECIESGOSTR3410Encryptor (const uint8_t * pub) @@ -131,7 +131,7 @@ namespace crypto void CreateECIESGOSTR3410RandomKeys (uint8_t * priv, uint8_t * pub) { auto& curve = GetGOSTR3410Curve (eGOSTR3410CryptoProA); - EC_POINT * p = nullptr; + EC_POINT * p = nullptr; BIGNUM * key = nullptr; GenerateECIESKeyPair (curve->GetGroup (), key, p); bn2buf (key, priv, 32); @@ -140,9 +140,9 @@ namespace crypto BIGNUM * x = BN_new (), * y = BN_new (); EC_POINT_get_affine_coordinates_GFp (curve->GetGroup (), p, x, y, NULL); bn2buf (x, pub, 32); - bn2buf (y, pub + 32, 32); + bn2buf (y, pub + 32, 32); RAND_bytes (pub + 64, 192); - EC_POINT_free (p); + EC_POINT_free (p); BN_free (x); BN_free (y); } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index a2cfdd87..ece86eb0 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -8,15 +8,15 @@ namespace i2p { namespace crypto { - class CryptoKeyEncryptor + class CryptoKeyEncryptor { public: virtual ~CryptoKeyEncryptor () {}; virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) = 0; // 222 bytes data, 512 bytes encrypted - }; + }; - class CryptoKeyDecryptor + class CryptoKeyDecryptor { public: @@ -30,7 +30,7 @@ namespace crypto public: ElGamalEncryptor (const uint8_t * pub); - void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); private: @@ -42,7 +42,7 @@ namespace crypto public: ElGamalDecryptor (const uint8_t * priv); - bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); + bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); private: @@ -51,13 +51,13 @@ namespace crypto // ECIES P256 - class ECIESP256Encryptor: public CryptoKeyEncryptor + class ECIESP256Encryptor: public CryptoKeyEncryptor { public: ECIESP256Encryptor (const uint8_t * pub); ~ECIESP256Encryptor (); - void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); private: @@ -72,7 +72,7 @@ namespace crypto ECIESP256Decryptor (const uint8_t * priv); ~ECIESP256Decryptor (); - bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); + bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); private: @@ -80,17 +80,17 @@ namespace crypto BIGNUM * m_PrivateKey; }; - void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub); + void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub); // ECIES GOST R 34.10 - class ECIESGOSTR3410Encryptor: public CryptoKeyEncryptor + class ECIESGOSTR3410Encryptor: public CryptoKeyEncryptor { public: ECIESGOSTR3410Encryptor (const uint8_t * pub); ~ECIESGOSTR3410Encryptor (); - void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); private: @@ -104,7 +104,7 @@ namespace crypto ECIESGOSTR3410Decryptor (const uint8_t * priv); ~ECIESGOSTR3410Decryptor (); - bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); + bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); private: diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 2af26771..ed87a054 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -11,20 +11,20 @@ namespace i2p { namespace datagram { - DatagramDestination::DatagramDestination (std::shared_ptr owner): + DatagramDestination::DatagramDestination (std::shared_ptr owner): m_Owner (owner.get()), m_Receiver (nullptr) { m_Identity.FromBase64 (owner->GetIdentity()->ToBase64()); } - + DatagramDestination::~DatagramDestination () { m_Sessions.clear(); } void DatagramDestination::SendDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort) - { + { auto owner = m_Owner; std::vector v(MAX_DATAGRAM_SIZE); uint8_t * buf = v.data(); @@ -33,11 +33,11 @@ namespace datagram auto signatureLen = m_Identity.GetSignatureLen (); uint8_t * buf1 = signature + signatureLen; size_t headerLen = identityLen + signatureLen; - - memcpy (buf1, payload, len); + + memcpy (buf1, payload, len); if (m_Identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) { - uint8_t hash[32]; + uint8_t hash[32]; SHA256(buf1, len, hash); owner->Sign (hash, 32, signature); } @@ -63,10 +63,10 @@ namespace datagram uint8_t hash[32]; SHA256(buf + headerLen, len - headerLen, hash); verified = identity.Verify (hash, 32, signature); - } - else + } + else verified = identity.Verify (buf + headerLen, len - headerLen, signature); - + if (verified) { auto h = identity.GetIdentHash(); @@ -79,7 +79,7 @@ namespace datagram LogPrint (eLogWarning, "DatagramDestination: no receiver for port ", toPort); } else - LogPrint (eLogWarning, "Datagram signature verification failed"); + LogPrint (eLogWarning, "Datagram signature verification failed"); } DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port) @@ -113,24 +113,24 @@ namespace datagram { htobe32buf (msg->GetPayload (), size); // length htobe16buf (buf + 4, fromPort); // source port - htobe16buf (buf + 6, toPort); // destination port + htobe16buf (buf + 6, toPort); // destination port buf[9] = i2p::client::PROTOCOL_TYPE_DATAGRAM; // datagram protocol - msg->len += size + 4; + msg->len += size + 4; msg->FillI2NPMessageHeader (eI2NPData); - } + } else msg = nullptr; return msg; } void DatagramDestination::CleanUp () - { + { if (m_Sessions.empty ()) return; auto now = i2p::util::GetMillisecondsSinceEpoch(); LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); std::unique_lock lock(m_SessionsMutex); // for each session ... - for (auto it = m_Sessions.begin (); it != m_Sessions.end (); ) + for (auto it = m_Sessions.begin (); it != m_Sessions.end (); ) { // check if expired if (now - it->second->LastActivity() >= DATAGRAM_SESSION_MAX_IDLE) @@ -143,7 +143,7 @@ namespace datagram it++; } } - + std::shared_ptr DatagramDestination::ObtainSession(const i2p::data::IdentHash & identity) { std::shared_ptr session = nullptr; @@ -169,7 +169,7 @@ namespace datagram } return nullptr; } - + DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination, const i2p::data::IdentHash & remoteIdent) : m_LocalDestination(localDestination), @@ -203,7 +203,7 @@ namespace datagram { if(!m_RoutingSession) return DatagramSession::Info(nullptr, nullptr, m_LastUse); - + auto routingPath = m_RoutingSession->GetSharedRoutingPath(); if (!routingPath) return DatagramSession::Info(nullptr, nullptr, m_LastUse); @@ -318,7 +318,7 @@ namespace datagram m_RoutingSession->SetSharedRoutingPath(path); } return path; - + } void DatagramSession::HandleLeaseSetUpdated(std::shared_ptr ls) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index cb42e480..5742cbd4 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -24,9 +24,9 @@ namespace client int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY; int numTags = DEFAULT_TAGS_TO_SEND; std::shared_ptr > explicitPeers; - try + try { - if (params) + if (params) { auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH); if (it != params->end ()) @@ -59,16 +59,16 @@ namespace client } } it = params->find (I2CP_PARAM_INBOUND_NICKNAME); - if (it != params->end ()) m_Nickname = it->second; + if (it != params->end ()) m_Nickname = it->second; else // try outbound - { + { it = params->find (I2CP_PARAM_OUTBOUND_NICKNAME); - if (it != params->end ()) m_Nickname = it->second; + if (it != params->end ()) m_Nickname = it->second; // otherwise we set deafult nickname in Start when we know local address } } - } - catch (std::exception & ex) + } + catch (std::exception & ex) { LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what()); } @@ -492,7 +492,7 @@ namespace client m_PublishReplyToken = 0; if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) { - LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); + LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); Publish (); } else @@ -503,7 +503,7 @@ namespace client m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, shared_from_this (), std::placeholders::_1)); - + } } } @@ -728,14 +728,14 @@ namespace client if (isPublic) PersistTemporaryKeys (); else - i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), + i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), m_EncryptionPrivateKey, m_EncryptionPublicKey); - m_Decryptor = m_Keys.CreateDecryptor (m_EncryptionPrivateKey); + m_Decryptor = m_Keys.CreateDecryptor (m_EncryptionPrivateKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); // extract streaming params - if (params) + if (params) { auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY); if (it != params->end ()) @@ -956,7 +956,7 @@ namespace client } LogPrint (eLogInfo, "Destination: Creating new temporary keys for address ", ident, ".b32.i2p"); - i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), + i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), m_EncryptionPrivateKey, m_EncryptionPublicKey); std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 17daecb5..2ca0b7a6 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -190,9 +190,9 @@ namespace client void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; // ref counter - int Acquire () { return ++m_RefCounter; }; + int Acquire () { return ++m_RefCounter; }; int Release () { return --m_RefCounter; }; - int GetRefCounter () const { return m_RefCounter; }; + int GetRefCounter () const { return m_RefCounter; }; // streaming std::shared_ptr CreateStreamingDestination (int port, bool gzip = true); // additional diff --git a/libi2pd/Event.cpp b/libi2pd/Event.cpp index 4bc6d594..9c75f95b 100644 --- a/libi2pd/Event.cpp +++ b/libi2pd/Event.cpp @@ -30,7 +30,7 @@ namespace i2p } m_collected[key].Val += val; } - + void EventCore::PumpCollected(EventListener * listener) { std::unique_lock lock(m_collect_mutex); diff --git a/libi2pd/Event.h b/libi2pd/Event.h index a9f97df2..a8b46a4b 100644 --- a/libi2pd/Event.h +++ b/libi2pd/Event.h @@ -29,7 +29,7 @@ namespace i2p void CollectEvent(const std::string & type, const std::string & ident, uint64_t val); void SetListener(EventListener * l); void PumpCollected(EventListener * l); - + private: std::mutex m_collect_mutex; struct CollectedEvent @@ -41,7 +41,7 @@ namespace i2p std::map m_collected; EventListener * m_listener = nullptr; }; -#ifdef WITH_EVENTS +#ifdef WITH_EVENTS extern EventCore core; #endif } diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index bceda568..117f86d0 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -68,7 +68,7 @@ namespace fs { #else /* other unix */ #if defined(ANDROID) const char * ext = getenv("EXTERNAL_STORAGE"); - if (!ext) ext = "/sdcard"; + if (!ext) ext = "/sdcard"; if (boost::filesystem::exists(ext)) { dataDir = std::string (ext) + "/" + appName; @@ -123,12 +123,12 @@ namespace fs { } uint32_t GetLastUpdateTime (const std::string & path) - { + { if (!boost::filesystem::exists(path)) return 0; boost::system::error_code ec; auto t = boost::filesystem::last_write_time (path, ec); return ec ? 0 : t; - } + } bool Remove(const std::string & path) { if (!boost::filesystem::exists(path)) diff --git a/libi2pd/FS.h b/libi2pd/FS.h index cb9b632d..87364fea 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -97,7 +97,7 @@ namespace fs { * @param files Vector to store found files * @return true on success and false if directory not exists */ - bool ReadDir(const std::string & path, std::vector & files); + bool ReadDir(const std::string & path, std::vector & files); /** * @brief Remove file with given path @@ -113,9 +113,9 @@ namespace fs { */ bool Exists(const std::string & path); - uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch - - bool CreateDirectory (const std::string& path); + uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch + + bool CreateDirectory (const std::string& path); template void _ExpandPath(std::stringstream & path, T c) { @@ -153,7 +153,7 @@ namespace fs { _ExpandPath(s, filenames...); return s.str(); - } + } } // fs } // i2p diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index fb3b19a6..3fb5d862 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -21,24 +21,24 @@ namespace data void Families::LoadCertificate (const std::string& filename) { SSL_CTX * ctx = SSL_CTX_new (TLS_method ()); - int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); + int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); if (ret) - { + { SSL * ssl = SSL_new (ctx); X509 * cert = SSL_get_certificate (ssl); if (cert) - { + { std::shared_ptr verifier; // extract issuer name char name[100]; X509_NAME_oneline (X509_get_issuer_name(cert), name, 100); char * cn = strstr (name, "CN="); if (cn) - { + { cn += 3; char * family = strstr (cn, ".family"); if (family) family[0] = 0; - } + } auto pkey = X509_get_pubkey (cert); int keyType = EVP_PKEY_base_id (pkey); switch (keyType) @@ -65,7 +65,7 @@ namespace data i2p::crypto::bn2buf (y, signingKey + 32, 32); BN_free (x); BN_free (y); verifier = std::make_shared(signingKey); - } + } else LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); } @@ -79,12 +79,12 @@ namespace data EVP_PKEY_free (pkey); if (verifier && cn) m_SigningKeys[cn] = verifier; - } - SSL_free (ssl); - } + } + SSL_free (ssl); + } else LogPrint (eLogError, "Family: Can't open certificate file ", filename); - SSL_CTX_free (ctx); + SSL_CTX_free (ctx); } void Families::LoadCertificates () @@ -105,11 +105,11 @@ namespace data } LoadCertificate (file); numCertificates++; - } + } LogPrint (eLogInfo, "Family: ", numCertificates, " certificates loaded"); } - bool Families::VerifyFamily (const std::string& family, const IdentHash& ident, + bool Families::VerifyFamily (const std::string& family, const IdentHash& ident, const char * signature, const char * key) { uint8_t buf[50], signatureBuf[64]; @@ -118,12 +118,12 @@ namespace data { LogPrint (eLogError, "Family: ", family, " is too long"); return false; - } + } memcpy (buf, family.c_str (), len); memcpy (buf + len, (const uint8_t *)ident, 32); - len += 32; - Base64ToByteStream (signature, signatureLen, signatureBuf, 64); + len += 32; + Base64ToByteStream (signature, signatureLen, signatureBuf, 64); auto it = m_SigningKeys.find (family); if (it != m_SigningKeys.end ()) return it->second->Verify (buf, len, signatureBuf); @@ -136,7 +136,7 @@ namespace data auto filename = i2p::fs::DataDirPath("family", (family + ".key")); std::string sig; SSL_CTX * ctx = SSL_CTX_new (TLS_method ()); - int ret = SSL_CTX_use_PrivateKey_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); + int ret = SSL_CTX_use_PrivateKey_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); if (ret) { SSL * ssl = SSL_new (ctx); @@ -167,15 +167,15 @@ namespace data } else LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); - } - } - SSL_free (ssl); - } + } + } + SSL_free (ssl); + } else LogPrint (eLogError, "Family: Can't open keys file: ", filename); - SSL_CTX_free (ctx); + SSL_CTX_free (ctx); return sig; - } + } } } diff --git a/libi2pd/Family.h b/libi2pd/Family.h index 42a37292..a1b5a789 100644 --- a/libi2pd/Family.h +++ b/libi2pd/Family.h @@ -18,7 +18,7 @@ namespace data Families (); ~Families (); void LoadCertificates (); - bool VerifyFamily (const std::string& family, const IdentHash& ident, + bool VerifyFamily (const std::string& family, const IdentHash& ident, const char * signature, const char * key = nullptr); private: @@ -28,7 +28,7 @@ namespace data private: std::map > m_SigningKeys; - }; + }; std::string CreateFamilySignature (const std::string& family, const IdentHash& ident); // return base64 signature of empty string in case of failure diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 93c1acbe..b268baf2 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -17,16 +17,16 @@ namespace i2p { namespace garlic { - GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner, + GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr destination, int numTags, bool attachLeaseSet): - m_Owner (owner), m_Destination (destination), m_NumTags (numTags), + m_Owner (owner), m_Destination (destination), m_NumTags (numTags), m_LeaseSetUpdateStatus (attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) { // create new session tags and session key RAND_bytes (m_SessionKey, 32); m_Encryption.SetKey (m_SessionKey); - } + } GarlicRoutingSession::GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag): m_Owner (nullptr), m_NumTags (1), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) @@ -35,10 +35,10 @@ namespace garlic m_Encryption.SetKey (m_SessionKey); m_SessionTags.push_back (sessionTag); m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch (); - } + } GarlicRoutingSession::~GarlicRoutingSession () - { + { } std::shared_ptr GarlicRoutingSession::GetSharedRoutingPath () @@ -53,56 +53,56 @@ namespace garlic if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++; return m_SharedRoutingPath; } - + void GarlicRoutingSession::SetSharedRoutingPath (std::shared_ptr path) - { - if (path && path->outboundTunnel && path->remoteLease) - { + { + if (path && path->outboundTunnel && path->remoteLease) + { path->updateTime = i2p::util::GetSecondsSinceEpoch (); path->numTimesUsed = 0; - } + } else path = nullptr; m_SharedRoutingPath = path; } - + GarlicRoutingSession::UnconfirmedTags * GarlicRoutingSession::GenerateSessionTags () { auto tags = new UnconfirmedTags (m_NumTags); - tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch (); + tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch (); for (int i = 0; i < m_NumTags; i++) { RAND_bytes (tags->sessionTags[i], 32); tags->sessionTags[i].creationTime = tags->tagsCreationTime; - } - return tags; + } + return tags; } void GarlicRoutingSession::MessageConfirmed (uint32_t msgID) { TagsConfirmed (msgID); if (msgID == m_LeaseSetUpdateMsgID) - { + { m_LeaseSetUpdateStatus = eLeaseSetUpToDate; m_LeaseSetUpdateMsgID = 0; LogPrint (eLogInfo, "Garlic: LeaseSet update confirmed"); - } + } else CleanupExpiredTags (); - } - - void GarlicRoutingSession::TagsConfirmed (uint32_t msgID) - { + } + + void GarlicRoutingSession::TagsConfirmed (uint32_t msgID) + { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); auto it = m_UnconfirmedTagsMsgs.find (msgID); if (it != m_UnconfirmedTagsMsgs.end ()) { auto& tags = it->second; if (ts < tags->tagsCreationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) - { + { for (int i = 0; i < tags->numTags; i++) m_SessionTags.push_back (tags->sessionTags[i]); - } + } m_UnconfirmedTagsMsgs.erase (it); } } @@ -114,7 +114,7 @@ namespace garlic { if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) it = m_SessionTags.erase (it); - else + else ++it; } CleanupUnconfirmedTags (); @@ -123,7 +123,7 @@ namespace garlic if (m_Owner) m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); m_LeaseSetUpdateMsgID = 0; - } + } return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty (); } @@ -140,10 +140,10 @@ namespace garlic m_Owner->RemoveDeliveryStatusSession (it->first); it = m_UnconfirmedTagsMsgs.erase (it); ret = true; - } + } else ++it; - } + } return ret; } @@ -155,10 +155,10 @@ namespace garlic uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length // find non-expired tag - bool tagFound = false; - SessionTag tag; + bool tagFound = false; + SessionTag tag; if (m_NumTags > 0) - { + { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); while (!m_SessionTags.empty ()) { @@ -168,11 +168,11 @@ namespace garlic m_SessionTags.pop_front (); // use same tag only once tagFound = true; break; - } + } else m_SessionTags.pop_front (); // remove expired tag } - } + } // create message if (!tagFound) // new session { @@ -184,34 +184,34 @@ namespace garlic } // create ElGamal block ElGamalBlock elGamal; - memcpy (elGamal.sessionKey, m_SessionKey, 32); + memcpy (elGamal.sessionKey, m_SessionKey, 32); RAND_bytes (elGamal.preIV, 32); // Pre-IV uint8_t iv[32]; // IV is first 16 bytes - SHA256(elGamal.preIV, 32, iv); + SHA256(elGamal.preIV, 32, iv); BN_CTX * ctx = BN_CTX_new (); - m_Destination->Encrypt ((uint8_t *)&elGamal, buf, ctx); - BN_CTX_free (ctx); + m_Destination->Encrypt ((uint8_t *)&elGamal, buf, ctx); + BN_CTX_free (ctx); m_Encryption.SetIV (iv); buf += 514; - len += 514; + len += 514; } else // existing session - { + { // session tag - memcpy (buf, tag, 32); + memcpy (buf, tag, 32); uint8_t iv[32]; // IV is first 16 bytes SHA256(tag, 32, iv); m_Encryption.SetIV (iv); buf += 32; - len += 32; - } + len += 32; + } // AES block len += CreateAESBlock (buf, msg); htobe32buf (m->GetPayload (), len); m->len += len + 4; m->FillI2NPMessageHeader (eI2NPGarlic); return m; - } + } size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, std::shared_ptr msg) { @@ -221,13 +221,13 @@ namespace garlic htobuf16 (buf, newTags ? htobe16 (newTags->numTags) : 0); // tag count blockSize += 2; if (newTags) // session tags recreated - { + { for (int i = 0; i < newTags->numTags; i++) { memcpy (buf + blockSize, newTags->sessionTags[i], 32); // tags blockSize += 32; } - } + } uint32_t * payloadSize = (uint32_t *)(buf + blockSize); blockSize += 4; uint8_t * payloadHash = buf + blockSize; @@ -243,7 +243,7 @@ namespace garlic blockSize += (16-rem); //padding m_Encryption.Encrypt(buf, blockSize, buf); return blockSize; - } + } size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, std::shared_ptr msg, UnconfirmedTags * newTags) { @@ -256,7 +256,7 @@ namespace garlic size++; if (m_Owner) - { + { // resubmit non-confirmed LeaseSet if (m_LeaseSetUpdateStatus == eLeaseSetSubmitted && ts > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT) { @@ -267,7 +267,7 @@ namespace garlic // attach DeviveryStatus if necessary if (newTags || m_LeaseSetUpdateStatus == eLeaseSetUpdated) // new tags created or leaseset updated { - // clove is DeliveryStatus + // clove is DeliveryStatus auto cloveSize = CreateDeliveryStatusClove (payload + size, msgID); if (cloveSize > 0) // successive? { @@ -278,14 +278,14 @@ namespace garlic newTags->msgID = msgID; m_UnconfirmedTagsMsgs.insert (std::make_pair(msgID, std::unique_ptr(newTags))); newTags = nullptr; // got acquired - } + } m_Owner->DeliveryStatusSent (shared_from_this (), msgID); } else LogPrint (eLogWarning, "Garlic: DeliveryStatus clove was not created"); - } + } // attach LeaseSet - if (m_LeaseSetUpdateStatus == eLeaseSetUpdated) + if (m_LeaseSetUpdateStatus == eLeaseSetUpdated) { if (m_LeaseSetUpdateMsgID) m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); // remove previous m_LeaseSetUpdateStatus = eLeaseSetSubmitted; @@ -293,25 +293,25 @@ namespace garlic m_LeaseSetSubmissionTime = ts; // clove if our leaseSet must be attached auto leaseSet = CreateDatabaseStoreMsg (m_Owner->GetLeaseSet ()); - size += CreateGarlicClove (payload + size, leaseSet, false); + size += CreateGarlicClove (payload + size, leaseSet, false); (*numCloves)++; } - } + } if (msg) // clove message ifself if presented - { + { size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false); (*numCloves)++; - } + } memset (payload + size, 0, 3); // certificate of message size += 3; htobe32buf (payload + size, msgID); // MessageID size += 4; htobe64buf (payload + size, ts + 8000); // Expiration of message, 8 sec size += 8; - - if (newTags) delete newTags; // not acquired, delete + + if (newTags) delete newTags; // not acquired, delete return size; - } + } size_t GarlicRoutingSession::CreateGarlicClove (uint8_t * buf, std::shared_ptr msg, bool isDestination) { @@ -323,13 +323,13 @@ namespace garlic size++; memcpy (buf + size, m_Destination->GetIdentHash (), 32); size += 32; - } - else - { + } + else + { buf[size] = 0;// delivery instructions flag local size++; } - + memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); size += msg->GetLength (); uint32_t cloveID; @@ -341,34 +341,34 @@ namespace garlic memset (buf + size, 0, 3); // certificate of clove size += 3; return size; - } + } size_t GarlicRoutingSession::CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID) - { + { size_t size = 0; if (m_Owner) { auto inboundTunnel = m_Owner->GetTunnelPool ()->GetNextInboundTunnel (); if (inboundTunnel) - { + { buf[size] = eGarlicDeliveryTypeTunnel << 5; // delivery instructions flag tunnel size++; - // hash and tunnelID sequence is reversed for Garlic + // hash and tunnelID sequence is reversed for Garlic memcpy (buf + size, inboundTunnel->GetNextIdentHash (), 32); // To Hash size += 32; htobe32buf (buf + size, inboundTunnel->GetNextTunnelID ()); // tunnelID - size += 4; - // create msg + size += 4; + // create msg auto msg = CreateDeliveryStatusMsg (msgID); if (m_Owner) { - //encrypt + //encrypt uint8_t key[32], tag[32]; - RAND_bytes (key, 32); // random session key + RAND_bytes (key, 32); // random session key RAND_bytes (tag, 32); // random session tag m_Owner->SubmitSessionKey (key, tag); GarlicRoutingSession garlic (key, tag); - msg = garlic.WrapSingleMessage (msg); + msg = garlic.WrapSingleMessage (msg); } memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); size += msg->GetLength (); @@ -383,7 +383,7 @@ namespace garlic memset (buf + size, 0, 3); // certificate of clove size += 3; } - else + else LogPrint (eLogError, "Garlic: No inbound tunnels in the pool for DeliveryStatus"); } else @@ -395,19 +395,19 @@ namespace garlic GarlicDestination::GarlicDestination (): m_NumTags (32) // 32 tags by default { m_Ctx = BN_CTX_new (); - } - + } + GarlicDestination::~GarlicDestination () { BN_CTX_free (m_Ctx); } void GarlicDestination::CleanUp () - { + { m_Sessions.clear (); m_DeliveryStatusSessions.clear (); m_Tags.clear (); - } + } void GarlicDestination::AddSessionKey (const uint8_t * key, const uint8_t * tag) { if (key) @@ -417,7 +417,7 @@ namespace garlic } } - bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) + bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) { AddSessionKey (key, tag); return true; @@ -431,22 +431,22 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ()); return; - } + } buf += 4; // length auto it = m_Tags.find (SessionTag(buf)); if (it != m_Tags.end ()) { // tag found. Use AES auto decryption = it->second; - m_Tags.erase (it); // tag might be used only once + m_Tags.erase (it); // tag might be used only once if (length >= 32) - { + { uint8_t iv[32]; // IV is first 16 bytes SHA256(buf, 32, iv); decryption->SetIV (iv); decryption->Decrypt (buf + 32, length - 32, buf + 32); HandleAESBlock (buf + 32, length - 32, decryption, msg->from); - } + } else LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes"); } @@ -455,35 +455,35 @@ namespace garlic // tag not found. Use ElGamal ElGamalBlock elGamal; if (length >= 514 && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx)) - { + { auto decryption = std::make_shared(elGamal.sessionKey); uint8_t iv[32]; // IV is first 16 bytes - SHA256(elGamal.preIV, 32, iv); + SHA256(elGamal.preIV, 32, iv); decryption->SetIV (iv); decryption->Decrypt(buf + 514, length - 514, buf + 514); HandleAESBlock (buf + 514, length - 514, decryption, msg->from); - } + } else LogPrint (eLogError, "Garlic: Failed to decrypt message"); } - } + } void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, std::shared_ptr from) { uint16_t tagCount = bufbe16toh (buf); - buf += 2; len -= 2; + buf += 2; len -= 2; if (tagCount > 0) - { - if (tagCount*32 > len) + { + if (tagCount*32 > len) { LogPrint (eLogError, "Garlic: Tag count ", tagCount, " exceeds length ", len); return ; - } + } uint32_t ts = i2p::util::GetSecondsSinceEpoch (); for (int i = 0; i < tagCount; i++) - m_Tags[SessionTag(buf + i*32, ts)] = decryption; - } + m_Tags[SessionTag(buf + i*32, ts)] = decryption; + } buf += tagCount*32; len -= tagCount*32; uint32_t payloadSize = bufbe32toh (buf); @@ -491,10 +491,10 @@ namespace garlic { LogPrint (eLogError, "Garlic: Unexpected payload size ", payloadSize); return; - } + } buf += 4; uint8_t * payloadHash = buf; - buf += 32;// payload hash. + buf += 32;// payload hash. if (*buf) // session key? buf += 32; // new session key buf++; // flag @@ -506,9 +506,9 @@ namespace garlic { LogPrint (eLogError, "Garlic: wrong payload hash"); return; - } + } HandleGarlicPayload (buf, payloadSize, from); - } + } void GarlicDestination::HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr from) { @@ -530,8 +530,8 @@ namespace garlic { // TODO: implement LogPrint (eLogWarning, "Garlic: clove encrypted"); - buf += 32; - } + buf += 32; + } ptrdiff_t offset = buf - buf1; GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03); switch (deliveryType) @@ -542,10 +542,10 @@ namespace garlic { LogPrint (eLogError, "Garlic: message is too short"); break; - } + } HandleI2NPMessage (buf, len - offset, from); - break; - case eGarlicDeliveryTypeDestination: + break; + case eGarlicDeliveryTypeDestination: LogPrint (eLogDebug, "Garlic: type destination"); buf += 32; // destination. check it later or for multiple destinations offset = buf - buf1; @@ -553,11 +553,11 @@ namespace garlic { LogPrint (eLogError, "Garlic: message is too short"); break; - } - HandleI2NPMessage (buf, len - offset, from); + } + HandleI2NPMessage (buf, len - offset, from); break; case eGarlicDeliveryTypeTunnel: - { + { LogPrint (eLogDebug, "Garlic: type tunnel"); // gwHash and gwTunnel sequence is reverted uint8_t * gwHash = buf; @@ -591,7 +591,7 @@ namespace garlic { uint8_t * ident = buf; buf += 32; - offset = buf - buf1; + offset = buf - buf1; if (!from) // received directly { if (offset > (int)len) @@ -604,7 +604,7 @@ namespace garlic } else LogPrint (eLogWarning, "Garlic: type router for inbound tunnels not supported"); - break; + break; } default: LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType); @@ -623,23 +623,23 @@ namespace garlic { LogPrint (eLogError, "Garlic: clove is too long"); break; - } + } len -= offset; - } - } - - std::shared_ptr GarlicDestination::WrapMessage (std::shared_ptr destination, - std::shared_ptr msg, bool attachLeaseSet) + } + } + + std::shared_ptr GarlicDestination::WrapMessage (std::shared_ptr destination, + std::shared_ptr msg, bool attachLeaseSet) { - auto session = GetRoutingSession (destination, attachLeaseSet); - return session->WrapSingleMessage (msg); + auto session = GetRoutingSession (destination, attachLeaseSet); + return session->WrapSingleMessage (msg); } std::shared_ptr GarlicDestination::GetRoutingSession ( std::shared_ptr destination, bool attachLeaseSet) { GarlicRoutingSessionPtr session; - { + { std::unique_lock l(m_SessionsMutex); auto it = m_Sessions.find (destination->GetIdentHash ()); if (it != m_Sessions.end ()) @@ -647,14 +647,14 @@ namespace garlic } if (!session) { - session = std::make_shared (this, destination, + session = std::make_shared (this, destination, attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests std::unique_lock l(m_SessionsMutex); m_Sessions[destination->GetIdentHash ()] = session; - } + } return session; - } - + } + void GarlicDestination::CleanupExpiredTags () { // incoming @@ -666,7 +666,7 @@ namespace garlic { numExpiredTags++; it = m_Tags.erase (it); - } + } else ++it; } @@ -690,7 +690,7 @@ namespace garlic } } // delivery status sessions - { + { std::unique_lock l(m_DeliveryStatusSessionsMutex); for (auto it = m_DeliveryStatusSessions.begin (); it != m_DeliveryStatusSessions.end (); ) { @@ -699,7 +699,7 @@ namespace garlic else ++it; } - } + } } void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID) @@ -756,7 +756,7 @@ namespace garlic if (m_Tags.empty ()) return; std::string ident = GetIdentHash().ToBase32(); std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags")); - std::ofstream f (path, std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); + std::ofstream f (path, std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); uint32_t ts = i2p::util::GetSecondsSinceEpoch (); // 4 bytes timestamp, 32 bytes tag, 32 bytes key for (auto it: m_Tags) @@ -766,7 +766,7 @@ namespace garlic f.write ((char *)&it.first.creationTime, 4); f.write ((char *)it.first.data (), 32); f.write ((char *)it.second->GetKey ().data (), 32); - } + } } } @@ -775,11 +775,11 @@ namespace garlic std::string ident = GetIdentHash().ToBase32(); std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags")); uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - if (ts < i2p::fs::GetLastUpdateTime (path) + INCOMING_TAGS_EXPIRATION_TIMEOUT) + if (ts < i2p::fs::GetLastUpdateTime (path) + INCOMING_TAGS_EXPIRATION_TIMEOUT) { // might contain non-expired tags std::ifstream f (path, std::ifstream::binary); - if (f) + if (f) { std::map > keys; // 4 bytes timestamp, 32 bytes tag, 32 bytes key @@ -794,7 +794,7 @@ namespace garlic f.read ((char *)key, 32); } else - f.seekg (64, std::ios::cur); // skip + f.seekg (64, std::ios::cur); // skip if (f.eof ()) break; std::shared_ptr decryption; @@ -805,21 +805,21 @@ namespace garlic decryption = std::make_shared(key); m_Tags.insert (std::make_pair (SessionTag (tag, ts), decryption)); } - if (!m_Tags.empty ()) - LogPrint (eLogInfo, m_Tags.size (), " loaded for ", ident); + if (!m_Tags.empty ()) + LogPrint (eLogInfo, m_Tags.size (), " loaded for ", ident); } } - i2p::fs::Remove (path); + i2p::fs::Remove (path); } void CleanUpTagsFiles () { - std::vector files; + std::vector files; i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files); uint32_t ts = i2p::util::GetSecondsSinceEpoch (); for (auto it: files) if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT) i2p::fs::Remove (it); } -} +} } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index b78b89f9..c5236c90 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -17,46 +17,46 @@ namespace i2p { namespace tunnel -{ +{ class OutboundTunnel; } - + namespace garlic { - - enum GarlicDeliveryType - { - eGarlicDeliveryTypeLocal = 0, + + enum GarlicDeliveryType + { + eGarlicDeliveryTypeLocal = 0, eGarlicDeliveryTypeDestination = 1, - eGarlicDeliveryTypeRouter = 2, + eGarlicDeliveryTypeRouter = 2, eGarlicDeliveryTypeTunnel = 3 - }; + }; struct ElGamalBlock { uint8_t sessionKey[32]; uint8_t preIV[32]; uint8_t padding[158]; - }; + }; - const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 960; // 16 minutes + const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 960; // 16 minutes const int OUTGOING_TAGS_EXPIRATION_TIMEOUT = 720; // 12 minutes - const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds + const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds const int LEASET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds - const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds - const int ROUTING_PATH_MAX_NUM_TIMES_USED = 100; // how many times might be used - - struct SessionTag: public i2p::data::Tag<32> + const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds + const int ROUTING_PATH_MAX_NUM_TIMES_USED = 100; // how many times might be used + + struct SessionTag: public i2p::data::Tag<32> { SessionTag (const uint8_t * buf, uint32_t ts = 0): Tag<32>(buf), creationTime (ts) {}; SessionTag () = default; SessionTag (const SessionTag& ) = default; SessionTag& operator= (const SessionTag& ) = default; #ifndef _WIN32 - SessionTag (SessionTag&& ) = default; - SessionTag& operator= (SessionTag&& ) = default; + SessionTag (SessionTag&& ) = default; + SessionTag& operator= (SessionTag&& ) = default; #endif - uint32_t creationTime; // seconds since epoch + uint32_t creationTime; // seconds since epoch }; // AESDecryption is associated with session tags and store key @@ -67,7 +67,7 @@ namespace garlic AESDecryption (const uint8_t * key): m_Key (key) { SetKey (key); - } + } const i2p::crypto::AESKey& GetKey () const { return m_Key; }; private: @@ -81,8 +81,8 @@ namespace garlic std::shared_ptr remoteLease; int rtt; // RTT uint32_t updateTime; // seconds since epoch - int numTimesUsed; - }; + int numTimesUsed; + }; class GarlicDestination; class GarlicRoutingSession: public std::enable_shared_from_this @@ -94,7 +94,7 @@ namespace garlic eLeaseSetSubmitted, eLeaseSetDoNotSend }; - + struct UnconfirmedTags { UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; }; @@ -107,23 +107,23 @@ namespace garlic public: - GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr destination, + GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr destination, int numTags, bool attachLeaseSet); GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption ~GarlicRoutingSession (); std::shared_ptr WrapSingleMessage (std::shared_ptr msg); void MessageConfirmed (uint32_t msgID); - bool CleanupExpiredTags (); // returns true if something left + bool CleanupExpiredTags (); // returns true if something left bool CleanupUnconfirmedTags (); // returns true if something has been deleted - void SetLeaseSetUpdated () - { - if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; + void SetLeaseSetUpdated () + { + if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; }; bool IsLeaseSetNonConfirmed () const { return m_LeaseSetUpdateStatus == eLeaseSetSubmitted; }; bool IsLeaseSetUpdated () const { return m_LeaseSetUpdateStatus == eLeaseSetUpdated; }; - uint64_t GetLeaseSetSubmissionTime () const { return m_LeaseSetSubmissionTime; } - + uint64_t GetLeaseSetSubmissionTime () const { return m_LeaseSetSubmissionTime; } + std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); @@ -144,26 +144,26 @@ namespace garlic GarlicDestination * m_Owner; std::shared_ptr m_Destination; - + i2p::crypto::AESKey m_SessionKey; std::list m_SessionTags; int m_NumTags; - std::map > m_UnconfirmedTagsMsgs; // msgID->tags - + std::map > m_UnconfirmedTagsMsgs; // msgID->tags + LeaseSetUpdateStatus m_LeaseSetUpdateStatus; uint32_t m_LeaseSetUpdateMsgID; uint64_t m_LeaseSetSubmissionTime; // in milliseconds - + i2p::crypto::CBCEncryption m_Encryption; std::shared_ptr m_SharedRoutingPath; - + public: // for HTTP only size_t GetNumOutgoingTags () const { return m_SessionTags.size (); }; - }; + }; //using GarlicRoutingSessionPtr = std::shared_ptr; - typedef std::shared_ptr GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 + typedef std::shared_ptr GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 class GarlicDestination: public i2p::data::LocalDestination { @@ -173,36 +173,36 @@ namespace garlic ~GarlicDestination (); void CleanUp (); - void SetNumTags (int numTags) { m_NumTags = numTags; }; - std::shared_ptr GetRoutingSession (std::shared_ptr destination, bool attachLeaseSet); + void SetNumTags (int numTags) { m_NumTags = numTags; }; + std::shared_ptr GetRoutingSession (std::shared_ptr destination, bool attachLeaseSet); void CleanupExpiredTags (); void RemoveDeliveryStatusSession (uint32_t msgID); - std::shared_ptr WrapMessage (std::shared_ptr destination, + std::shared_ptr WrapMessage (std::shared_ptr destination, std::shared_ptr msg, bool attachLeaseSet = false); void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID); - + virtual void ProcessGarlicMessage (std::shared_ptr msg); - virtual void ProcessDeliveryStatusMessage (std::shared_ptr msg); + virtual void ProcessDeliveryStatusMessage (std::shared_ptr msg); virtual void SetLeaseSetUpdated (); - + virtual std::shared_ptr GetLeaseSet () = 0; // TODO virtual std::shared_ptr GetTunnelPool () const = 0; virtual void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) = 0; - + protected: void HandleGarlicMessage (std::shared_ptr msg); - void HandleDeliveryStatusMessage (std::shared_ptr msg); + void HandleDeliveryStatusMessage (std::shared_ptr msg); void SaveTags (); - void LoadTags (); + void LoadTags (); private: - void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, + void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, std::shared_ptr from); void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr from); @@ -218,17 +218,17 @@ namespace garlic // DeliveryStatus std::mutex m_DeliveryStatusSessionsMutex; std::map m_DeliveryStatusSessions; // msgID -> session - + public: // for HTTP only - size_t GetNumIncomingTags () const { return m_Tags.size (); } + size_t GetNumIncomingTags () const { return m_Tags.size (); } const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; }; void CleanUpTagsFiles (); - -} + +} } #endif diff --git a/libi2pd/Gost.cpp b/libi2pd/Gost.cpp index 8663289a..5773fe15 100644 --- a/libi2pd/Gost.cpp +++ b/libi2pd/Gost.cpp @@ -28,7 +28,7 @@ namespace crypto GOSTR3410Curve::~GOSTR3410Curve () { EC_GROUP_free (m_Group); - } + } EC_POINT * GOSTR3410Curve::MulP (const BIGNUM * n) const { @@ -81,12 +81,12 @@ namespace crypto BN_mod_inverse (h, h, q, ctx); // 1/h mod q BIGNUM * z1 = BN_CTX_get (ctx); BN_mod_mul (z1, s, h, q, ctx); // z1 = s/h - BIGNUM * z2 = BN_CTX_get (ctx); + BIGNUM * z2 = BN_CTX_get (ctx); BN_sub (z2, q, r); // z2 = -r BN_mod_mul (z2, z2, h, q, ctx); // z2 = -r/h EC_POINT * C = EC_POINT_new (m_Group); EC_POINT_mul (m_Group, C, z1, pub, z2, ctx); // z1*P + z2*pub - BIGNUM * x = BN_CTX_get (ctx); + BIGNUM * x = BN_CTX_get (ctx); GetXY (C, x, nullptr); // Cx BN_mod (x, x, q, ctx); // Cx % q bool ret = !BN_cmp (x, r); // Cx = r ? @@ -94,9 +94,9 @@ namespace crypto BN_CTX_end (ctx); BN_CTX_free (ctx); return ret; - } + } - EC_POINT * GOSTR3410Curve::RecoverPublicKey (const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s, bool isNegativeY) const + EC_POINT * GOSTR3410Curve::RecoverPublicKey (const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s, bool isNegativeY) const { // s*P = r*Q + h*C BN_CTX * ctx = BN_CTX_new (); @@ -104,7 +104,7 @@ namespace crypto EC_POINT * C = EC_POINT_new (m_Group); // C = k*P = (rx, ry) EC_POINT * Q = nullptr; if (EC_POINT_set_compressed_coordinates_GFp (m_Group, C, r, isNegativeY ? 1 : 0, ctx)) - { + { EC_POINT * S = EC_POINT_new (m_Group); // S = s*P EC_POINT_mul (m_Group, S, s, nullptr, nullptr, ctx); BIGNUM * q = BN_CTX_get (ctx); @@ -112,28 +112,28 @@ namespace crypto BIGNUM * h = BN_CTX_get (ctx); BN_mod (h, digest, q, ctx); // h = digest % q BN_sub (h, q, h); // h = -h - EC_POINT * H = EC_POINT_new (m_Group); + EC_POINT * H = EC_POINT_new (m_Group); EC_POINT_mul (m_Group, H, nullptr, C, h, ctx); // -h*C EC_POINT_add (m_Group, C, S, H, ctx); // s*P - h*C EC_POINT_free (H); EC_POINT_free (S); BIGNUM * r1 = BN_CTX_get (ctx); BN_mod_inverse (r1, r, q, ctx); - Q = EC_POINT_new (m_Group); - EC_POINT_mul (m_Group, Q, nullptr, C, r1, ctx); // (s*P - h*C)/r - } + Q = EC_POINT_new (m_Group); + EC_POINT_mul (m_Group, Q, nullptr, C, r1, ctx); // (s*P - h*C)/r + } EC_POINT_free (C); BN_CTX_end (ctx); BN_CTX_free (ctx); return Q; - } - + } + static GOSTR3410Curve * CreateGOSTR3410Curve (GOSTR3410ParamSet paramSet) { - // a, b, p, q, x, y - static const char * params[eGOSTR3410NumParamSets][6] = + // a, b, p, q, x, y + static const char * params[eGOSTR3410NumParamSets][6] = { - { + { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94", "A6", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", @@ -147,10 +147,10 @@ namespace crypto "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275", "3", - "7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4" + "7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4" } // tc26-2012-paramSetA-512 - }; - + }; + BIGNUM * a = nullptr, * b = nullptr, * p = nullptr, * q =nullptr, * x = nullptr, * y = nullptr; BN_hex2bn(&a, params[paramSet][0]); BN_hex2bn(&b, params[paramSet][1]); @@ -161,25 +161,25 @@ namespace crypto auto curve = new GOSTR3410Curve (a, b, p, q, x, y); BN_free (a); BN_free (b); BN_free (p); BN_free (q); BN_free (x); BN_free (y); return curve; - } + } static std::array, eGOSTR3410NumParamSets> g_GOSTR3410Curves; std::unique_ptr& GetGOSTR3410Curve (GOSTR3410ParamSet paramSet) { if (!g_GOSTR3410Curves[paramSet]) { - auto c = CreateGOSTR3410Curve (paramSet); + auto c = CreateGOSTR3410Curve (paramSet); if (!g_GOSTR3410Curves[paramSet]) // make sure it was not created already g_GOSTR3410Curves[paramSet].reset (c); else delete c; - } - return g_GOSTR3410Curves[paramSet]; + } + return g_GOSTR3410Curves[paramSet]; } // ГОСТ 34.11-2012 - static const uint64_t T0[256] = + static const uint64_t T0[256] = { 0xE6F87E5C5B711FD0, 0x258377800924FA16, 0xC849E07E852EA4A8, 0x5B4686A18F06C16A, 0x0B32E9A2D77B416E, 0xABDA37A467815C66, 0xF61796A81A686676, 0xF5DC0B706391954B, @@ -246,7 +246,7 @@ namespace crypto 0x92BDE697D67F3422, 0xC78933E10514BC61, 0xE1C1D9B975C9B54A, 0xD2266160CF1BCD80, 0x9A4492ED78FD8671, 0xB3CCAB2A881A9793, 0x72CEBF667FE1D088, 0xD6D45B5D985A9427 }; - static const uint64_t T1[256] = + static const uint64_t T1[256] = { 0xC811A8058C3F55DE, 0x65F5B43196B50619, 0xF74F96B1D6706E43, 0x859D1E8BCB43D336, 0x5AAB8A85CCFA3D84, 0xF9C7BF99C295FCFD, 0xA21FD5A1DE4B630F, 0xCDB3EF763B8B456D, @@ -313,7 +313,7 @@ namespace crypto 0x57B69E77B57354A0, 0x3969441D8097D0B4, 0x3330CAFBF3E2F0CF, 0xE28E77DDE0BE8CC3, 0x62B12E259C494F46, 0xA6CE726FB9DBD1CA, 0x41E242C1EED14DBA, 0x76032FF47AA30FB0 }; - static const uint64_t T2[256] = + static const uint64_t T2[256] = { 0x45B268A93ACDE4CC, 0xAF7F0BE884549D08, 0x048354B3C1468263, 0x925435C2C80EFED2, 0xEE4E37F27FDFFBA7, 0x167A33920C60F14D, 0xFB123B52EA03E584, 0x4A0CAB53FDBB9007, @@ -380,7 +380,7 @@ namespace crypto 0xF9DD11850420A43B, 0x4BE5BEB68A243ED6, 0x5584255F19C8D65D, 0x3B67404E633FA006, 0xA68DB6766C472A1F, 0xF78AC79AB4C97E21, 0xC353442E1080AAEC, 0x9A4F9DB95782E714 }; - static const uint64_t T3[256] = + static const uint64_t T3[256] = { 0x05BA7BC82C9B3220, 0x31A54665F8B65E4F, 0xB1B651F77547F4D4, 0x8BFA0D857BA46682, 0x85A96C5AA16A98BB, 0x990FAEF908EB79C9, 0xA15E37A247F4A62D, 0x76857DCD5D27741E, @@ -447,7 +447,7 @@ namespace crypto 0x77059157F359DC47, 0x1D262E3907FF492B, 0xFB582233E59AC557, 0xDDB2BCE242F8B673, 0x2577B76248E096CF, 0x6F99C4A6D83DA74C, 0xC1147E41EB795701, 0xF48BAF76912A9337 }; - static const uint64_t T4[256] = + static const uint64_t T4[256] = { 0x3EF29D249B2C0A19, 0xE9E16322B6F8622F, 0x5536994047757F7A, 0x9F4D56D5A47B0B33, 0x822567466AA1174C, 0xB8F5057DEB082FB2, 0xCC48C10BF4475F53, 0x373088D4275DEC3A, @@ -514,7 +514,7 @@ namespace crypto 0x6853032B59F3EE6E, 0x65B3E9C4FF073AAA, 0x772AC3399AE5EBEC, 0x87816E97F842A75B, 0x110E2DB2E0484A4B, 0x331277CB3DD8DEDD, 0xBD510CAC79EB9FA5, 0x352179552A91F5C7 }; - static const uint64_t T5[256] = + static const uint64_t T5[256] = { 0x8AB0A96846E06A6D, 0x43C7E80B4BF0B33A, 0x08C9B3546B161EE5, 0x39F1C235EBA990BE, 0xC1BEF2376606C7B2, 0x2C209233614569AA, 0xEB01523B6FC3289A, 0x946953AB935ACEDD, @@ -581,7 +581,7 @@ namespace crypto 0xEFEB8511D4C82766, 0x961CB6BE40D147A3, 0xAAB35F25F7B812DE, 0x76154E407044329D, 0x513D76B64E570693, 0xF3479AC7D2F90AA8, 0x9B8B2E4477079C85, 0x297EB99D3D85AC69 }; - static const uint64_t T6[256] = + static const uint64_t T6[256] = { 0x7E37E62DFC7D40C3, 0x776F25A4EE939E5B, 0xE045C850DD8FB5AD, 0x86ED5BA711FF1952, 0xE91D0BD9CF616B35, 0x37E0AB256E408FFB, 0x9607F6C031025A7A, 0x0B02F5E116D23C9D, @@ -648,7 +648,7 @@ namespace crypto 0xE6AB92E8D1CB8EA2, 0x3354C7F5663856F1, 0xD93EE170AF7BAE4D, 0x616BD27BC22AE67C, 0x92B39A10397A8370, 0xABC8B3304B8E9890, 0xBF967287630B02B2, 0x5B67D607B6FC6E15 }; - static uint64_t T7[256] = + static uint64_t T7[256] = { 0xD031C397CE553FE6, 0x16BA5B01B006B525, 0xA89BADE6296E70C8, 0x6A1F525D77D3435B, 0x6E103570573DFA0B, 0x660EFB2A17FC95AB, 0x76327A9E97634BF6, 0x4BAD9D6462458BF5, @@ -716,59 +716,59 @@ namespace crypto 0x717E7067AF4F499A, 0x938290A9ECD1DBB3, 0x88E3B293344DD172, 0x2734158C250FA3D6 }; - static const uint64_t C_[12][8] = + static const uint64_t C_[12][8] = { { 0xe9daca1eda5b08b1, 0x1f7c65c0812fcbeb, 0x16d0452e43766a2f, 0xfcc485758db84e71, 0x0169679291e07c4b, 0x15d360a4082a42a2, 0x234d74cc36747605, 0x0745a6f2596580dd - }, + }, { 0x1a2f9da98ab5a36f, 0xd7b5700f469de34f, 0x982b230a72eafef3, 0x3101b5160f5ed561, 0x5899d6126b17b59a, 0xcaa70adbc261b55c, 0x56cdcbd71ba2dd55, 0xb79bb121700479e6 - }, + }, { 0xc72fce2bacdc74f5, 0x35843d6a28fc390a, 0x8b1f9c525f5ef106, 0x7b7b29b11475eaf2, 0xb19e3590e40fe2d3, 0x09db6260373ac9c1, 0x31db7a8643f4b6c2, 0xb20aba0af5961e99 - }, + }, { 0xd26615e8b3df1fef, 0xdde4715da0e148f9, 0x7d3c5c337e858e48, 0x3f355e68ad1c729d, 0x75d603ed822cd7a9, 0xbe0352933313b7d8, 0xf137e893a1ea5334, 0x2ed1e384bcbe0c22 - }, + }, { 0x994747adac6bea4b, 0x6323a96c0c413f9a, 0x4a1086161f1c157f, 0xbdff0f80d7359e35, 0xa3f53a254717cdbf, 0x161a2723b700ffdf, 0xf563eaa97ea2567a, 0x57fe6c7cfd581760 - }, + }, { 0xd9d33a1daeae4fae, 0xc039307a3bc3a46f, 0x6ca44251f9c4662d, 0xc68ef09ab49a7f18, 0xb4b79a1cb7a6facf, 0xb6c6bec2661ff20a, 0x354f903672c571bf, 0x6e7d64467a4068fa - }, + }, { 0xecc5aaee160ec7f4, 0x540924bffe86ac51, 0xc987bfe6c7c69e39, 0xc9937a19333e47d3, 0x372c822dc5ab9209, 0x04054a2883694706, 0xf34a3ca24c451735, 0x93d4143a4d568688 - }, + }, { 0xa7c9934d425b1f9b, 0x41416e0c02aae703, 0x1ede369c71f8b74e, 0x9ac4db4d3b44b489, 0x90069b92cb2b89f4, 0x2fc4a5d12b8dd169, 0xd9a8515935c2ac36, 0x1ee702bfd40d7fa4 - }, + }, { 0x9b223116545a8f37, 0xde5f16ecd89a4c94, 0x244289251b3a7d3a, 0x84090de0b755d93c, 0xb1ceb2db0b440a80, 0x549c07a69a8a2b7b, 0x602a1fcb92dc380e, 0xdb5a238351446172 - }, + }, { 0x526f0580a6debeab, 0xf3f3e4b248e52a38, 0xdb788aff1ce74189, 0x0361331b8ae1ff1f, 0x4b3369af0267e79f, 0xf452763b306c1e7a, 0xc3b63b15d1fa9836, 0xed9c4598fbc7b474 - }, + }, { 0xfb89c8efd09ecd7b, 0x94fe5a63cdc60230, 0x6107abebbb6bfad8, 0x7966841421800120, 0xcab948eaef711d8a, 0x986e477d1dcdbaef, 0x5dd86fc04a59a2de, 0x1b2df381cda4ca6b - }, + }, { 0xba3116f167e78e37, 0x7ab14904b08013d2, 0x771ddfbc323ca4cd, 0x9b9f2130d41220f8, 0x86cc91189def805d, 0x5228e188aaa41de7, 0x991bb2d9d517f4fa, 0x20d71bf14a92bc48 } }; - + union GOST3411Block // 8 bytes aligned { uint8_t buf[64]; @@ -780,15 +780,15 @@ namespace crypto for (int i = 0; i < 8; i++) ret.ll[i] = ll[i]^other.ll[i]; return ret; - } - + } + GOST3411Block operator^(const uint64_t * other) const { GOST3411Block ret; for (int i = 0; i < 8; i++) ret.ll[i] = ll[i]^other[i]; return ret; - } + } GOST3411Block operator+(const GOST3411Block& other) const { @@ -799,7 +799,7 @@ namespace crypto uint16_t sum = buf[i] + other.buf[i] + carry; ret.buf[i] = sum; carry = sum >> 8; - } + } return ret; } @@ -807,17 +807,17 @@ namespace crypto { for (int i = 63; i >= 0; i--) { - if (!c) return; + if (!c) return; c += buf[i]; buf[i] = c; - c >>= 8; + c >>= 8; } } void F () { uint64_t res[8]; - for (int b=0; b<8; b++) + for (int b=0; b<8; b++) { uint64_t r; r = T0[buf[b+56]]; @@ -843,11 +843,11 @@ namespace crypto k = k^C_[i]; k.F (); res = k^res; - } + } return res; - } + } }; - + static GOST3411Block gN (const GOST3411Block& N, const GOST3411Block& h, const GOST3411Block& m) { GOST3411Block res = N ^ h; @@ -855,12 +855,12 @@ namespace crypto res = res.E (m); res = res^h; res = res^m; - return res; - } + return res; + } static void H (const uint8_t * iv, const uint8_t * buf, size_t len, uint8_t * digest) { - // stage 1 + // stage 1 GOST3411Block h, N, s, m; memcpy (h.buf, iv, 64); memset (N.buf, 0, 64); @@ -885,15 +885,15 @@ namespace crypto memcpy (m.buf + padding, buf, l); h = gN (N, h, m); - N.Add (l*8); + N.Add (l*8); s = m + s; - + GOST3411Block N0; memset (N0.buf, 0, 64); h = gN (N0, h, N); h = gN (N0, h, s); - - memcpy (digest, h.buf, 64); + + memcpy (digest, h.buf, 64); } void GOSTR3411_2012_256 (const uint8_t * buf, size_t len, uint8_t * digest) @@ -919,7 +919,7 @@ namespace crypto size_t len; bool is512; }; - + GOSTR3411_2012_CTX * GOSTR3411_2012_CTX_new () { return new GOSTR3411_2012_CTX; @@ -949,7 +949,7 @@ namespace crypto size_t l = 64 - ctx->len; if (len < l) l = len; for (size_t i = 0; i < l; i++) - ctx->m.buf[ctx->len + i] = buf[l-i-1]; // invert + ctx->m.buf[ctx->len + i] = buf[l-i-1]; // invert ctx->len += l; len -= l; buf += l; ctx->h = gN (ctx->N, ctx->h, ctx->m); @@ -959,7 +959,7 @@ namespace crypto while (len >= 64) { for (size_t i = 0; i < 64; i++) - ctx->m.buf[i] = buf[63-i]; // invert + ctx->m.buf[i] = buf[63-i]; // invert len -= 64; buf += 64; ctx->h = gN (ctx->N, ctx->h, ctx->m); ctx->N.Add (512); @@ -975,7 +975,7 @@ namespace crypto void GOSTR3411_2012_CTX_Finish (uint8_t * digest, GOSTR3411_2012_CTX * ctx) { - GOST3411Block m; + GOST3411Block m; size_t padding = 64 - ctx->len; if (padding) { @@ -985,14 +985,14 @@ namespace crypto memcpy (m.buf + padding, ctx->m.buf, ctx->len); ctx->h = gN (ctx->N, ctx->h, m); - ctx->N.Add (ctx->len*8); + ctx->N.Add (ctx->len*8); ctx->s = m + ctx->s; - + GOST3411Block N0; memset (N0.buf, 0, 64); ctx->h = gN (N0, ctx->h, ctx->N); ctx->h = gN (N0, ctx->h, ctx->s); - + size_t sz = ctx->is512 ? 64 : 32; for (size_t i = 0; i < sz; i++) digest[i] = ctx->h.buf[sz - i - 1]; diff --git a/libi2pd/Gost.h b/libi2pd/Gost.h index 66e8bbe8..30386104 100644 --- a/libi2pd/Gost.h +++ b/libi2pd/Gost.h @@ -10,25 +10,25 @@ namespace crypto { // ГОСТ Р 34.10 - + enum GOSTR3410ParamSet { eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1 // XchA = A, XchB = C //eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0 - //eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1 + //eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1 eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1 eGOSTR3410NumParamSets - }; - + }; + class GOSTR3410Curve { public: GOSTR3410Curve (BIGNUM * a, BIGNUM * b, BIGNUM * p, BIGNUM * q, BIGNUM * x, BIGNUM * y); - ~GOSTR3410Curve (); + ~GOSTR3410Curve (); - size_t GetKeyLen () const { return m_KeyLen; }; + size_t GetKeyLen () const { return m_KeyLen; }; const EC_GROUP * GetGroup () const { return m_Group; }; EC_POINT * MulP (const BIGNUM * n) const; bool GetXY (const EC_POINT * p, BIGNUM * x, BIGNUM * y) const; @@ -36,7 +36,7 @@ namespace crypto void Sign (const BIGNUM * priv, const BIGNUM * digest, BIGNUM * r, BIGNUM * s); bool Verify (const EC_POINT * pub, const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s); EC_POINT * RecoverPublicKey (const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s, bool isNegativeY = false) const; - + private: EC_GROUP * m_Group; @@ -47,14 +47,14 @@ namespace crypto // Big Endian void GOSTR3411_2012_256 (const uint8_t * buf, size_t len, uint8_t * digest); - void GOSTR3411_2012_512 (const uint8_t * buf, size_t len, uint8_t * digest); + void GOSTR3411_2012_512 (const uint8_t * buf, size_t len, uint8_t * digest); // Little Endian struct GOSTR3411_2012_CTX; GOSTR3411_2012_CTX * GOSTR3411_2012_CTX_new (); void GOSTR3411_2012_CTX_Init (GOSTR3411_2012_CTX * ctx, bool is512 = true); void GOSTR3411_2012_CTX_Update (const uint8_t * buf, size_t len, GOSTR3411_2012_CTX * ctx); - void GOSTR3411_2012_CTX_Finish (uint8_t * digest, GOSTR3411_2012_CTX * ctx); + void GOSTR3411_2012_CTX_Finish (uint8_t * digest, GOSTR3411_2012_CTX * ctx); void GOSTR3411_2012_CTX_free (GOSTR3411_2012_CTX * ctx); } } diff --git a/libi2pd/Gzip.cpp b/libi2pd/Gzip.cpp index db991283..1c06e941 100644 --- a/libi2pd/Gzip.cpp +++ b/libi2pd/Gzip.cpp @@ -12,9 +12,9 @@ #include "Log.h" #include "Gzip.h" -namespace i2p +namespace i2p { -namespace data +namespace data { const size_t GZIP_CHUNK_SIZE = 16384; @@ -38,7 +38,7 @@ namespace data m_Inflator.next_out = out; m_Inflator.avail_out = outLen; int err; - if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END) + if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END) return outLen - m_Inflator.avail_out; // else LogPrint (eLogError, "Gzip: Inflate error ", err); @@ -52,19 +52,19 @@ namespace data m_Inflator.next_in = const_cast(in); m_Inflator.avail_in = inLen; int ret; - do + do { m_Inflator.next_out = out; m_Inflator.avail_out = GZIP_CHUNK_SIZE; ret = inflate (&m_Inflator, Z_NO_FLUSH); - if (ret < 0) + if (ret < 0) { inflateEnd (&m_Inflator); os.setstate(std::ios_base::failbit); break; } os.write ((char *)out, GZIP_CHUNK_SIZE - m_Inflator.avail_out); - } + } while (!m_Inflator.avail_out); // more data to read delete[] out; } @@ -105,7 +105,7 @@ namespace data m_Deflator.next_out = out; m_Deflator.avail_out = outLen; int err; - if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END) + if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END) return outLen - m_Deflator.avail_out; // else LogPrint (eLogError, "Gzip: Deflate error ", err); diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index c81b1a07..9ae88d4a 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -44,7 +44,7 @@ namespace http { } } - static std::pair parse_header_line(const std::string& line) + static std::pair parse_header_line(const std::string& line) { std::size_t pos = 0; std::size_t len = 2; /* strlen(": ") */ @@ -251,14 +251,14 @@ namespace http { uri = tokens[1]; version = tokens[2]; expect = HEADER_LINE; - } - else + } + else { std::string line = str.substr(pos, eol - pos); auto p = parse_header_line(line); if (p.first.length () > 0) headers.push_back (p); - else + else return -1; } pos = eol + strlen(CRLF); @@ -268,10 +268,10 @@ namespace http { return eoh + strlen(HTTP_EOH); } - void HTTPReq::write(std::ostream & o) + void HTTPReq::write(std::ostream & o) { o << method << " " << uri << " " << version << CRLF; - for (auto & h : headers) + for (auto & h : headers) o << h.first << ": " << h.second << CRLF; o << CRLF; } @@ -284,7 +284,7 @@ namespace http { } void HTTPReq::AddHeader (const std::string& name, const std::string& value) - { + { headers.push_back (std::make_pair(name, value)); } @@ -295,28 +295,28 @@ namespace http { { it.second = value; break; - } - } - + } + } + void HTTPReq::RemoveHeader (const std::string& name, const std::string& exempt) { for (auto it = headers.begin (); it != headers.end ();) { - if (!it->first.compare(0, name.length (), name) && it->first != exempt) + if (!it->first.compare(0, name.length (), name) && it->first != exempt) it = headers.erase (it); else it++; - } - } + } + } - std::string HTTPReq::GetHeader (const std::string& name) const + std::string HTTPReq::GetHeader (const std::string& name) const { for (auto& it : headers) if (it.first == name) - return it.second; + return it.second; return ""; - } - + } + bool HTTPRes::is_chunked() const { auto it = headers.find("Transfer-Encoding"); @@ -335,10 +335,10 @@ namespace http { if (it->second.find("gzip") != std::string::npos) return true; /* gotcha! */ if (includingI2PGzip && it->second.find("x-i2p-gzip") != std::string::npos) - return true; + return true; return false; } - + long int HTTPMsg::content_length() const { unsigned long int length = 0; @@ -385,8 +385,8 @@ namespace http { std::string line = str.substr(pos, eol - pos); auto p = parse_header_line(line); if (p.first.length () > 0) - headers.insert (p); - else + headers.insert (p); + else return -1; } pos = eol + strlen(CRLF); diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index 272f2f44..837faf01 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -16,16 +16,16 @@ #include #include -namespace i2p +namespace i2p { -namespace http +namespace http { const char CRLF[] = "\r\n"; /**< HTTP line terminator */ const char HTTP_EOH[] = "\r\n\r\n"; /**< HTTP end-of-headers mark */ extern const std::vector HTTP_METHODS; /**< list of valid HTTP methods */ extern const std::vector HTTP_VERSIONS; /**< list of valid HTTP versions */ - struct URL + struct URL { std::string schema; std::string user; @@ -63,7 +63,7 @@ namespace http bool is_i2p() const; }; - struct HTTPMsg + struct HTTPMsg { std::map headers; @@ -75,9 +75,9 @@ namespace http long int content_length() const; }; - struct HTTPReq + struct HTTPReq { - std::list > headers; + std::list > headers; std::string version; std::string method; std::string uri; @@ -97,10 +97,10 @@ namespace http void write(std::ostream & o); void AddHeader (const std::string& name, const std::string& value); - void UpdateHeader (const std::string& name, const std::string& value); + void UpdateHeader (const std::string& name, const std::string& value); void RemoveHeader (const std::string& name, const std::string& exempt); // remove all headers starting with name, but exempt void RemoveHeader (const std::string& name) { RemoveHeader (name, ""); }; - std::string GetHeader (const std::string& name) const; + std::string GetHeader (const std::string& name) const; }; struct HTTPRes : HTTPMsg { diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 5719a1b0..9bb7dfd1 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -21,7 +21,7 @@ namespace i2p { return std::make_shared >(); } - + std::shared_ptr NewI2NPShortMessage () { return std::make_shared >(); @@ -32,38 +32,38 @@ namespace i2p auto msg = new I2NPMessageBuffer(); // reserved for alignment and NTCP 16 + 6 + 12 msg->Align (12); return std::shared_ptr(msg); - } - + } + std::shared_ptr NewI2NPMessage (size_t len) { return (len < I2NP_MAX_SHORT_MESSAGE_SIZE/2) ? NewI2NPShortMessage () : NewI2NPMessage (); - } + } void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID) { SetTypeID (msgType); if (!replyMsgID) RAND_bytes ((uint8_t *)&replyMsgID, 4); - SetMsgID (replyMsgID); - SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); + SetMsgID (replyMsgID); + SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); UpdateSize (); UpdateChks (); - } - + } + void I2NPMessage::RenewI2NPMessageHeader () { uint32_t msgID; RAND_bytes ((uint8_t *)&msgID, 4); SetMsgID (msgID); - SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); + SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); } bool I2NPMessage::IsExpired () const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); - auto exp = GetExpiration (); + auto exp = GetExpiration (); return (ts > exp + I2NP_MESSAGE_CLOCK_SKEW) || (ts < exp - 3*I2NP_MESSAGE_CLOCK_SKEW); // check if expired or too far in future - } - + } + std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID) { auto msg = NewI2NPMessage (len); @@ -71,7 +71,7 @@ namespace i2p LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length ", msg->maxLen); msg->FillI2NPMessageHeader (msgType, replyMsgID); return msg; - } + } std::shared_ptr CreateI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) { @@ -85,7 +85,7 @@ namespace i2p else LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length"); return msg; - } + } std::shared_ptr CopyI2NPMessage (std::shared_ptr msg) { @@ -94,8 +94,8 @@ namespace i2p newMsg->offset = msg->offset; *newMsg = *msg; return newMsg; - } - + } + std::shared_ptr CreateDeliveryStatusMsg (uint32_t msgID) { auto m = NewI2NPShortMessage (); @@ -109,14 +109,14 @@ namespace i2p { RAND_bytes ((uint8_t *)&msgID, 4); htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID); - htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::context.GetNetID ()); - } + htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::context.GetNetID ()); + } m->len += DELIVERY_STATUS_SIZE; m->FillI2NPMessageHeader (eI2NPDeliveryStatus); return m; } - std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, + std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, uint32_t replyTunnelID, bool exploratory, std::set * excludedPeers) { auto m = excludedPeers ? NewI2NPMessage () : NewI2NPShortMessage (); @@ -125,7 +125,7 @@ namespace i2p buf += 32; memcpy (buf, from, 32); // from buf += 32; - uint8_t flag = exploratory ? DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP : DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP; + uint8_t flag = exploratory ? DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP : DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP; if (replyTunnelID) { *buf = flag | DATABASE_LOOKUP_DELIVERY_FLAG; // set delivery flag @@ -133,11 +133,11 @@ namespace i2p buf += 5; } else - { + { *buf = flag; // flag buf++; - } - + } + if (excludedPeers) { int cnt = excludedPeers->size (); @@ -147,21 +147,21 @@ namespace i2p { memcpy (buf, it, 32); buf += 32; - } + } } else - { + { // nothing to exclude htobuf16 (buf, 0); buf += 2; - } - - m->len += (buf - m->GetPayload ()); - m->FillI2NPMessageHeader (eI2NPDatabaseLookup); - return m; - } + } - std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, + m->len += (buf - m->GetPayload ()); + m->FillI2NPMessageHeader (eI2NPDatabaseLookup); + return m; + } + + std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, const std::set& excludedFloodfills, std::shared_ptr replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag) { @@ -176,7 +176,7 @@ namespace i2p buf ++; htobe32buf (buf, replyTunnel->GetNextTunnelID ()); // reply tunnel ID buf += 4; - + // excluded htobe16buf (buf, cnt); buf += 2; @@ -187,19 +187,19 @@ namespace i2p memcpy (buf, it, 32); buf += 32; } - } + } // encryption memcpy (buf, replyKey, 32); buf[32] = uint8_t( 1 ); // 1 tag memcpy (buf + 33, replyTag, 32); buf += 65; - m->len += (buf - m->GetPayload ()); + m->len += (buf - m->GetPayload ()); m->FillI2NPMessageHeader (eI2NPDatabaseLookup); - return m; - } + return m; + } - std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, + std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector routers) { auto m = NewI2NPShortMessage (); @@ -207,27 +207,27 @@ namespace i2p size_t len = 0; memcpy (buf, ident, 32); len += 32; - buf[len] = routers.size (); + buf[len] = routers.size (); len++; for (const auto& it: routers) { memcpy (buf + len, it, 32); len += 32; - } + } memcpy (buf + len, i2p::context.GetRouterInfo ().GetIdentHash (), 32); - len += 32; + len += 32; m->len += len; m->FillI2NPMessageHeader (eI2NPDatabaseSearchReply); - return m; - } - + return m; + } + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router, uint32_t replyToken) { if (!router) // we send own RouterInfo router = context.GetSharedRouterInfo (); auto m = NewI2NPShortMessage (); - uint8_t * payload = m->GetPayload (); + uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, router->GetIdentHash (), 32); payload[DATABASE_STORE_TYPE_OFFSET] = 0; // RouterInfo @@ -239,7 +239,7 @@ namespace i2p buf += 4; memcpy (buf, router->GetIdentHash (), 32); buf += 32; - } + } uint8_t * sizePtr = buf; buf += 2; @@ -247,22 +247,22 @@ namespace i2p i2p::data::GzipDeflator deflator; size_t size = deflator.Deflate (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len); if (size) - { + { htobe16buf (sizePtr, size); // size m->len += size; - } + } else m = nullptr; if (m) m->FillI2NPMessageHeader (eI2NPDatabaseStore); return m; - } + } std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet) { if (!leaseSet) return nullptr; auto m = NewI2NPShortMessage (); - uint8_t * payload = m->GetPayload (); + uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32); payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); @@ -278,7 +278,7 @@ namespace i2p { if (!leaseSet) return nullptr; auto m = NewI2NPShortMessage (); - uint8_t * payload = m->GetPayload (); + uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32); payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, replyToken); @@ -306,8 +306,8 @@ namespace i2p { if (!msg || msg->GetTypeID () != eI2NPDatabaseStore) return false; return !msg->GetPayload ()[DATABASE_STORE_TYPE_OFFSET]; // 0- RouterInfo - } - + } + static uint16_t g_MaxNumTransitTunnels = DEFAULT_MAX_NUM_TRANSIT_TUNNELS; // TODO: void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels) { @@ -321,37 +321,37 @@ namespace i2p bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText) { for (int i = 0; i < num; i++) - { + { uint8_t * record = records + i*TUNNEL_BUILD_RECORD_SIZE; if (!memcmp (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16)) - { + { LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours"); BN_CTX * ctx = BN_CTX_new (); i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKeys ().GetPrivateKey () , record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx); BN_CTX_free (ctx); - // replace record to reply - if (i2p::context.AcceptsTunnels () && + // replace record to reply + if (i2p::context.AcceptsTunnels () && i2p::tunnel::tunnels.GetTransitTunnels ().size () <= g_MaxNumTransitTunnels && !i2p::transport::transports.IsBandwidthExceeded () && !i2p::transport::transports.IsTransitBandwidthExceeded ()) - { + { auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( - bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), - clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), + clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), - clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, - clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, - clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80, + clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, + clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, + clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80, clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40); i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 0; } else record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 30; // always reject with bandwidth reason (30) - + //TODO: fill filler SHA256 (record + BUILD_RESPONSE_RECORD_PADDING_OFFSET, BUILD_RESPONSE_RECORD_PADDING_SIZE + 1, // + 1 byte of ret - record + BUILD_RESPONSE_RECORD_HASH_OFFSET); + record + BUILD_RESPONSE_RECORD_HASH_OFFSET); // encrypt reply i2p::crypto::CBCEncryption encryption; for (int j = 0; j < num; j++) @@ -359,23 +359,23 @@ namespace i2p encryption.SetKey (clearText + BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET); encryption.SetIV (clearText + BUILD_REQUEST_RECORD_REPLY_IV_OFFSET); uint8_t * reply = records + j*TUNNEL_BUILD_RECORD_SIZE; - encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply); + encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply); } return true; - } - } + } + } return false; } void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len) - { + { int num = buf[0]; LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records"); if (len < num*BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 1) { LogPrint (eLogError, "VaribleTunnelBuild message of ", num, " records is too short ", len); return; - } + } auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID); if (tunnel) @@ -385,34 +385,34 @@ namespace i2p if (tunnel->HandleTunnelBuildResponse (buf, len)) { LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been created"); - tunnel->SetState (i2p::tunnel::eTunnelStateEstablished); + tunnel->SetState (i2p::tunnel::eTunnelStateEstablished); i2p::tunnel::tunnels.AddInboundTunnel (tunnel); } else { LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been declined"); - tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed); + tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed); } } else { - uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; + uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; if (HandleBuildRequestRecords (num, buf + 1, clearText)) { if (clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) // we are endpoint of outboud tunnel { - // so we send it to reply tunnel - transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + // so we send it to reply tunnel + transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), - eI2NPVariableTunnelBuildReply, buf, len, - bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); - } - else - transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, - CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, + eI2NPVariableTunnelBuildReply, buf, len, + bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); + } + else + transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); - } - } + } + } } void HandleTunnelBuildMsg (uint8_t * buf, size_t len) @@ -421,51 +421,51 @@ namespace i2p { LogPrint (eLogError, "TunnelBuild message is too short ", len); return; - } - uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; + } + uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; if (HandleBuildRequestRecords (NUM_TUNNEL_BUILD_RECORDS, buf, clearText)) { if (clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) // we are endpoint of outbound tunnel { - // so we send it to reply tunnel - transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + // so we send it to reply tunnel + transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), - eI2NPTunnelBuildReply, buf, len, - bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); - } - else - transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, - CreateI2NPMessage (eI2NPTunnelBuild, buf, len, + eI2NPTunnelBuildReply, buf, len, + bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); + } + else + transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + CreateI2NPMessage (eI2NPTunnelBuild, buf, len, bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); - } + } } void HandleVariableTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len) - { + { int num = buf[0]; LogPrint (eLogDebug, "I2NP: VariableTunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID); if (len < num*BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 1) { LogPrint (eLogError, "VaribleTunnelBuildReply message of ", num, " records is too short ", len); return; - } - + } + auto tunnel = i2p::tunnel::tunnels.GetPendingOutboundTunnel (replyMsgID); if (tunnel) - { + { // reply for outbound tunnel if (tunnel->HandleTunnelBuildResponse (buf, len)) - { + { LogPrint (eLogInfo, "I2NP: Outbound tunnel ", tunnel->GetTunnelID (), " has been created"); - tunnel->SetState (i2p::tunnel::eTunnelStateEstablished); + tunnel->SetState (i2p::tunnel::eTunnelStateEstablished); i2p::tunnel::tunnels.AddOutboundTunnel (tunnel); - } + } else { LogPrint (eLogInfo, "I2NP: Outbound tunnel ", tunnel->GetTunnelID (), " has been declined"); - tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed); + tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed); } - } + } else LogPrint (eLogWarning, "I2NP: Pending tunnel for message ", replyMsgID, " not found"); } @@ -474,12 +474,12 @@ namespace i2p std::shared_ptr CreateTunnelDataMsg (const uint8_t * buf) { auto msg = NewI2NPTunnelMessage (); - msg->Concat (buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE); + msg->Concat (buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE); msg->FillI2NPMessageHeader (eI2NPTunnelData); return msg; - } + } - std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload) + std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload) { auto msg = NewI2NPTunnelMessage (); htobe32buf (msg->GetPayload (), tunnelID); @@ -487,15 +487,15 @@ namespace i2p msg->Concat (payload, i2p::tunnel::TUNNEL_DATA_MSG_SIZE - 4); msg->FillI2NPMessageHeader (eI2NPTunnelData); return msg; - } + } std::shared_ptr CreateEmptyTunnelDataMsg () { auto msg = NewI2NPTunnelMessage (); - msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE; + msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE; return msg; - } - + } + std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, const uint8_t * buf, size_t len) { auto msg = NewI2NPMessage (len); @@ -504,10 +504,10 @@ namespace i2p htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len); msg->len += TUNNEL_GATEWAY_HEADER_SIZE; if (msg->Concat (buf, len) < len) - LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen); + LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen); msg->FillI2NPMessageHeader (eI2NPTunnelGateway); return msg; - } + } std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr msg) { @@ -520,14 +520,14 @@ namespace i2p htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len); msg->offset -= (I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE); msg->len = msg->offset + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE +len; - msg->FillI2NPMessageHeader (eI2NPTunnelGateway); + msg->FillI2NPMessageHeader (eI2NPTunnelGateway); return msg; } else - return CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ()); + return CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ()); } - std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, + std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID) { auto msg = NewI2NPMessage (len); @@ -544,7 +544,7 @@ namespace i2p htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len); msg->FillI2NPMessageHeader (eI2NPTunnelGateway); // gateway message return msg; - } + } size_t GetI2NPMessageLength (const uint8_t * msg, size_t len) { @@ -552,25 +552,25 @@ namespace i2p { LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header"); return len; - } + } auto l = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE; if (l > len) { LogPrint (eLogError, "I2NP: message length ", l, " exceeds buffer length ", len); l = len; - } + } return l; - } - + } + void HandleI2NPMessage (uint8_t * msg, size_t len) { if (len < I2NP_HEADER_SIZE) { LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header"); return; - } + } uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET]; - uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_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; auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET); @@ -581,35 +581,35 @@ namespace i2p size = len; } switch (typeID) - { + { case eI2NPVariableTunnelBuild: HandleVariableTunnelBuildMsg (msgID, buf, size); - break; + break; case eI2NPVariableTunnelBuildReply: HandleVariableTunnelBuildReplyMsg (msgID, buf, size); - break; + break; case eI2NPTunnelBuild: HandleTunnelBuildMsg (buf, size); - break; + break; case eI2NPTunnelBuildReply: // TODO: - break; + break; default: LogPrint (eLogWarning, "I2NP: Unexpected message ", (int)typeID); - } + } } void HandleI2NPMessage (std::shared_ptr msg) { if (msg) - { + { uint8_t typeID = msg->GetTypeID (); LogPrint (eLogDebug, "I2NP: Handling message with type ", (int)typeID); switch (typeID) - { + { case eI2NPTunnelData: i2p::tunnel::tunnels.PostTunnelData (msg); - break; + break; case eI2NPTunnelGateway: i2p::tunnel::tunnels.PostTunnelData (msg); break; @@ -623,7 +623,7 @@ namespace i2p LogPrint (eLogInfo, "I2NP: Local destination for garlic doesn't exist anymore"); } else - i2p::context.ProcessGarlicMessage (msg); + i2p::context.ProcessGarlicMessage (msg); break; } case eI2NPDatabaseStore: @@ -638,55 +638,55 @@ namespace i2p msg->from->GetTunnelPool ()->ProcessDeliveryStatus (msg); else i2p::context.ProcessDeliveryStatusMessage (msg); - break; + break; } - case eI2NPVariableTunnelBuild: + case eI2NPVariableTunnelBuild: case eI2NPVariableTunnelBuildReply: case eI2NPTunnelBuild: - case eI2NPTunnelBuildReply: + case eI2NPTunnelBuildReply: // forward to tunnel thread i2p::tunnel::tunnels.PostTunnelData (msg); - break; + break; default: HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ()); - } - } - } + } + } + } I2NPMessagesHandler::~I2NPMessagesHandler () { Flush (); } - + void I2NPMessagesHandler::PutNextMessage (std::shared_ptr msg) { if (msg) { switch (msg->GetTypeID ()) - { + { case eI2NPTunnelData: m_TunnelMsgs.push_back (msg); break; - case eI2NPTunnelGateway: + case eI2NPTunnelGateway: m_TunnelGatewayMsgs.push_back (msg); - break; + break; default: HandleI2NPMessage (msg); - } - } + } + } } - + void I2NPMessagesHandler::Flush () { if (!m_TunnelMsgs.empty ()) - { + { i2p::tunnel::tunnels.PostTunnelData (m_TunnelMsgs); m_TunnelMsgs.clear (); - } + } if (!m_TunnelGatewayMsgs.empty ()) - { + { i2p::tunnel::tunnels.PostTunnelData (m_TunnelGatewayMsgs); m_TunnelGatewayMsgs.clear (); - } - } + } + } } diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 3f36b0a8..f394d284 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -12,7 +12,7 @@ #include "LeaseSet.h" namespace i2p -{ +{ // I2NP header const size_t I2NP_HEADER_TYPEID_OFFSET = 0; const size_t I2NP_HEADER_MSGID_OFFSET = I2NP_HEADER_TYPEID_OFFSET + 1; @@ -25,13 +25,13 @@ namespace i2p const size_t I2NP_SHORT_HEADER_TYPEID_OFFSET = 0; const size_t I2NP_SHORT_HEADER_EXPIRATION_OFFSET = I2NP_SHORT_HEADER_TYPEID_OFFSET + 1; const size_t I2NP_SHORT_HEADER_SIZE = I2NP_SHORT_HEADER_EXPIRATION_OFFSET + 4; - + // Tunnel Gateway header const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0; const size_t TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET = TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET + 4; const size_t TUNNEL_GATEWAY_HEADER_SIZE = TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET + 2; - // DeliveryStatus + // DeliveryStatus const size_t DELIVERY_STATUS_MSGID_OFFSET = 0; const size_t DELIVERY_STATUS_TIMESTAMP_OFFSET = DELIVERY_STATUS_MSGID_OFFSET + 4; const size_t DELIVERY_STATUS_SIZE = DELIVERY_STATUS_TIMESTAMP_OFFSET + 8; @@ -42,7 +42,7 @@ namespace i2p const size_t DATABASE_STORE_REPLY_TOKEN_OFFSET = DATABASE_STORE_TYPE_OFFSET + 1; const size_t DATABASE_STORE_HEADER_SIZE = DATABASE_STORE_REPLY_TOKEN_OFFSET + 4; - // TunnelBuild + // TunnelBuild const size_t TUNNEL_BUILD_RECORD_SIZE = 528; //BuildRequestRecordClearText @@ -59,11 +59,11 @@ namespace i2p const size_t BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET = BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET + 4; const size_t BUILD_REQUEST_RECORD_PADDING_OFFSET = BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET + 4; const size_t BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE = 222; - - // BuildRequestRecordEncrypted + + // BuildRequestRecordEncrypted const size_t BUILD_REQUEST_RECORD_TO_PEER_OFFSET = 0; const size_t BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET = BUILD_REQUEST_RECORD_TO_PEER_OFFSET + 16; - + // BuildResponseRecord const size_t BUILD_RESPONSE_RECORD_HASH_OFFSET = 0; const size_t BUILD_RESPONSE_RECORD_PADDING_OFFSET = 32; @@ -83,40 +83,40 @@ namespace i2p eI2NPTunnelBuild = 21, eI2NPTunnelBuildReply = 22, eI2NPVariableTunnelBuild = 23, - eI2NPVariableTunnelBuildReply = 24 - }; + eI2NPVariableTunnelBuildReply = 24 + }; - const int NUM_TUNNEL_BUILD_RECORDS = 8; + const int NUM_TUNNEL_BUILD_RECORDS = 8; // DatabaseLookup flags const uint8_t DATABASE_LOOKUP_DELIVERY_FLAG = 0x01; - const uint8_t DATABASE_LOOKUP_ENCRYPTION_FLAG = 0x02; + const uint8_t DATABASE_LOOKUP_ENCRYPTION_FLAG = 0x02; const uint8_t DATABASE_LOOKUP_TYPE_FLAGS_MASK = 0x0C; const uint8_t DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP = 0; const uint8_t DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP = 0x04; // 0100 - const uint8_t DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP = 0x08; // 1000 + const uint8_t DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP = 0x08; // 1000 const uint8_t DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP = 0x0C; // 1100 namespace tunnel -{ +{ class InboundTunnel; class TunnelPool; } - const size_t I2NP_MAX_MESSAGE_SIZE = 32768; - const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096; + const size_t I2NP_MAX_MESSAGE_SIZE = 32768; + const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096; const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT) - const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds + const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds struct I2NPMessage - { - uint8_t * buf; + { + uint8_t * buf; size_t len, offset, maxLen; std::shared_ptr from; - - I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2), + + I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2), offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header - + // header accessors uint8_t * GetHeader () { return GetBuffer (); }; const uint8_t * GetHeader () const { return GetBuffer (); }; @@ -128,24 +128,24 @@ namespace tunnel uint64_t GetExpiration () const { return bufbe64toh (GetHeader () + I2NP_HEADER_EXPIRATION_OFFSET); }; void SetSize (uint16_t size) { htobe16buf (GetHeader () + I2NP_HEADER_SIZE_OFFSET, size); }; uint16_t GetSize () const { return bufbe16toh (GetHeader () + I2NP_HEADER_SIZE_OFFSET); }; - void UpdateSize () { SetSize (GetPayloadLength ()); }; + void UpdateSize () { SetSize (GetPayloadLength ()); }; void SetChks (uint8_t chks) { GetHeader ()[I2NP_HEADER_CHKS_OFFSET] = chks; }; - void UpdateChks () + void UpdateChks () { uint8_t hash[32]; SHA256(GetPayload (), GetPayloadLength (), hash); GetHeader ()[I2NP_HEADER_CHKS_OFFSET] = hash[0]; - } - + } + // payload uint8_t * GetPayload () { return GetBuffer () + I2NP_HEADER_SIZE; }; const uint8_t * GetPayload () const { return GetBuffer () + I2NP_HEADER_SIZE; }; uint8_t * GetBuffer () { return buf + offset; }; const uint8_t * GetBuffer () const { return buf + offset; }; - size_t GetLength () const { return len - offset; }; - size_t GetPayloadLength () const { return GetLength () - I2NP_HEADER_SIZE; }; - - void Align (size_t alignment) + size_t GetLength () const { return len - offset; }; + size_t GetPayloadLength () const { return GetLength () - I2NP_HEADER_SIZE; }; + + void Align (size_t alignment) { if (len + alignment > maxLen) return; size_t rem = ((size_t)GetBuffer ()) % alignment; @@ -153,7 +153,7 @@ namespace tunnel { offset += (alignment - rem); len += (alignment - rem); - } + } } size_t Concat (const uint8_t * buf1, size_t len1) @@ -171,10 +171,10 @@ namespace tunnel len = offset + other.GetLength (); from = other.from; return *this; - } - + } + // for SSU only - uint8_t * GetSSUHeader () { return buf + offset + I2NP_HEADER_SIZE - I2NP_SHORT_HEADER_SIZE; }; + uint8_t * GetSSUHeader () { return buf + offset + I2NP_HEADER_SIZE - I2NP_SHORT_HEADER_SIZE; }; void FromSSU (uint32_t msgID) // we have received SSU message and convert it to regular { const uint8_t * ssu = GetSSUHeader (); @@ -193,12 +193,12 @@ namespace tunnel htobe32buf (ssu + I2NP_SHORT_HEADER_EXPIRATION_OFFSET, bufbe64toh (header + I2NP_HEADER_EXPIRATION_OFFSET)/1000LL); len = offset + I2NP_SHORT_HEADER_SIZE + bufbe16toh (header + I2NP_HEADER_SIZE_OFFSET); return bufbe32toh (header + I2NP_HEADER_MSGID_OFFSET); - } + } void FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID = 0); void RenewI2NPMessageHeader (); bool IsExpired () const; - }; + }; template struct I2NPMessageBuffer: public I2NPMessage @@ -211,35 +211,35 @@ namespace tunnel std::shared_ptr NewI2NPShortMessage (); std::shared_ptr NewI2NPTunnelMessage (); std::shared_ptr NewI2NPMessage (size_t len); - - std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0); + + std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0); std::shared_ptr CreateI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from = nullptr); std::shared_ptr CopyI2NPMessage (std::shared_ptr msg); std::shared_ptr CreateDeliveryStatusMsg (uint32_t msgID); - std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, + std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, uint32_t replyTunnelID, bool exploratory = false, std::set * excludedPeers = nullptr); - std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, + std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, const std::set& excludedFloodfills, std::shared_ptr replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag); std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector routers); - + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router = nullptr, uint32_t replyToken = 0); std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet); // for floodfill only - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr); - bool IsRouterInfoMsg (std::shared_ptr msg); + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr); + bool IsRouterInfoMsg (std::shared_ptr msg); bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText); void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len); void HandleVariableTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len); - void HandleTunnelBuildMsg (uint8_t * buf, size_t len); + void HandleTunnelBuildMsg (uint8_t * buf, size_t len); - std::shared_ptr CreateTunnelDataMsg (const uint8_t * buf); - std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload); + std::shared_ptr CreateTunnelDataMsg (const uint8_t * buf); + std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload); std::shared_ptr CreateEmptyTunnelDataMsg (); - + std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, const uint8_t * buf, size_t len); - std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, + std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0); std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr msg); @@ -254,7 +254,7 @@ namespace tunnel ~I2NPMessagesHandler (); void PutNextMessage (std::shared_ptr msg); void Flush (); - + private: std::vector > m_TunnelMsgs, m_TunnelGatewayMsgs; @@ -262,6 +262,6 @@ namespace tunnel const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 2500; void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); -} +} #endif diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 23f32bc8..d7679fd5 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -41,7 +41,7 @@ namespace data IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType): m_IsVerifierCreated (false) - { + { memcpy (m_StandardIdentity.publicKey, publicKey, 256); // publicKey in awlays assumed 256 regardless actual size, padding must be taken care of if (type != SIGNING_KEY_TYPE_DSA_SHA1) { @@ -450,7 +450,7 @@ namespace data std::shared_ptr IdentityEx::CreateEncryptor (const uint8_t * key) const { - if (!key) key = GetEncryptionPublicKey (); // use publicKey + if (!key) key = GetEncryptionPublicKey (); // use publicKey switch (GetCryptoKeyType ()) { case CRYPTO_KEY_TYPE_ELGAMAL: @@ -596,12 +596,12 @@ namespace data std::shared_ptr PrivateKeys::CreateDecryptor (const uint8_t * key) const { - if (!key) key = m_PrivateKey; // use privateKey + if (!key) key = m_PrivateKey; // use privateKey return CreateDecryptor (m_Public->GetCryptoKeyType (), key); } std::shared_ptr PrivateKeys::CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key) - { + { if (!key) return nullptr; switch (cryptoType) { @@ -618,7 +618,7 @@ namespace data default: LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)cryptoType); }; - return nullptr; + return nullptr; } PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type, CryptoKeyType cryptoType) @@ -643,7 +643,7 @@ namespace data case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA512_4096: LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Create EdDSA"); - // no break here + // no break here case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); break; @@ -685,7 +685,7 @@ namespace data break; default: LogPrint (eLogError, "Identity: Crypto key type ", (int)type, " is not supported"); - } + } } Keys CreateRandomKeys () diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 53ab4a7c..21ad1e9b 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -96,7 +96,7 @@ namespace data const IdentHash& GetIdentHash () const { return m_IdentHash; }; const uint8_t * GetEncryptionPublicKey () const { return m_StandardIdentity.publicKey; }; uint8_t * GetEncryptionPublicKeyBuffer () { return m_StandardIdentity.publicKey; }; - std::shared_ptr CreateEncryptor (const uint8_t * key) const; + std::shared_ptr CreateEncryptor (const uint8_t * key) const; size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; }; size_t GetSigningPublicKeyLen () const; size_t GetSigningPrivateKeyLen () const; diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d2709a97..f715304e 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -11,7 +11,7 @@ namespace i2p { namespace data { - + LeaseSet::LeaseSet (const uint8_t * buf, size_t len, bool storeLeases): m_IsValid (true), m_StoreLeases (storeLeases), m_ExpirationTime (0) { @@ -22,13 +22,13 @@ namespace data } void LeaseSet::Update (const uint8_t * buf, size_t len) - { + { if (len > m_BufferLen) { auto oldBuffer = m_Buffer; m_Buffer = new uint8_t[len]; delete[] oldBuffer; - } + } memcpy (m_Buffer, buf, len); m_BufferLen = len; ReadFromBuffer (false); @@ -38,10 +38,10 @@ namespace data { m_StoreLeases = true; ReadFromBuffer (false); - } - - void LeaseSet::ReadFromBuffer (bool readIdentity) - { + } + + void LeaseSet::ReadFromBuffer (bool readIdentity) + { if (readIdentity || !m_Identity) m_Identity = std::make_shared(m_Buffer, m_BufferLen); size_t size = m_Identity->GetFullLen (); @@ -58,17 +58,17 @@ namespace data size++; // num LogPrint (eLogDebug, "LeaseSet: read num=", (int)num); if (!num || num > MAX_NUM_LEASES) - { + { LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)num); m_IsValid = false; return; - } + } // reset existing leases if (m_StoreLeases) for (auto& it: m_Leases) it->isUpdated = false; - else + else m_Leases.clear (); // process leases @@ -82,14 +82,14 @@ namespace data leases += 32; // gateway lease.tunnelID = bufbe32toh (leases); leases += 4; // tunnel ID - lease.endDate = bufbe64toh (leases); + lease.endDate = bufbe64toh (leases); leases += 8; // end date if (ts < lease.endDate + LEASE_ENDDATE_THRESHOLD) - { + { if (lease.endDate > m_ExpirationTime) m_ExpirationTime = lease.endDate; if (m_StoreLeases) - { + { auto ret = m_Leases.insert (std::make_shared(lease)); if (!ret.second) (*ret.first)->endDate = lease.endDate; // update existing (*ret.first)->isUpdated = true; @@ -100,28 +100,28 @@ namespace data LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting"); netdb.RequestDestination (lease.tunnelGateway); } - } + } } else LogPrint (eLogWarning, "LeaseSet: Lease is expired already "); - } + } if (!m_ExpirationTime) { LogPrint (eLogWarning, "LeaseSet: all leases are expired. Dropped"); m_IsValid = false; return; - } + } m_ExpirationTime += LEASE_ENDDATE_THRESHOLD; - // delete old leases + // delete old leases if (m_StoreLeases) - { + { for (auto it = m_Leases.begin (); it != m_Leases.end ();) - { + { if (!(*it)->isUpdated) { (*it)->endDate = 0; // somebody might still hold it m_Leases.erase (it++); - } + } else ++it; } @@ -133,9 +133,9 @@ namespace data LogPrint (eLogWarning, "LeaseSet: verification failed"); m_IsValid = false; } - } + } - uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const + uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const { if (!m_Identity) return 0; size_t size = m_Identity->GetFullLen (); @@ -150,18 +150,18 @@ namespace data for (int i = 0; i < num; i++) { size += 36; // gateway (32) + tunnelId(4) - auto endDate = bufbe64toh (buf + size); + auto endDate = bufbe64toh (buf + size); size += 8; // end date if (!timestamp || endDate < timestamp) timestamp = endDate; - } + } return timestamp; - } + } bool LeaseSet::IsNewer (const uint8_t * buf, size_t len) const { return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen); - } + } bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const { @@ -175,7 +175,7 @@ namespace data { return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold); } - + const std::vector > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); @@ -189,9 +189,9 @@ namespace data endDate -= LEASE_ENDDATE_THRESHOLD; if (ts < endDate && !exclude(*it)) leases.push_back (it); - } - return leases; - } + } + return leases; + } bool LeaseSet::HasExpiredLeases () const { @@ -199,7 +199,7 @@ namespace data for (const auto& it: m_Leases) if (ts >= it->endDate) return true; return false; - } + } bool LeaseSet::IsExpired () const { @@ -222,15 +222,15 @@ namespace data if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES; // identity auto signingKeyLen = m_Identity->GetSigningPublicKeyLen (); - m_BufferLen = m_Identity->GetFullLen () + 256 + signingKeyLen + 1 + num*LEASE_SIZE + m_Identity->GetSignatureLen (); - m_Buffer = new uint8_t[m_BufferLen]; + m_BufferLen = m_Identity->GetFullLen () + 256 + signingKeyLen + 1 + num*LEASE_SIZE + m_Identity->GetSignatureLen (); + m_Buffer = new uint8_t[m_BufferLen]; auto offset = m_Identity->ToBuffer (m_Buffer, m_BufferLen); memcpy (m_Buffer + offset, encryptionPublicKey, 256); offset += 256; memset (m_Buffer + offset, 0, signingKeyLen); offset += signingKeyLen; // num leases - m_Buffer[offset] = num; + m_Buffer[offset] = num; offset++; // leases m_Leases = m_Buffer + offset; @@ -257,13 +257,13 @@ namespace data { m_BufferLen = len; m_Buffer = new uint8_t[m_BufferLen]; - memcpy (m_Buffer, buf, len); + memcpy (m_Buffer, buf, len); } bool LocalLeaseSet::IsExpired () const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); return ts > m_ExpirationTime; - } -} -} + } +} +} diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 5a4202ee..172a5078 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -14,11 +14,11 @@ namespace i2p namespace tunnel { - class InboundTunnel; + class InboundTunnel; } namespace data -{ +{ const int LEASE_ENDDATE_THRESHOLD = 51000; // in milliseconds struct Lease { @@ -33,24 +33,24 @@ namespace data if (endDate < expire) return true; return (endDate - expire) < t; } - }; + }; struct LeaseCmp { bool operator() (std::shared_ptr l1, std::shared_ptr l2) const - { + { if (l1->tunnelID != l2->tunnelID) - return l1->tunnelID < l2->tunnelID; + return l1->tunnelID < l2->tunnelID; else - return l1->tunnelGateway < l2->tunnelGateway; + return l1->tunnelGateway < l2->tunnelGateway; }; - }; + }; typedef std::function LeaseInspectFunc; - + const size_t MAX_LS_BUFFER_SIZE = 3072; const size_t LEASE_SIZE = 44; // 32 + 4 + 8 - const uint8_t MAX_NUM_LEASES = 16; + const uint8_t MAX_NUM_LEASES = 16; class LeaseSet: public RoutingDestination { public: @@ -59,10 +59,10 @@ namespace data ~LeaseSet () { delete[] m_Buffer; }; void Update (const uint8_t * buf, size_t len); bool IsNewer (const uint8_t * buf, size_t len) const; - void PopulateLeases (); // from buffer + void PopulateLeases (); // from buffer const uint8_t * GetBuffer () const { return m_Buffer; }; - size_t GetBufferLen () const { return m_BufferLen; }; + size_t GetBufferLen () const { return m_BufferLen; }; bool IsValid () const { return m_IsValid; }; const std::vector > GetNonExpiredLeases (bool withThreshold = true) const; const std::vector > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const; @@ -71,8 +71,8 @@ namespace data bool IsEmpty () const { return m_Leases.empty (); }; uint64_t GetExpirationTime () const { return m_ExpirationTime; }; bool ExpiresSoon(const uint64_t dlt=1000 * 5, const uint64_t fudge = 0) const ; - bool operator== (const LeaseSet& other) const - { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; + bool operator== (const LeaseSet& other) const + { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; // implements RoutingDestination std::shared_ptr GetIdentity () const { return m_Identity; }; @@ -83,7 +83,7 @@ namespace data void ReadFromBuffer (bool readIdentity = true); uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // min expiration time - + private: bool m_IsValid, m_StoreLeases; // we don't need to store leases for floodfill @@ -93,7 +93,7 @@ namespace data uint8_t m_EncryptionKey[256]; uint8_t * m_Buffer; size_t m_BufferLen; - }; + }; class LocalLeaseSet { @@ -104,27 +104,27 @@ namespace data ~LocalLeaseSet () { delete[] m_Buffer; }; const uint8_t * GetBuffer () const { return m_Buffer; }; - uint8_t * GetSignature () { return m_Buffer + m_BufferLen - GetSignatureLen (); }; - size_t GetBufferLen () const { return m_BufferLen; }; + uint8_t * GetSignature () { return m_Buffer + m_BufferLen - GetSignatureLen (); }; + size_t GetBufferLen () const { return m_BufferLen; }; size_t GetSignatureLen () const { return m_Identity->GetSignatureLen (); }; - uint8_t * GetLeases () { return m_Leases; }; - + uint8_t * GetLeases () { return m_Leases; }; + const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); }; bool IsExpired () const; uint64_t GetExpirationTime () const { return m_ExpirationTime; }; void SetExpirationTime (uint64_t expirationTime) { m_ExpirationTime = expirationTime; }; - bool operator== (const LeaseSet& other) const - { return m_BufferLen == other.GetBufferLen () && !memcmp (other.GetBuffer (), other.GetBuffer (), m_BufferLen); }; + bool operator== (const LeaseSet& other) const + { return m_BufferLen == other.GetBufferLen () && !memcmp (other.GetBuffer (), other.GetBuffer (), m_BufferLen); }; private: - + uint64_t m_ExpirationTime; // in milliseconds std::shared_ptr m_Identity; uint8_t * m_Buffer, * m_Leases; size_t m_BufferLen; - }; -} -} + }; +} +} #endif diff --git a/libi2pd/Log.h b/libi2pd/Log.h index 74b4dc01..b11c6763 100644 --- a/libi2pd/Log.h +++ b/libi2pd/Log.h @@ -44,7 +44,7 @@ enum LogType { namespace i2p { namespace log { - + struct LogMsg; /* forward declaration */ class Log @@ -146,7 +146,7 @@ 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) {}; }; @@ -185,7 +185,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept std::stringstream ss(""); LogPrint (ss, std::forward(args)...); - + auto msg = std::make_shared(level, std::time(nullptr), ss.str()); msg->tid = std::this_thread::get_id(); log.Append(msg); diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 47baaac7..3fc7701e 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -22,18 +22,18 @@ using namespace i2p::transport; namespace i2p { namespace data -{ +{ NetDb netdb; NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_FloodfillBootstrap(nullptr), m_HiddenMode(false) { } - + NetDb::~NetDb () { - Stop (); + Stop (); delete m_Reseeder; - } + } void NetDb::Start () { @@ -50,46 +50,46 @@ namespace data m_IsRunning = true; m_Thread = new std::thread (std::bind (&NetDb::Run, this)); } - + void NetDb::Stop () { if (m_IsRunning) - { + { for (auto& it: m_RouterInfos) it.second->SaveProfile (); DeleteObsoleteProfiles (); m_RouterInfos.clear (); m_Floodfills.clear (); if (m_Thread) - { + { m_IsRunning = false; m_Queue.WakeUp (); - m_Thread->join (); + m_Thread->join (); delete m_Thread; m_Thread = 0; } m_LeaseSets.clear(); m_Requests.Stop (); } - } - + } + void NetDb::Run () { uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; while (m_IsRunning) - { + { try - { + { auto msg = m_Queue.GetNextWithTimeout (15000); // 15 sec if (msg) - { - int numMsgs = 0; + { + int numMsgs = 0; while (msg) { LogPrint(eLogDebug, "NetDb: got request with type ", (int) msg->GetTypeID ()); - switch (msg->GetTypeID ()) + switch (msg->GetTypeID ()) { - case eI2NPDatabaseStore: + case eI2NPDatabaseStore: HandleDatabaseStoreMsg (msg); break; case eI2NPDatabaseSearchReply: @@ -97,16 +97,16 @@ namespace data break; case eI2NPDatabaseLookup: HandleDatabaseLookupMsg (msg); - break; + break; default: // WTF? LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ()); //i2p::HandleI2NPMessage (msg); - } + } if (numMsgs > 100) break; msg = m_Queue.Get (); numMsgs++; - } - } + } + } if (!m_IsRunning) break; uint64_t ts = i2p::util::GetSecondsSinceEpoch (); @@ -114,29 +114,29 @@ namespace data { m_Requests.ManageRequests (); lastManageRequest = ts; - } + } if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute { if (lastSave) { SaveUpdated (); ManageLeaseSets (); - } + } lastSave = ts; } - if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT) + if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT) { i2p::context.CleanupDestination (); lastDestinationCleanup = ts; } - - if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish + + if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish { Publish (); lastPublish = ts; - } + } if (ts - lastExploratory >= 30) // exploratory every 30 seconds - { + { auto numRouters = m_RouterInfos.size (); if (numRouters == 0) { @@ -145,29 +145,29 @@ namespace data else // we have peers now m_FloodfillBootstrap = nullptr; if (numRouters < 2500 || ts - lastExploratory >= 90) - { + { numRouters = 800/numRouters; if (numRouters < 1) numRouters = 1; - if (numRouters > 9) numRouters = 9; + if (numRouters > 9) numRouters = 9; m_Requests.ManageRequests (); if(!m_HiddenMode) Explore (numRouters); lastExploratory = ts; - } - } + } + } } catch (std::exception& ex) { LogPrint (eLogError, "NetDb: runtime exception: ", ex.what ()); - } - } - } - + } + } + } + bool NetDb::AddRouterInfo (const uint8_t * buf, int len) { IdentityEx identity; if (identity.FromBuffer (buf, len)) - return AddRouterInfo (identity.GetIdentHash (), buf, len); + return AddRouterInfo (identity.GetIdentHash (), buf, len); return false; } @@ -175,10 +175,10 @@ namespace data // TODO: remove reachable addresses from router info m_HiddenMode = hide; } - + bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) - { - bool updated = true; + { + bool updated = true; auto r = FindRouter (ident); if (r) { @@ -193,9 +193,9 @@ namespace data LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64()); updated = false; } - } - else - { + } + else + { r = std::make_shared (buf, len); if (!r->IsUnreachable ()) { @@ -218,14 +218,14 @@ namespace data LogPrint (eLogWarning, "NetDb: Duplicated RouterInfo ", ident.ToBase64()); updated = false; } - } + } else updated = false; - } + } // take care about requested destination m_Requests.RequestComplete (ident, r); return updated; - } + } bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from) @@ -233,30 +233,30 @@ namespace data std::unique_lock lock(m_LeaseSetsMutex); bool updated = false; if (!from) // unsolicited LS must be received directly - { + { auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { if (it->second->IsNewer (buf, len)) { - it->second->Update (buf, len); + it->second->Update (buf, len); if (it->second->IsValid ()) { LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); - updated = true; + updated = true; } else { LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); m_LeaseSets.erase (it); - } + } } else LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); } else - { - auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb + { + auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb if (leaseSet->IsValid ()) { LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32()); @@ -265,10 +265,10 @@ namespace data } else LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase32()); - } - } + } + } return updated; - } + } std::shared_ptr NetDb::FindRouter (const IdentHash& ident) const { @@ -294,8 +294,8 @@ namespace data { auto router = FindRouter (ident); return router ? router->GetProfile () : nullptr; - } - + } + void NetDb::SetUnreachable (const IdentHash& ident, bool unreachable) { auto it = m_RouterInfos.find (ident); @@ -306,7 +306,7 @@ namespace data void NetDb::Reseed () { if (!m_Reseeder) - { + { m_Reseeder = new Reseeder (); m_Reseeder->LoadCertificates (); // we need certificates for SU3 verification } @@ -341,7 +341,7 @@ namespace data i2p::data::IdentHash ourIdent = i2p::context.GetIdentHash(); i2p::data::IdentHash ih = ri.GetIdentHash(); i2p::data::IdentHash randomIdent; - + // make floodfill lookups while(numFloodfills > 0) { randomIdent.Randomize(); @@ -349,7 +349,7 @@ namespace data requests.push_back(msg); numFloodfills --; } - + // make regular router lookups while(numRouters > 0) { randomIdent.Randomize(); @@ -357,7 +357,7 @@ namespace data requests.push_back(msg); numRouters --; } - + // send them off i2p::transport::transports.SendMessages(ih, requests); } @@ -373,8 +373,8 @@ namespace data m_RouterInfos[r->GetIdentHash ()] = r; if (r->IsFloodfill () && r->IsReachable ()) // floodfill must be reachable m_Floodfills.push_back (r); - } - else + } + else { LogPrint(eLogWarning, "NetDb: RI from ", path, " is invalid. Delete"); i2p::fs::Remove(path); @@ -449,12 +449,12 @@ namespace data } return visited; } - + void NetDb::Load () { // make sure we cleanup netDb from previous attempts - m_RouterInfos.clear (); - m_Floodfills.clear (); + m_RouterInfos.clear (); + m_Floodfills.clear (); m_LastLoad = i2p::util::GetSecondsSinceEpoch(); std::vector files; @@ -463,25 +463,25 @@ namespace data LoadRouterInfo(path); LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.size (), " floodfils)"); - } + } void NetDb::SaveUpdated () - { + { int updatedCount = 0, deletedCount = 0; auto total = m_RouterInfos.size (); - uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; + uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); - // routers don't expire if less than 90 or uptime is less than 1 hour - bool checkForExpiration = total > NETDB_MIN_ROUTERS && ts > (i2p::context.GetStartupTime () + 600)*1000LL; // 10 minutes - if (checkForExpiration && ts > (i2p::context.GetStartupTime () + 3600)*1000LL) // 1 hour + // routers don't expire if less than 90 or uptime is less than 1 hour + bool checkForExpiration = total > NETDB_MIN_ROUTERS && ts > (i2p::context.GetStartupTime () + 600)*1000LL; // 10 minutes + if (checkForExpiration && ts > (i2p::context.GetStartupTime () + 3600)*1000LL) // 1 hour expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL : - NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; + NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; for (auto& it: m_RouterInfos) - { + { std::string ident = it.second->GetIdentHashBase64(); std::string path = m_Storage.Path(ident); - if (it.second->IsUpdated ()) + if (it.second->IsUpdated ()) { it.second->SaveToFile (path); it.second->SetUpdated (false); @@ -493,14 +493,14 @@ namespace data // find & mark expired routers if (it.second->UsesIntroducer ()) { - if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) + if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) // RouterInfo expires after 1 hour if uses introducer it.second->SetUnreachable (true); } - else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) + else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) it.second->SetUnreachable (true); - if (it.second->IsUnreachable ()) + if (it.second->IsUnreachable ()) { // delete RI file m_Storage.Remove(ident); @@ -508,7 +508,7 @@ namespace data if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false; } } // m_RouterInfos iteration - + if (updatedCount > 0) LogPrint (eLogInfo, "NetDb: saved ", updatedCount, " new/updated routers"); if (deletedCount > 0) @@ -519,15 +519,15 @@ namespace data std::unique_lock l(m_RouterInfosMutex); for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();) { - if (it->second->IsUnreachable ()) + if (it->second->IsUnreachable ()) { it->second->SaveProfile (); it = m_RouterInfos.erase (it); continue; - } + } ++it; } - } + } // clean up expired floodfiils { std::unique_lock l(m_FloodfillsMutex); @@ -536,7 +536,7 @@ namespace data it = m_Floodfills.erase (it); else ++it; - } + } } } @@ -546,49 +546,49 @@ namespace data if (!dest) { LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already"); - return; + return; } auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ()); if (floodfill) - transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); + transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found"); m_Requests.RequestComplete (destination, nullptr); - } - } + } + } void NetDb::RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete) { - + auto dest = m_Requests.CreateRequest (destination, exploritory, requestComplete); // non-exploratory if (!dest) { LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already"); - return; + return; } LogPrint(eLogInfo, "NetDb: destination ", destination.ToBase64(), " being requested directly from ", from.ToBase64()); // direct - transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr)); - } - - + transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr)); + } + + void NetDb::HandleDatabaseStoreMsg (std::shared_ptr m) - { + { const uint8_t * buf = m->GetPayload (); - size_t len = m->GetSize (); + size_t len = m->GetSize (); IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET); if (ident.IsZero ()) { LogPrint (eLogDebug, "NetDb: database store with zero ident, dropped"); return; - } + } uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET); size_t offset = DATABASE_STORE_HEADER_SIZE; if (replyToken) { - auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); + auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); uint32_t tunnelID = bufbe32toh (buf + offset); offset += 4; if (!tunnelID) // send response directly @@ -601,23 +601,23 @@ namespace data outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus); else LogPrint (eLogWarning, "NetDb: no outbound tunnels for DatabaseStore reply found"); - } + } offset += 32; } - // we must send reply back before this check + // we must send reply back before this check if (ident == i2p::context.GetIdentHash ()) { LogPrint (eLogDebug, "NetDb: database store with own RouterInfo received, dropped"); return; } - size_t payloadOffset = offset; + size_t payloadOffset = offset; bool updated = false; if (buf[DATABASE_STORE_TYPE_OFFSET]) // type { LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32()); updated = AddLeaseSet (ident, buf + offset, len - offset, m->from); - } + } else { LogPrint (eLogDebug, "NetDb: store request: RouterInfo"); @@ -627,31 +627,31 @@ namespace data { LogPrint (eLogError, "NetDb: invalid RouterInfo length ", (int)size); return; - } + } uint8_t uncompressed[2048]; size_t uncompressedSize = m_Inflator.Inflate (buf + offset, size, uncompressed, 2048); if (uncompressedSize && uncompressedSize < 2048) updated = AddRouterInfo (ident, uncompressed, uncompressedSize); else - { + { LogPrint (eLogInfo, "NetDb: decompression failed ", uncompressedSize); return; - } - } + } + } if (replyToken && context.IsFloodfill () && updated) { // flood updated auto floodMsg = NewI2NPShortMessage (); - uint8_t * payload = floodMsg->GetPayload (); + uint8_t * payload = floodMsg->GetPayload (); memcpy (payload, buf, 33); // key + type htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token size_t msgLen = len - payloadOffset; floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen; if (floodMsg->len < floodMsg->maxLen) - { + { memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen); - floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); + floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); std::set excluded; excluded.insert (i2p::context.GetIdentHash ()); // don't flood to itself excluded.insert (ident); // don't flood back @@ -667,12 +667,12 @@ namespace data } else break; - } - } + } + } else LogPrint (eLogError, "NetDb: Database store message is too long ", floodMsg->len); - } - } + } + } void NetDb::HandleDatabaseSearchReplyMsg (std::shared_ptr msg) { @@ -683,12 +683,12 @@ namespace data int num = buf[32]; // num LogPrint (eLogDebug, "NetDb: DatabaseSearchReply for ", key, " num=", num); IdentHash ident (buf); - auto dest = m_Requests.FindRequest (ident); + auto dest = m_Requests.FindRequest (ident); if (dest) - { + { bool deleteDest = true; if (num > 0) - { + { auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; auto inbound = pool ? pool->GetNextInboundTunnel () : nullptr; @@ -700,36 +700,36 @@ namespace data std::vector msgs; auto count = dest->GetExcludedPeers ().size (); if (count < 7) - { + { auto nextFloodfill = GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); if (nextFloodfill) - { - // tell floodfill about us - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + { + // tell floodfill about us + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, nextFloodfill->GetIdentHash (), 0, - CreateDatabaseStoreMsg () - }); - + CreateDatabaseStoreMsg () + }); + // request destination LogPrint (eLogDebug, "NetDb: Try ", key, " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); auto msg = dest->CreateRequestMessage (nextFloodfill, inbound); - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, nextFloodfill->GetIdentHash (), 0, msg }); deleteDest = false; - } + } } else LogPrint (eLogWarning, "NetDb: ", key, " was not found on ", count, " floodfills"); if (msgs.size () > 0) - outbound->SendTunnelDataMsg (msgs); - } - } + outbound->SendTunnelDataMsg (msgs); + } + } if (deleteDest) // no more requests for the destinationation. delete it @@ -751,9 +751,9 @@ namespace data peerHash[l1] = 0; LogPrint (eLogDebug, "NetDb: ", i, ": ", peerHash); - auto r = FindRouter (router); - if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL) - { + auto r = FindRouter (router); + if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL) + { // router with ident not found or too old (1 hour) LogPrint (eLogDebug, "NetDb: found new/outdated router. Requesting RouterInfo ..."); if(m_FloodfillBootstrap) @@ -763,9 +763,9 @@ namespace data } else LogPrint (eLogDebug, "NetDb: [:|||:]"); - } - } - + } + } + void NetDb::HandleDatabaseLookupMsg (std::shared_ptr msg) { const uint8_t * buf = msg->GetPayload (); @@ -774,7 +774,7 @@ namespace data { LogPrint (eLogError, "NetDb: DatabaseLookup for zero ident. Ignored"); return; - } + } char key[48]; int l = i2p::data::ByteStreamToBase64 (buf, 32, key, 48); key[l] = 0; @@ -782,24 +782,24 @@ namespace data IdentHash replyIdent(buf + 32); uint8_t flag = buf[64]; - + LogPrint (eLogDebug, "NetDb: DatabaseLookup for ", key, " received flags=", (int)flag); uint8_t lookupType = flag & DATABASE_LOOKUP_TYPE_FLAGS_MASK; - const uint8_t * excluded = buf + 65; + const uint8_t * excluded = buf + 65; uint32_t replyTunnelID = 0; if (flag & DATABASE_LOOKUP_DELIVERY_FLAG) //reply to tunnel { replyTunnelID = bufbe32toh (excluded); excluded += 4; } - uint16_t numExcluded = bufbe16toh (excluded); + uint16_t numExcluded = bufbe16toh (excluded); excluded += 2; if (numExcluded > 512) { LogPrint (eLogWarning, "NetDb: number of excluded peers", numExcluded, " exceeds 512"); return; - } - + } + std::shared_ptr replyMsg; if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP) { @@ -809,34 +809,34 @@ namespace data { excludedRouters.insert (excluded); excluded += 32; - } + } std::vector routers; for (int i = 0; i < 3; i++) { auto r = GetClosestNonFloodfill (ident, excludedRouters); if (r) - { + { routers.push_back (r->GetIdentHash ()); excludedRouters.insert (r->GetIdentHash ()); - } - } + } + } replyMsg = CreateDatabaseSearchReply (ident, routers); - } + } else - { + { if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP) - { + { auto router = FindRouter (ident); if (router) { LogPrint (eLogDebug, "NetDb: requested RouterInfo ", key, " found"); router->LoadBuffer (); - if (router->GetBuffer ()) + if (router->GetBuffer ()) replyMsg = CreateDatabaseStoreMsg (router); } } - + if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)) { @@ -852,9 +852,9 @@ namespace data replyMsg = CreateDatabaseStoreMsg (leaseSet); } } - + if (!replyMsg) - { + { std::set excludedRouters; const uint8_t * exclude_ident = excluded; for (int i = 0; i < numExcluded; i++) @@ -868,9 +868,9 @@ namespace data replyMsg = CreateDatabaseSearchReply (ident, closestFloodfills); } } - excluded += numExcluded * 32; + excluded += numExcluded * 32; if (replyMsg) - { + { if (replyTunnelID) { // encryption might be used though tunnel only @@ -887,7 +887,7 @@ namespace data } else LogPrint(eLogWarning, "NetDb: encrypted reply requested but no tags provided"); - } + } auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; if (outbound) @@ -898,124 +898,124 @@ namespace data else transports.SendMessage (replyIdent, replyMsg); } - } + } void NetDb::Explore (int numDestinations) - { + { // new requests auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr; bool throughTunnels = outbound && inbound; - + uint8_t randomHash[32]; std::vector msgs; LogPrint (eLogInfo, "NetDb: exploring new ", numDestinations, " routers ..."); for (int i = 0; i < numDestinations; i++) - { + { RAND_bytes (randomHash, 32); auto dest = m_Requests.CreateRequest (randomHash, true); // exploratory if (!dest) - { + { LogPrint (eLogWarning, "NetDb: exploratory destination is requested already"); - return; - } + return; + } auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ()); - if (floodfill) - { + if (floodfill) + { if (i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) throughTunnels = false; if (throughTunnels) - { - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + { + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, floodfill->GetIdentHash (), 0, - CreateDatabaseStoreMsg () // tell floodfill about us - }); - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + CreateDatabaseStoreMsg () // tell floodfill about us + }); + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, - floodfill->GetIdentHash (), 0, + floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound) // explore - }); - } + }); + } else i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); - } + } else m_Requests.RequestComplete (randomHash, nullptr); - } + } if (throughTunnels && msgs.size () > 0) - outbound->SendTunnelDataMsg (msgs); - } + outbound->SendTunnelDataMsg (msgs); + } void NetDb::Publish () { i2p::context.UpdateStats (); // for floodfill std::set excluded; // TODO: fill up later for (int i = 0; i < 2; i++) - { + { auto floodfill = GetClosestFloodfill (i2p::context.GetRouterInfo ().GetIdentHash (), excluded); if (floodfill) { uint32_t replyToken; RAND_bytes ((uint8_t *)&replyToken, 4); LogPrint (eLogInfo, "NetDb: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken); - transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); + transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); excluded.insert (floodfill->GetIdentHash ()); } - } - } + } + } std::shared_ptr NetDb::GetRandomRouter () const { return GetRandomRouter ( - [](std::shared_ptr router)->bool - { - return !router->IsHidden (); + [](std::shared_ptr router)->bool + { + return !router->IsHidden (); }); - } - + } + std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith) const { return GetRandomRouter ( - [compatibleWith](std::shared_ptr router)->bool - { - return !router->IsHidden () && router != compatibleWith && - router->IsCompatible (*compatibleWith); + [compatibleWith](std::shared_ptr router)->bool + { + return !router->IsHidden () && router != compatibleWith && + router->IsCompatible (*compatibleWith); }); - } + } std::shared_ptr NetDb::GetRandomPeerTestRouter (bool v4only) const { return GetRandomRouter ( - [v4only](std::shared_ptr router)->bool - { - return !router->IsHidden () && router->IsPeerTesting () && router->IsSSU (v4only); + [v4only](std::shared_ptr router)->bool + { + return !router->IsHidden () && router->IsPeerTesting () && router->IsSSU (v4only); }); } std::shared_ptr NetDb::GetRandomIntroducer () const { return GetRandomRouter ( - [](std::shared_ptr router)->bool - { - return !router->IsHidden () && router->IsIntroducer (); + [](std::shared_ptr router)->bool + { + return !router->IsHidden () && router->IsIntroducer (); }); - } - + } + std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith) const { return GetRandomRouter ( - [compatibleWith](std::shared_ptr router)->bool - { + [compatibleWith](std::shared_ptr router)->bool + { return !router->IsHidden () && router != compatibleWith && - router->IsCompatible (*compatibleWith) && + router->IsCompatible (*compatibleWith) && (router->GetCaps () & RouterInfo::eHighBandwidth); }); - } - + } + template std::shared_ptr NetDb::GetRandomRouter (Filter filter) const { @@ -1023,31 +1023,31 @@ namespace data return 0; uint32_t ind = rand () % m_RouterInfos.size (); for (int j = 0; j < 2; j++) - { + { uint32_t i = 0; std::unique_lock l(m_RouterInfosMutex); for (const auto& it: m_RouterInfos) - { + { if (i >= ind) - { + { if (!it.second->IsUnreachable () && filter (it.second)) return it.second; - } - else + } + else i++; } // we couldn't find anything, try second pass ind = 0; - } + } return nullptr; // seems we have too few routers - } - + } + void NetDb::PostI2NPMsg (std::shared_ptr msg) { - if (msg) m_Queue.Put (msg); - } + if (msg) m_Queue.Put (msg); + } - std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, + std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, const std::set& excluded, bool closeThanUsOnly) const { std::shared_ptr r; @@ -1055,23 +1055,23 @@ namespace data IdentHash destKey = CreateRoutingKey (destination); if (closeThanUsOnly) minMetric = destKey ^ i2p::context.GetIdentHash (); - else + else minMetric.SetMax (); std::unique_lock l(m_FloodfillsMutex); for (const auto& it: m_Floodfills) - { + { if (!it->IsUnreachable ()) - { + { XORMetric m = destKey ^ it->GetIdentHash (); if (m < minMetric && !excluded.count (it->GetIdentHash ())) { minMetric = m; r = it; } - } - } + } + } return r; - } + } std::vector NetDb::GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded, bool closeThanUsOnly) const @@ -1092,7 +1092,7 @@ namespace data for (const auto& it: m_Floodfills) { if (!it->IsUnreachable ()) - { + { XORMetric m = destKey ^ it->GetIdentHash (); if (closeThanUsOnly && ourMetric < m) continue; if (sorted.size () < num) @@ -1106,22 +1106,22 @@ namespace data } } - std::vector res; - size_t i = 0; + std::vector res; + size_t i = 0; for (const auto& it: sorted) { if (i < num) { const auto& ident = it.r->GetIdentHash (); if (!excluded.count (ident)) - { + { res.push_back (ident); i++; } } else break; - } + } return res; } @@ -1132,8 +1132,8 @@ namespace data return router->IsFamily(fam); }); } - - std::shared_ptr NetDb::GetClosestNonFloodfill (const IdentHash& destination, + + std::shared_ptr NetDb::GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const { std::shared_ptr r; @@ -1142,31 +1142,31 @@ namespace data minMetric.SetMax (); // must be called from NetDb thread only for (const auto& it: m_RouterInfos) - { + { if (!it.second->IsFloodfill ()) - { + { XORMetric m = destKey ^ it.first; if (m < minMetric && !excluded.count (it.first)) { minMetric = m; r = it.second; } - } - } + } + } return r; - } - + } + void NetDb::ManageLeaseSets () { auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it = m_LeaseSets.begin (); it != m_LeaseSets.end ();) { - if (ts > it->second->GetExpirationTime () - LEASE_ENDDATE_THRESHOLD) + if (ts > it->second->GetExpirationTime () - LEASE_ENDDATE_THRESHOLD) { LogPrint (eLogInfo, "NetDb: LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); it = m_LeaseSets.erase (it); - } - else + } + else ++it; } } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index a5cec84f..18377b4f 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -25,7 +25,7 @@ namespace i2p { namespace data -{ +{ const int NETDB_MIN_ROUTERS = 90; const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60; @@ -37,11 +37,11 @@ namespace data typedef std::function)> LeaseSetVisitor; /** function for visiting a router info we have locally */ - typedef std::function)> RouterInfoVisitor; + typedef std::function)> RouterInfoVisitor; /** function for visiting a router info and determining if we want to use it */ typedef std::function)> RouterInfoFilter; - + class NetDb { public: @@ -51,7 +51,7 @@ namespace data void Start (); void Stop (); - + bool AddRouterInfo (const uint8_t * buf, int len); bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from); @@ -59,12 +59,12 @@ namespace data std::shared_ptr FindLeaseSet (const IdentHash& destination) const; std::shared_ptr FindRouterProfile (const IdentHash& ident) const; - void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr); - void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr); - + void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr); + void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr); + void HandleDatabaseStoreMsg (std::shared_ptr msg); void HandleDatabaseSearchReplyMsg (std::shared_ptr msg); - void HandleDatabaseLookupMsg (std::shared_ptr msg); + void HandleDatabaseLookupMsg (std::shared_ptr msg); std::shared_ptr GetRandomRouter () const; std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith) const; @@ -76,13 +76,13 @@ namespace data std::set& excluded, bool closeThanUsOnly = false) const; std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; std::shared_ptr GetRandomRouterInFamily(const std::string & fam) const; - void SetUnreachable (const IdentHash& ident, bool unreachable); + void SetUnreachable (const IdentHash& ident, bool unreachable); void PostI2NPMsg (std::shared_ptr msg); /** set hidden mode, aka don't publish our RI to netdb and don't explore */ - void SetHidden(bool hide); - + void SetHidden(bool hide); + void Reseed (); Families& GetFamilies () { return m_Families; }; @@ -108,28 +108,28 @@ namespace data bool LoadRouterInfo (const std::string & path); void SaveUpdated (); void Run (); // exploratory thread - void Explore (int numDestinations); + void Explore (int numDestinations); void Publish (); void ManageLeaseSets (); void ManageRequests (); void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20); - + template - std::shared_ptr GetRandomRouter (Filter filter) const; - + std::shared_ptr GetRandomRouter (Filter filter) const; + private: - + mutable std::mutex m_LeaseSetsMutex; std::map > m_LeaseSets; mutable std::mutex m_RouterInfosMutex; std::map > m_RouterInfos; mutable std::mutex m_FloodfillsMutex; std::list > m_Floodfills; - + bool m_IsRunning; uint64_t m_LastLoad; - std::thread * m_Thread; + std::thread * m_Thread; i2p::util::Queue > m_Queue; // of I2NPDatabaseStoreMsg GzipInflator m_Inflator; @@ -137,12 +137,12 @@ namespace data Families m_Families; i2p::fs::HashedStorage m_Storage; - friend class NetDbRequests; + friend class NetDbRequests; NetDbRequests m_Requests; /** router info we are bootstrapping from or nullptr if we are not currently doing that*/ std::shared_ptr m_FloodfillBootstrap; - + /** true if in hidden mode */ bool m_HiddenMode; diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 2fe2c229..f1853124 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -13,8 +13,8 @@ namespace data { std::shared_ptr msg; if(replyTunnel) - msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, - replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory, + msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, + replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory, &m_ExcludedPeers); else msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers); @@ -22,22 +22,22 @@ namespace data m_ExcludedPeers.insert (router->GetIdentHash ()); m_CreationTime = i2p::util::GetSecondsSinceEpoch (); return msg; - } + } std::shared_ptr RequestedDestination::CreateRequestMessage (const IdentHash& floodfill) { - auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, + auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, i2p::context.GetRouterInfo ().GetIdentHash () , 0, false, &m_ExcludedPeers); m_ExcludedPeers.insert (floodfill); m_CreationTime = i2p::util::GetSecondsSinceEpoch (); return msg; - } + } void RequestedDestination::ClearExcludedPeers () { m_ExcludedPeers.clear (); - } - + } + void RequestedDestination::Success (std::shared_ptr r) { if (m_RequestComplete) @@ -69,15 +69,15 @@ namespace data std::shared_ptr NetDbRequests::CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete) { // request RouterInfo directly - auto dest = std::make_shared (destination, isExploratory); + auto dest = std::make_shared (destination, isExploratory); dest->SetRequestComplete (requestComplete); { std::unique_lock l(m_RequestedDestinationsMutex); if (!m_RequestedDestinations.insert (std::make_pair (destination, dest)).second) // not inserted - return nullptr; + return nullptr; } return dest; - } + } void NetDbRequests::RequestComplete (const IdentHash& ident, std::shared_ptr r) { @@ -86,18 +86,18 @@ namespace data std::unique_lock l(m_RequestedDestinationsMutex); auto it = m_RequestedDestinations.find (ident); if (it != m_RequestedDestinations.end ()) - { + { request = it->second; m_RequestedDestinations.erase (it); - } - } + } + } if (request) { if (r) request->Success (r); else request->Fail (); - } + } } std::shared_ptr NetDbRequests::FindRequest (const IdentHash& ident) const @@ -107,12 +107,12 @@ namespace data if (it != m_RequestedDestinations.end ()) return it->second; return nullptr; - } + } void NetDbRequests::ManageRequests () { - uint64_t ts = i2p::util::GetSecondsSinceEpoch (); - std::unique_lock l(m_RequestedDestinationsMutex); + uint64_t ts = i2p::util::GetSecondsSinceEpoch (); + std::unique_lock l(m_RequestedDestinationsMutex); for (auto it = m_RequestedDestinations.begin (); it != m_RequestedDestinations.end ();) { auto& dest = it->second; @@ -126,7 +126,7 @@ namespace data { auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = pool->GetNextOutboundTunnel (); - auto inbound = pool->GetNextInboundTunnel (); + auto inbound = pool->GetNextInboundTunnel (); auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); if (nextFloodfill && outbound && inbound) outbound->SendTunnelDataMsg (nextFloodfill->GetIdentHash (), 0, @@ -138,15 +138,15 @@ namespace data if (!outbound) LogPrint (eLogWarning, "NetDbReq: No outbound tunnels"); if (!nextFloodfill) LogPrint (eLogWarning, "NetDbReq: No more floodfills"); } - } + } else { if (!dest->IsExploratory ()) LogPrint (eLogWarning, "NetDbReq: ", dest->GetDestination ().ToBase64 (), " not found after 7 attempts"); done = true; - } - } - } + } + } + } else // delete obsolete request done = true; @@ -154,7 +154,7 @@ namespace data it = m_RequestedDestinations.erase (it); else ++it; - } + } } } } diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index debf1273..7a7a55ab 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -12,14 +12,14 @@ namespace i2p namespace data { class RequestedDestination - { + { public: typedef std::function)> RequestComplete; RequestedDestination (const IdentHash& destination, bool isExploratory = false): m_Destination (destination), m_IsExploratory (isExploratory), m_CreationTime (0) {}; - ~RequestedDestination () { if (m_RequestComplete) m_RequestComplete (nullptr); }; + ~RequestedDestination () { if (m_RequestComplete) m_RequestComplete (nullptr); }; const IdentHash& GetDestination () const { return m_Destination; }; int GetNumExcludedPeers () const { return m_ExcludedPeers.size (); }; @@ -30,12 +30,12 @@ namespace data uint64_t GetCreationTime () const { return m_CreationTime; }; std::shared_ptr CreateRequestMessage (std::shared_ptr, std::shared_ptr replyTunnel); std::shared_ptr CreateRequestMessage (const IdentHash& floodfill); - + void SetRequestComplete (const RequestComplete& requestComplete) { m_RequestComplete = requestComplete; }; bool IsRequestComplete () const { return m_RequestComplete != nullptr; }; void Success (std::shared_ptr r); void Fail (); - + private: IdentHash m_Destination; @@ -43,7 +43,7 @@ namespace data std::set m_ExcludedPeers; uint64_t m_CreationTime; RequestComplete m_RequestComplete; - }; + }; class NetDbRequests { diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 34e0681f..3840eb32 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -15,20 +15,20 @@ namespace data RouterProfile::RouterProfile (): m_LastUpdateTime (boost::posix_time::second_clock::local_time()), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0), - m_NumTimesTaken (0), m_NumTimesRejected (0) + m_NumTimesTaken (0), m_NumTimesRejected (0) { } boost::posix_time::ptime RouterProfile::GetTime () const { return boost::posix_time::second_clock::local_time(); - } - + } + void RouterProfile::UpdateTime () { m_LastUpdateTime = GetTime (); - } - + } + void RouterProfile::Save (const IdentHash& identHash) { // fill sections @@ -63,57 +63,57 @@ namespace data std::string path = m_ProfilesStorage.Path(ident); boost::property_tree::ptree pt; - if (!i2p::fs::Exists(path)) + if (!i2p::fs::Exists(path)) { LogPrint(eLogWarning, "Profiling: no profile yet for ", ident); return; } - try + try { boost::property_tree::read_ini (path, pt); - } catch (std::exception& ex) + } catch (std::exception& ex) { /* boost exception verbose enough */ LogPrint (eLogError, "Profiling: ", ex.what ()); return; } - try + try { auto t = pt.get (PEER_PROFILE_LAST_UPDATE_TIME, ""); if (t.length () > 0) m_LastUpdateTime = boost::posix_time::time_from_string (t); - if ((GetTime () - m_LastUpdateTime).hours () < PEER_PROFILE_EXPIRATION_TIMEOUT) + if ((GetTime () - m_LastUpdateTime).hours () < PEER_PROFILE_EXPIRATION_TIMEOUT) { - try - { + try + { // read participations auto participations = pt.get_child (PEER_PROFILE_SECTION_PARTICIPATION); m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); - } - catch (boost::property_tree::ptree_bad_path& ex) + } + catch (boost::property_tree::ptree_bad_path& ex) { LogPrint (eLogWarning, "Profiling: Missing section ", PEER_PROFILE_SECTION_PARTICIPATION, " in profile for ", ident); - } - try + } + try { // read usage auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE); m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0); m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0); - } - catch (boost::property_tree::ptree_bad_path& ex) + } + catch (boost::property_tree::ptree_bad_path& ex) { LogPrint (eLogWarning, "Missing section ", PEER_PROFILE_SECTION_USAGE, " in profile for ", ident); } - } - else + } + else *this = RouterProfile (); - } - catch (std::exception& ex) + } + catch (std::exception& ex) { LogPrint (eLogError, "Profiling: Can't read profile ", ident, " :", ex.what ()); } @@ -126,46 +126,46 @@ namespace data m_NumTunnelsDeclined++; else m_NumTunnelsAgreed++; - } + } void RouterProfile::TunnelNonReplied () { m_NumTunnelsNonReplied++; UpdateTime (); - } + } bool RouterProfile::IsLowPartcipationRate () const { return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate - } + } bool RouterProfile::IsLowReplyRate () const { auto total = m_NumTunnelsAgreed + m_NumTunnelsDeclined; return m_NumTunnelsNonReplied > 10*(total + 1); - } - + } + bool RouterProfile::IsBad () - { + { auto isBad = IsAlwaysDeclining () || IsLowPartcipationRate () /*|| IsLowReplyRate ()*/; - if (isBad && m_NumTimesRejected > 10*(m_NumTimesTaken + 1)) + if (isBad && m_NumTimesRejected > 10*(m_NumTimesTaken + 1)) { // reset profile m_NumTunnelsAgreed = 0; m_NumTunnelsDeclined = 0; m_NumTunnelsNonReplied = 0; isBad = false; - } + } if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++; - return isBad; + return isBad; } - + std::shared_ptr GetRouterProfile (const IdentHash& identHash) { auto profile = std::make_shared (); profile->Load (identHash); // if possible return profile; - } + } void InitProfilesStorage () { @@ -191,5 +191,5 @@ namespace data } } } -} -} +} +} diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 34ed4f72..4ba6702f 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -8,32 +8,32 @@ namespace i2p { namespace data -{ +{ // sections const char PEER_PROFILE_SECTION_PARTICIPATION[] = "participation"; const char PEER_PROFILE_SECTION_USAGE[] = "usage"; - // params + // params const char PEER_PROFILE_LAST_UPDATE_TIME[] = "lastupdatetime"; const char PEER_PROFILE_PARTICIPATION_AGREED[] = "agreed"; const char PEER_PROFILE_PARTICIPATION_DECLINED[] = "declined"; - const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied"; + const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied"; const char PEER_PROFILE_USAGE_TAKEN[] = "taken"; const char PEER_PROFILE_USAGE_REJECTED[] = "rejected"; const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days) - + class RouterProfile { public: RouterProfile (); RouterProfile& operator= (const RouterProfile& ) = default; - + void Save (const IdentHash& identHash); void Load (const IdentHash& identHash); bool IsBad (); - + void TunnelBuildResponse (uint8_t ret); void TunnelNonReplied (); @@ -45,23 +45,23 @@ namespace data bool IsAlwaysDeclining () const { return !m_NumTunnelsAgreed && m_NumTunnelsDeclined >= 5; }; bool IsLowPartcipationRate () const; bool IsLowReplyRate () const; - - private: + + private: boost::posix_time::ptime m_LastUpdateTime; // participation uint32_t m_NumTunnelsAgreed; - uint32_t m_NumTunnelsDeclined; + uint32_t m_NumTunnelsDeclined; uint32_t m_NumTunnelsNonReplied; // usage uint32_t m_NumTimesTaken; - uint32_t m_NumTimesRejected; - }; + uint32_t m_NumTimesRejected; + }; - std::shared_ptr GetRouterProfile (const IdentHash& identHash); + std::shared_ptr GetRouterProfile (const IdentHash& identHash); void InitProfilesStorage (); void DeleteObsoleteProfiles (); -} -} +} +} #endif diff --git a/libi2pd/Queue.h b/libi2pd/Queue.h index 9e95b2a5..d701e4b8 100644 --- a/libi2pd/Queue.h +++ b/libi2pd/Queue.h @@ -15,7 +15,7 @@ namespace util { template class Queue - { + { public: void Put (Element e) @@ -29,14 +29,14 @@ namespace util void Put (const Container& vec) { if (!vec.empty ()) - { + { std::unique_lock l(m_QueueMutex); for (const auto& it: vec) - m_Queue.push (it); + m_Queue.push (it); m_NonEmpty.notify_one (); - } + } } - + Element GetNext () { std::unique_lock l(m_QueueMutex); @@ -45,7 +45,7 @@ namespace util { m_NonEmpty.wait (l); el = GetNonThreadSafe (); - } + } return el; } @@ -57,7 +57,7 @@ namespace util { m_NonEmpty.wait_for (l, std::chrono::milliseconds (usec)); el = GetNonThreadSafe (); - } + } return el; } @@ -73,17 +73,17 @@ namespace util return m_NonEmpty.wait_for (l, std::chrono::seconds (sec) + std::chrono::milliseconds (usec)) != std::cv_status::timeout; } - bool IsEmpty () - { + bool IsEmpty () + { std::unique_lock l(m_QueueMutex); return m_Queue.empty (); } - int GetSize () + int GetSize () { std::unique_lock l(m_QueueMutex); return m_Queue.size (); - } + } void WakeUp () { m_NonEmpty.notify_all (); }; @@ -91,14 +91,14 @@ namespace util { std::unique_lock l(m_QueueMutex); return GetNonThreadSafe (); - } + } Element Peek () { std::unique_lock l(m_QueueMutex); return GetNonThreadSafe (true); - } - + } + private: Element GetNonThreadSafe (bool peek = false) @@ -109,17 +109,17 @@ namespace util if (!peek) m_Queue.pop (); return el; - } + } return nullptr; - } - + } + private: std::queue m_Queue; std::mutex m_QueueMutex; std::condition_variable m_NonEmpty; - }; -} -} + }; +} +} #endif diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 12888cef..4a2f8055 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include @@ -23,7 +23,7 @@ namespace i2p { namespace data { - + Reseeder::Reseeder() { } @@ -114,11 +114,11 @@ namespace data return 0; } } - + int Reseeder::ProcessSU3File (const char * filename) { std::ifstream s(filename, std::ifstream::binary); - if (s.is_open ()) + if (s.is_open ()) return ProcessSU3Stream (s); else { @@ -130,21 +130,21 @@ namespace data int Reseeder::ProcessZIPFile (const char * filename) { std::ifstream s(filename, std::ifstream::binary); - if (s.is_open ()) - { + if (s.is_open ()) + { s.seekg (0, std::ios::end); auto len = s.tellg (); s.seekg (0, std::ios::beg); return ProcessZIPStream (s, len); - } + } else { LogPrint (eLogError, "Reseed: Can't open file ", filename); return 0; } - } - - const char SU3_MAGIC_NUMBER[]="I2Psu3"; + } + + const char SU3_MAGIC_NUMBER[]="I2Psu3"; int Reseeder::ProcessSU3Stream (std::istream& s) { char magicNumber[7]; @@ -153,7 +153,7 @@ namespace data { LogPrint (eLogError, "Reseed: Unexpected SU3 magic number"); return 0; - } + } s.seekg (1, std::ios::cur); // su3 file format version SigningKeyType signatureType; s.read ((char *)&signatureType, 2); // signature type @@ -163,16 +163,16 @@ namespace data signatureLength = be16toh (signatureLength); s.seekg (1, std::ios::cur); // unused uint8_t versionLength; - s.read ((char *)&versionLength, 1); // version length + s.read ((char *)&versionLength, 1); // version length s.seekg (1, std::ios::cur); // unused uint8_t signerIDLength; - s.read ((char *)&signerIDLength, 1); // signer ID length + s.read ((char *)&signerIDLength, 1); // signer ID length uint64_t contentLength; - s.read ((char *)&contentLength, 8); // content length + s.read ((char *)&contentLength, 8); // content length contentLength = be64toh (contentLength); s.seekg (1, std::ios::cur); // unused uint8_t fileType; - s.read ((char *)&fileType, 1); // file type + s.read ((char *)&fileType, 1); // file type if (fileType != 0x00) // zip file { LogPrint (eLogError, "Reseed: Can't handle file type ", (int)fileType); @@ -180,7 +180,7 @@ namespace data } s.seekg (1, std::ios::cur); // unused uint8_t contentType; - s.read ((char *)&contentType, 1); // content type + s.read ((char *)&contentType, 1); // content type if (contentType != 0x03) // reseed data { LogPrint (eLogError, "Reseed: Unexpected content type ", (int)contentType); @@ -192,10 +192,10 @@ namespace data char signerID[256]; s.read (signerID, signerIDLength); // signerID signerID[signerIDLength] = 0; - + bool verify; i2p::config::GetOption("reseed.verify", verify); if (verify) - { + { //try to verify signature auto it = m_SigningKeys.find (signerID); if (it != m_SigningKeys.end ()) @@ -220,7 +220,7 @@ namespace data BIGNUM * s = BN_new (), * n = BN_new (); BN_bin2bn (signature, signatureLength, s); BN_bin2bn (it->second, i2p::crypto::RSASHA5124096_KEY_LENGTH, n); - BN_mod_exp (s, s, i2p::crypto::GetRSAE (), n, bnctx); // s = s^e mod n + BN_mod_exp (s, s, i2p::crypto::GetRSAE (), n, bnctx); // s = s^e mod n uint8_t * enSigBuf = new uint8_t[signatureLength]; i2p::crypto::bn2buf (s, enSigBuf, signatureLength); // digest is right aligned @@ -232,8 +232,8 @@ namespace data delete[] enSigBuf; BN_free (s); BN_free (n); BN_CTX_free (bnctx); - } - + } + delete[] signature; delete[] tbs; s.seekg (pos, std::ios::beg); @@ -249,21 +249,21 @@ namespace data { LogPrint (eLogError, "Reseed: SU3 verification failed"); return 0; - } + } // handle content return ProcessZIPStream (s, contentLength); } const uint32_t ZIP_HEADER_SIGNATURE = 0x04034B50; - const uint32_t ZIP_CENTRAL_DIRECTORY_HEADER_SIGNATURE = 0x02014B50; + const uint32_t ZIP_CENTRAL_DIRECTORY_HEADER_SIGNATURE = 0x02014B50; const uint16_t ZIP_BIT_FLAG_DATA_DESCRIPTOR = 0x0008; int Reseeder::ProcessZIPStream (std::istream& s, uint64_t contentLength) - { + { int numFiles = 0; size_t contentPos = s.tellg (); while (!s.eof ()) - { + { uint32_t signature; s.read ((char *)&signature, 4); signature = le32toh (signature); @@ -272,22 +272,22 @@ namespace data // next local file s.seekg (2, std::ios::cur); // version uint16_t bitFlag; - s.read ((char *)&bitFlag, 2); + s.read ((char *)&bitFlag, 2); bitFlag = le16toh (bitFlag); uint16_t compressionMethod; - s.read ((char *)&compressionMethod, 2); + s.read ((char *)&compressionMethod, 2); compressionMethod = le16toh (compressionMethod); s.seekg (4, std::ios::cur); // skip fields we don't care about - uint32_t compressedSize, uncompressedSize; + uint32_t compressedSize, uncompressedSize; uint32_t crc_32; s.read ((char *)&crc_32, 4); crc_32 = le32toh (crc_32); - s.read ((char *)&compressedSize, 4); - compressedSize = le32toh (compressedSize); + s.read ((char *)&compressedSize, 4); + compressedSize = le32toh (compressedSize); s.read ((char *)&uncompressedSize, 4); - uncompressedSize = le32toh (uncompressedSize); - uint16_t fileNameLength, extraFieldLength; - s.read ((char *)&fileNameLength, 2); + uncompressedSize = le32toh (uncompressedSize); + uint16_t fileNameLength, extraFieldLength; + s.read ((char *)&fileNameLength, 2); fileNameLength = le16toh (fileNameLength); if ( fileNameLength > 255 ) { // too big @@ -308,13 +308,13 @@ namespace data { LogPrint (eLogError, "Reseed: SU3 archive data descriptor not found"); return numFiles; - } - s.read ((char *)&crc_32, 4); + } + s.read ((char *)&crc_32, 4); crc_32 = le32toh (crc_32); - s.read ((char *)&compressedSize, 4); + s.read ((char *)&compressedSize, 4); compressedSize = le32toh (compressedSize) + 4; // ??? we must consider signature as part of compressed data s.read ((char *)&uncompressedSize, 4); - uncompressedSize = le32toh (uncompressedSize); + uncompressedSize = le32toh (uncompressedSize); // now we know compressed and uncompressed size s.seekg (pos, std::ios::beg); // back to compressed data @@ -325,8 +325,8 @@ namespace data { LogPrint (eLogWarning, "Reseed: Unexpected size 0. Skipped"); continue; - } - + } + uint8_t * compressed = new uint8_t[compressedSize]; s.read ((char *)compressed, compressedSize); if (compressionMethod) // we assume Deflate @@ -338,29 +338,29 @@ namespace data inflator.next_in = compressed; inflator.avail_in = compressedSize; inflator.next_out = uncompressed; - inflator.avail_out = uncompressedSize; + inflator.avail_out = uncompressedSize; int err; if ((err = inflate (&inflator, Z_SYNC_FLUSH)) >= 0) - { + { uncompressedSize -= inflator.avail_out; if (crc32 (0, uncompressed, uncompressedSize) == crc_32) { i2p::data::netdb.AddRouterInfo (uncompressed, uncompressedSize); numFiles++; - } + } else LogPrint (eLogError, "Reseed: CRC32 verification failed"); - } + } else LogPrint (eLogError, "Reseed: SU3 decompression error ", err); - delete[] uncompressed; + delete[] uncompressed; inflateEnd (&inflator); } else // no compression { i2p::data::netdb.AddRouterInfo (compressed, compressedSize); numFiles++; - } + } delete[] compressed; if (bitFlag & ZIP_BIT_FLAG_DATA_DESCRIPTOR) s.seekg (12, std::ios::cur); // skip data descriptor section if presented (12 = 16 - 4) @@ -406,15 +406,15 @@ namespace data return numFiles; } - const uint8_t ZIP_DATA_DESCRIPTOR_SIGNATURE[] = { 0x50, 0x4B, 0x07, 0x08 }; + const uint8_t ZIP_DATA_DESCRIPTOR_SIGNATURE[] = { 0x50, 0x4B, 0x07, 0x08 }; bool Reseeder::FindZipDataDescriptor (std::istream& s) { - size_t nextInd = 0; + size_t nextInd = 0; while (!s.eof ()) { uint8_t nextByte; s.read ((char *)&nextByte, 1); - if (nextByte == ZIP_DATA_DESCRIPTOR_SIGNATURE[nextInd]) + if (nextByte == ZIP_DATA_DESCRIPTOR_SIGNATURE[nextInd]) { nextInd++; if (nextInd >= sizeof (ZIP_DATA_DESCRIPTOR_SIGNATURE)) @@ -429,24 +429,24 @@ namespace data void Reseeder::LoadCertificate (const std::string& filename) { SSL_CTX * ctx = SSL_CTX_new (TLS_method ()); - int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); + int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); if (ret) - { + { SSL * ssl = SSL_new (ctx); X509 * cert = SSL_get_certificate (ssl); // verify if (cert) - { + { // extract issuer name char name[100]; X509_NAME_oneline (X509_get_issuer_name(cert), name, 100); char * cn = strstr (name, "CN="); if (cn) - { + { cn += 3; char * terminator = strchr (cn, '/'); if (terminator) terminator[0] = 0; - } + } // extract RSA key (we need n only, e = 65537) RSA * key = EVP_PKEY_get0_RSA (X509_get_pubkey (cert)); const BIGNUM * n, * e, * d; @@ -457,12 +457,12 @@ namespace data m_SigningKeys[cn] = value; else LogPrint (eLogError, "Reseed: Can't find CN field in ", filename); - } - SSL_free (ssl); - } + } + SSL_free (ssl); + } else LogPrint (eLogError, "Reseed: Can't open certificate file ", filename); - SSL_CTX_free (ctx); + SSL_CTX_free (ctx); } void Reseeder::LoadCertificates () @@ -483,9 +483,9 @@ namespace data } LoadCertificate (file); numCertificates++; - } + } LogPrint (eLogInfo, "Reseed: ", numCertificates, " certificates loaded"); - } + } std::string Reseeder::HttpsRequest (const std::string& address) { diff --git a/libi2pd/Reseed.h b/libi2pd/Reseed.h index 6b09f911..a69969bf 100644 --- a/libi2pd/Reseed.h +++ b/libi2pd/Reseed.h @@ -15,10 +15,10 @@ namespace data class Reseeder { - typedef Tag<512> PublicKey; - + typedef Tag<512> PublicKey; + public: - + Reseeder(); ~Reseeder(); void Bootstrap (); @@ -28,19 +28,19 @@ namespace data int ProcessZIPFile (const char * filename); void LoadCertificates (); - + private: void LoadCertificate (const std::string& filename); - - int ProcessSU3Stream (std::istream& s); - int ProcessZIPStream (std::istream& s, uint64_t contentLength); - + + int ProcessSU3Stream (std::istream& s); + int ProcessZIPStream (std::istream& s, uint64_t contentLength); + bool FindZipDataDescriptor (std::istream& s); - + std::string HttpsRequest (const std::string& address); - private: + private: std::map m_SigningKeys; }; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 80a03abf..38fe3224 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -28,7 +28,7 @@ namespace i2p m_StartupTime = i2p::util::GetSecondsSinceEpoch (); if (!Load ()) CreateNewRouter (); - m_Decryptor = m_Keys.CreateDecryptor (nullptr); + m_Decryptor = m_Keys.CreateDecryptor (nullptr); UpdateRouterInfo (); } @@ -204,7 +204,7 @@ namespace i2p } } - void RouterContext::SetBandwidth (char L) + void RouterContext::SetBandwidth (char L) { uint32_t limit = 0; enum { low, high, extra, unlim } type = high; diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index f587e0a5..ef23af25 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -13,7 +13,7 @@ namespace i2p { const char ROUTER_INFO[] = "router.info"; - const char ROUTER_KEYS[] = "router.keys"; + const char ROUTER_KEYS[] = "router.keys"; const int ROUTER_INFO_UPDATE_INTERVAL = 1800; // 30 minutes enum RouterStatus @@ -21,16 +21,16 @@ namespace i2p eRouterStatusOK = 0, eRouterStatusTesting = 1, eRouterStatusFirewalled = 2, - eRouterStatusError = 3 - }; + eRouterStatusError = 3 + }; enum RouterError { eRouterErrorNone = 0, eRouterErrorClockSkew = 1 - }; - - class RouterContext: public i2p::garlic::GarlicDestination + }; + + class RouterContext: public i2p::garlic::GarlicDestination { public: @@ -39,17 +39,17 @@ namespace i2p const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; }; - std::shared_ptr GetSharedRouterInfo () const - { - return std::shared_ptr (&m_RouterInfo, + std::shared_ptr GetSharedRouterInfo () const + { + return std::shared_ptr (&m_RouterInfo, [](const i2p::data::RouterInfo *) {}); } - std::shared_ptr GetSharedDestination () + std::shared_ptr GetSharedDestination () { - return std::shared_ptr (this, + return std::shared_ptr (this, [](i2p::garlic::GarlicDestination *) {}); - } - + } + uint32_t GetUptime () const; uint32_t GetStartupTime () const { return m_StartupTime; }; uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; }; @@ -60,17 +60,17 @@ namespace i2p RouterError GetError () const { return m_Error; }; void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; }; int GetNetID () const { return m_NetID; }; - void SetNetID (int netID) { m_NetID = netID; }; + void SetNetID (int netID) { m_NetID = netID; }; void UpdatePort (int port); // called from Daemon void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer); void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e); bool IsUnreachable () const; - void SetUnreachable (); + void SetUnreachable (); void SetReachable (); - bool IsFloodfill () const { return m_IsFloodfill; }; - void SetFloodfill (bool floodfill); + bool IsFloodfill () const { return m_IsFloodfill; }; + void SetFloodfill (bool floodfill); void SetFamily (const std::string& family); std::string GetFamily () const; void SetBandwidth (int limit); /* in kilobytes */ @@ -83,14 +83,14 @@ namespace i2p void SetSupportsV6 (bool supportsV6); void SetSupportsV4 (bool supportsV4); - void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session - void UpdateStats (); + void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session + void UpdateStats (); void CleanupDestination (); // garlic destination // implements LocalDestination std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const; - void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; void SetLeaseSetUpdated () {}; // implements GarlicDestination @@ -100,8 +100,8 @@ namespace i2p // override GarlicDestination void ProcessGarlicMessage (std::shared_ptr msg); - void ProcessDeliveryStatusMessage (std::shared_ptr msg); - + void ProcessDeliveryStatusMessage (std::shared_ptr msg); + private: void CreateNewRouter (); @@ -109,11 +109,11 @@ namespace i2p void UpdateRouterInfo (); bool Load (); void SaveKeys (); - + private: i2p::data::RouterInfo m_RouterInfo; - i2p::data::PrivateKeys m_Keys; + i2p::data::PrivateKeys m_Keys; std::shared_ptr m_Decryptor; uint64_t m_LastUpdateTime; bool m_AcceptsTunnels, m_IsFloodfill; @@ -127,6 +127,6 @@ namespace i2p }; extern RouterContext context; -} +} #endif diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 642373f2..b119fc26 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -19,20 +19,20 @@ namespace i2p { namespace data -{ - RouterInfo::RouterInfo (): m_Buffer (nullptr) - { +{ + RouterInfo::RouterInfo (): m_Buffer (nullptr) + { m_Addresses = boost::make_shared(); // create empty list } - + RouterInfo::RouterInfo (const std::string& fullPath): - m_FullPath (fullPath), m_IsUpdated (false), m_IsUnreachable (false), + m_FullPath (fullPath), m_IsUpdated (false), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0) { m_Addresses = boost::make_shared(); // create empty list m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; ReadFromFile (); - } + } RouterInfo::RouterInfo (const uint8_t * buf, int len): m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0) @@ -42,13 +42,13 @@ namespace data memcpy (m_Buffer, buf, len); m_BufferLen = len; ReadFromBuffer (true); - } + } RouterInfo::~RouterInfo () { delete[] m_Buffer; - } - + } + void RouterInfo::Update (const uint8_t * buf, int len) { // verify signature since we have indentity already @@ -63,35 +63,35 @@ namespace data // don't clean up m_Addresses, it will be replaced in ReadFromStream m_Properties.clear (); // copy buffer - if (!m_Buffer) + if (!m_Buffer) m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; memcpy (m_Buffer, buf, len); m_BufferLen = len; // skip identity size_t identityLen = m_RouterIdentity->GetFullLen (); - // read new RI + // read new RI std::stringstream str (std::string ((char *)m_Buffer + identityLen, m_BufferLen - identityLen)); ReadFromStream (str); // don't delete buffer until saved to the file } else - { + { LogPrint (eLogError, "RouterInfo: signature verification failed"); m_IsUnreachable = true; } - } - + } + void RouterInfo::SetRouterIdentity (std::shared_ptr identity) - { + { m_RouterIdentity = identity; m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); } - + bool RouterInfo::LoadFile () { std::ifstream s(m_FullPath, std::ifstream::binary); - if (s.is_open ()) - { + if (s.is_open ()) + { s.seekg (0,std::ios::end); m_BufferLen = s.tellg (); if (m_BufferLen < 40 || m_BufferLen > MAX_RI_BUFFER_SIZE) @@ -103,22 +103,22 @@ namespace data if (!m_Buffer) m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; s.read((char *)m_Buffer, m_BufferLen); - } + } else { LogPrint (eLogError, "RouterInfo: Can't open file ", m_FullPath); - return false; + return false; } return true; - } + } void RouterInfo::ReadFromFile () { if (LoadFile ()) - ReadFromBuffer (false); + ReadFromBuffer (false); else - m_IsUnreachable = true; - } + m_IsUnreachable = true; + } void RouterInfo::ReadFromBuffer (bool verifySignature) { @@ -131,7 +131,7 @@ namespace data return; } if (verifySignature) - { + { // reject RSA signatures if (m_RouterIdentity->IsRSA ()) { @@ -140,15 +140,15 @@ namespace data return; } // verify signature - int l = m_BufferLen - m_RouterIdentity->GetSignatureLen (); + int l = m_BufferLen - m_RouterIdentity->GetSignatureLen (); if (l < 0 || !m_RouterIdentity->Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l)) - { + { LogPrint (eLogError, "RouterInfo: signature verification failed"); m_IsUnreachable = true; return; } m_RouterIdentity->DropVerifier (); - } + } // parse RI std::stringstream str; str.write ((const char *)m_Buffer + identityLen, m_BufferLen - identityLen); @@ -158,17 +158,17 @@ namespace data LogPrint (eLogError, "RouterInfo: malformed message"); m_IsUnreachable = true; } - - } - + + } + void RouterInfo::ReadFromStream (std::istream& s) { s.read ((char *)&m_Timestamp, sizeof (m_Timestamp)); m_Timestamp = be64toh (m_Timestamp); // read addresses - auto addresses = boost::make_shared(); + auto addresses = boost::make_shared(); uint8_t numAddresses; - s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return; + s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return; bool introducers = false; for (int i = 0; i < numAddresses; i++) { @@ -181,11 +181,11 @@ namespace data if (!strcmp (transportStyle, "NTCP")) address->transportStyle = eTransportNTCP; else if (!strcmp (transportStyle, "SSU")) - { + { address->transportStyle = eTransportSSU; address->ssu.reset (new SSUExt ()); address->ssu->mtu = 0; - } + } else address->transportStyle = eTransportUnknown; address->port = 0; @@ -197,35 +197,35 @@ namespace data char key[255], value[255]; r += ReadString (key, 255, s); s.seekg (1, std::ios_base::cur); r++; // = - r += ReadString (value, 255, s); + r += ReadString (value, 255, s); s.seekg (1, std::ios_base::cur); r++; // ; if (!s) return; if (!strcmp (key, "host")) - { + { boost::system::error_code ecode; address->host = boost::asio::ip::address::from_string (value, ecode); if (ecode) - { + { if (address->transportStyle == eTransportNTCP) { supportedTransports |= eNTCPV4; // TODO: address->addressString = value; } else - { + { supportedTransports |= eSSUV4; // TODO: address->addressString = value; - } - } + } + } else { // add supported protocol if (address->host.is_v4 ()) - supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4; + supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4; else supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6; - } - } + } + } else if (!strcmp (key, "port")) address->port = boost::lexical_cast(value); else if (!strcmp (key, "mtu")) @@ -234,21 +234,21 @@ namespace data address->ssu->mtu = boost::lexical_cast(value); else LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP"); - } + } else if (!strcmp (key, "key")) - { + { if (address->ssu) Base64ToByteStream (value, strlen (value), address->ssu->key, 32); else LogPrint (eLogWarning, "RouterInfo: Unexpected field 'key' for NTCP"); - } + } else if (!strcmp (key, "caps")) ExtractCaps (value); else if (key[0] == 'i') - { + { // introducers introducers = true; - size_t l = strlen(key); + size_t l = strlen(key); unsigned char index = key[l-1] - '0'; // TODO: key[l-1] = 0; if (index > 9) @@ -257,13 +257,13 @@ namespace data if (s) continue; else return; } if (index >= address->ssu->introducers.size ()) - address->ssu->introducers.resize (index + 1); + address->ssu->introducers.resize (index + 1); Introducer& introducer = address->ssu->introducers.at (index); if (!strcmp (key, "ihost")) { boost::system::error_code ecode; introducer.iHost = boost::asio::ip::address::from_string (value, ecode); - } + } else if (!strcmp (key, "iport")) introducer.iPort = boost::lexical_cast(value); else if (!strcmp (key, "itag")) @@ -274,19 +274,19 @@ namespace data introducer.iExp = boost::lexical_cast(value); } if (!s) return; - } + } if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented if (supportedTransports) { addresses->push_back(address); m_SupportedTransports |= supportedTransports; } - } -#if (BOOST_VERSION >= 105300) + } +#if (BOOST_VERSION >= 105300) boost::atomic_store (&m_Addresses, addresses); #else m_Addresses = addresses; // race condition -#endif +#endif // read peers uint8_t numPeers; s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return; @@ -297,23 +297,23 @@ namespace data size = be16toh (size); while (r < size) { - char key[255], value[255]; + char key[255], value[255]; r += ReadString (key, 255, s); s.seekg (1, std::ios_base::cur); r++; // = - r += ReadString (value, 255, s); + r += ReadString (value, 255, s); s.seekg (1, std::ios_base::cur); r++; // ; if (!s) return; m_Properties[key] = value; - - // extract caps + + // extract caps if (!strcmp (key, "caps")) ExtractCaps (value); // check netId else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID) && atoi (value) != i2p::context.GetNetID ()) { LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value); - m_IsUnreachable = true; - } + m_IsUnreachable = true; + } // family else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY)) { @@ -327,10 +327,10 @@ namespace data LogPrint (eLogWarning, "RouterInfo: family signature verification failed"); m_Family.clear (); } - } + } if (!s) return; - } + } if (!m_SupportedTransports || !m_Addresses->size() || (UsesIntroducer () && !introducers)) SetUnreachable (true); @@ -358,56 +358,56 @@ namespace data case CAPS_FLAG_EXTRA_BANDWIDTH1: case CAPS_FLAG_EXTRA_BANDWIDTH2: m_Caps |= Caps::eExtraBandwidth; - break; + break; case CAPS_FLAG_HIDDEN: m_Caps |= Caps::eHidden; - break; + break; case CAPS_FLAG_REACHABLE: m_Caps |= Caps::eReachable; break; case CAPS_FLAG_UNREACHABLE: m_Caps |= Caps::eUnreachable; - break; + break; case CAPS_FLAG_SSU_TESTING: m_Caps |= Caps::eSSUTesting; - break; + break; case CAPS_FLAG_SSU_INTRODUCER: m_Caps |= Caps::eSSUIntroducer; - break; + break; default: ; - } + } cap++; } } void RouterInfo::UpdateCapsProperty () - { + { std::string caps; - if (m_Caps & eFloodfill) + if (m_Caps & eFloodfill) { if (m_Caps & eExtraBandwidth) caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X' CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P' caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O' - caps += CAPS_FLAG_FLOODFILL; // floodfill - } - else + caps += CAPS_FLAG_FLOODFILL; // floodfill + } + else { - if (m_Caps & eExtraBandwidth) - { + if (m_Caps & eExtraBandwidth) + { caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */ caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O' } - else - caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth - } + else + caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth + } if (m_Caps & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden if (m_Caps & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable if (m_Caps & eUnreachable) caps += CAPS_FLAG_UNREACHABLE; // unreachable SetProperty ("caps", caps); } - + void RouterInfo::WriteToStream (std::ostream& s) const { uint64_t ts = htobe64 (m_Timestamp); @@ -425,7 +425,7 @@ namespace data if (address.transportStyle == eTransportNTCP) WriteString ("NTCP", s); else if (address.transportStyle == eTransportSSU) - { + { WriteString ("SSU", s); // caps WriteString ("caps", properties); @@ -435,7 +435,7 @@ namespace data if (IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; WriteString (caps, properties); properties << ';'; - } + } else WriteString ("", s); @@ -447,7 +447,7 @@ namespace data { // write introducers if any if (address.ssu->introducers.size () > 0) - { + { int i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -456,7 +456,7 @@ namespace data WriteString (introducer.iHost.to_string (), properties); properties << ';'; i++; - } + } i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -468,7 +468,7 @@ namespace data WriteString (value, properties); properties << ';'; i++; - } + } i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -477,7 +477,7 @@ namespace data WriteString (boost::lexical_cast(introducer.iPort), properties); properties << ';'; i++; - } + } i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -486,7 +486,7 @@ namespace data WriteString (boost::lexical_cast(introducer.iTag), properties); properties << ';'; i++; - } + } i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -498,8 +498,8 @@ namespace data properties << ';'; } i++; - } - } + } + } // write intro key WriteString ("key", properties); properties << '='; @@ -515,17 +515,17 @@ namespace data properties << '='; WriteString (boost::lexical_cast(address.ssu->mtu), properties); properties << ';'; - } - } + } + } WriteString ("port", properties); properties << '='; WriteString (boost::lexical_cast(address.port), properties); properties << ';'; - + uint16_t size = htobe16 (properties.str ().size ()); s.write ((char *)&size, sizeof (size)); s.write (properties.str ().c_str (), properties.str ().size ()); - } + } // peers uint8_t numPeers = 0; @@ -539,18 +539,18 @@ namespace data properties << '='; WriteString (p.second, properties); properties << ';'; - } + } uint16_t size = htobe16 (properties.str ().size ()); s.write ((char *)&size, sizeof (size)); s.write (properties.str ().c_str (), properties.str ().size ()); - } + } bool RouterInfo::IsNewer (const uint8_t * buf, size_t len) const { if (!m_RouterIdentity) return false; size_t size = m_RouterIdentity->GetFullLen (); if (size + 8 > len) return false; - return bufbe64toh (buf + size) > m_Timestamp; + return bufbe64toh (buf + size) > m_Timestamp; } const uint8_t * RouterInfo::LoadBuffer () @@ -559,8 +559,8 @@ namespace data { if (LoadFile ()) LogPrint (eLogDebug, "RouterInfo: Buffer for ", GetIdentHashAbbreviation (GetIdentHash ()), " loaded from file"); - } - return m_Buffer; + } + return m_Buffer; } void RouterInfo::CreateBuffer (const PrivateKeys& privateKeys) @@ -569,7 +569,7 @@ namespace data std::stringstream s; uint8_t ident[1024]; auto identLen = privateKeys.GetPublic ()->ToBuffer (ident, 1024); - s.write ((char *)ident, identLen); + s.write ((char *)ident, identLen); WriteToStream (s); m_BufferLen = s.str ().size (); if (!m_Buffer) @@ -578,7 +578,7 @@ namespace data // signature privateKeys.Sign ((uint8_t *)m_Buffer, m_BufferLen, (uint8_t *)m_Buffer + m_BufferLen); m_BufferLen += privateKeys.GetPublic ()->GetSignatureLen (); - } + } bool RouterInfo::SaveToFile (const std::string& fullPath) { @@ -595,13 +595,13 @@ namespace data f.write ((char *)m_Buffer, m_BufferLen); return true; } - + size_t RouterInfo::ReadString (char * str, size_t len, std::istream& s) const { uint8_t l; s.read ((char *)&l, 1); if (l < len) - { + { s.read (str, l); if (!s) l = 0; // failed, return empty string str[l] = 0; @@ -611,16 +611,16 @@ namespace data LogPrint (eLogWarning, "RouterInfo: string length ", (int)l, " exceeds buffer size ", len); s.seekg (l, std::ios::cur); // skip str[0] = 0; - } + } return l+1; - } + } void RouterInfo::WriteString (const std::string& str, std::ostream& s) const { uint8_t len = str.size (); s.write ((char *)&len, 1); s.write (str.c_str (), len); - } + } void RouterInfo::AddNTCPAddress (const char * host, int port) { @@ -634,7 +634,7 @@ namespace data if (*it == *addr) return; m_SupportedTransports |= addr->host.is_v6 () ? eNTCPV6 : eNTCPV4; m_Addresses->push_back(std::move(addr)); - } + } void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu) { @@ -645,7 +645,7 @@ namespace data addr->cost = 10; // NTCP should have priority over SSU addr->date = 0; addr->ssu.reset (new SSUExt ()); - addr->ssu->mtu = mtu; + addr->ssu->mtu = mtu; memcpy (addr->ssu->key, key, 32); for (const auto& it: *m_Addresses) // don't insert same address twice if (*it == *addr) return; @@ -654,37 +654,37 @@ namespace data m_Caps |= eSSUTesting; m_Caps |= eSSUIntroducer; - } + } bool RouterInfo::AddIntroducer (const Introducer& introducer) { for (auto& addr : *m_Addresses) { if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ()) - { + { for (auto& intro: addr->ssu->introducers) if (intro.iTag == introducer.iTag) return false; // already presented addr->ssu->introducers.push_back (introducer); return true; - } - } + } + } return false; - } + } bool RouterInfo::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e) - { + { for (auto& addr: *m_Addresses) { if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ()) - { + { for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) - if ( boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e) + if ( boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e) { addr->ssu->introducers.erase (it); return true; } - } - } + } + } return false; } @@ -693,39 +693,39 @@ namespace data m_Caps = caps; UpdateCapsProperty (); } - + void RouterInfo::SetCaps (const char * caps) { SetProperty ("caps", caps); m_Caps = 0; ExtractCaps (caps); - } - + } + void RouterInfo::SetProperty (const std::string& key, const std::string& value) { m_Properties[key] = value; - } + } void RouterInfo::DeleteProperty (const std::string& key) { m_Properties.erase (key); } - std::string RouterInfo::GetProperty (const std::string& key) const + std::string RouterInfo::GetProperty (const std::string& key) const { auto it = m_Properties.find (key); if (it != m_Properties.end ()) return it->second; return ""; - } - + } + bool RouterInfo::IsNTCP (bool v4only) const { if (v4only) return m_SupportedTransports & eNTCPV4; else return m_SupportedTransports & (eNTCPV4 | eNTCPV6); - } + } bool RouterInfo::IsSSU (bool v4only) const { @@ -744,7 +744,7 @@ namespace data { return m_SupportedTransports & (eNTCPV4 | eSSUV4); } - + void RouterInfo::EnableV6 () { if (!IsV6 ()) @@ -756,13 +756,13 @@ namespace data if (!IsV4 ()) m_SupportedTransports |= eNTCPV4 | eSSUV4; } - - + + void RouterInfo::DisableV6 () - { + { if (IsV6 ()) - { - m_SupportedTransports &= ~(eNTCPV6 | eSSUV6); + { + m_SupportedTransports &= ~(eNTCPV6 | eSSUV6); for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) { auto addr = *it; @@ -770,15 +770,15 @@ namespace data it = m_Addresses->erase (it); else ++it; - } - } + } + } } void RouterInfo::DisableV4 () - { + { if (IsV4 ()) - { - m_SupportedTransports &= ~(eNTCPV4 | eSSUV4); + { + m_SupportedTransports &= ~(eNTCPV4 | eSSUV4); for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) { auto addr = *it; @@ -786,55 +786,55 @@ namespace data it = m_Addresses->erase (it); else ++it; - } - } + } + } } - - + + bool RouterInfo::UsesIntroducer () const { return m_Caps & Caps::eUnreachable; // non-reachable - } - + } + std::shared_ptr RouterInfo::GetNTCPAddress (bool v4only) const { return GetAddress (eTransportNTCP, v4only); - } + } - std::shared_ptr RouterInfo::GetSSUAddress (bool v4only) const + std::shared_ptr RouterInfo::GetSSUAddress (bool v4only) const { return GetAddress (eTransportSSU, v4only); - } + } - std::shared_ptr RouterInfo::GetSSUV6Address () const + std::shared_ptr RouterInfo::GetSSUV6Address () const { return GetAddress (eTransportSSU, false, true); - } - + } + std::shared_ptr RouterInfo::GetAddress (TransportStyle s, bool v4only, bool v6only) const { #if (BOOST_VERSION >= 105300) auto addresses = boost::atomic_load (&m_Addresses); -#else +#else auto addresses = m_Addresses; -#endif +#endif for (const auto& address : *addresses) { if (address->transportStyle == s) - { + { if ((!v4only || address->host.is_v4 ()) && (!v6only || address->host.is_v6 ())) return address; - } - } + } + } return nullptr; - } + } - std::shared_ptr RouterInfo::GetProfile () const + std::shared_ptr RouterInfo::GetProfile () const { if (!m_Profile) m_Profile = GetRouterProfile (GetIdentHash ()); return m_Profile; - } + } void RouterInfo::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const { diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 97c0f7b2..411c8095 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "Identity.h" #include "Profiling.h" @@ -17,15 +17,15 @@ namespace i2p namespace data { const char ROUTER_INFO_PROPERTY_LEASESETS[] = "netdb.knownLeaseSets"; - const char ROUTER_INFO_PROPERTY_ROUTERS[] = "netdb.knownRouters"; + const char ROUTER_INFO_PROPERTY_ROUTERS[] = "netdb.knownRouters"; const char ROUTER_INFO_PROPERTY_NETID[] = "netId"; - const char ROUTER_INFO_PROPERTY_FAMILY[] = "family"; + const char ROUTER_INFO_PROPERTY_FAMILY[] = "family"; const char ROUTER_INFO_PROPERTY_FAMILY_SIG[] = "family.sig"; - + const char CAPS_FLAG_FLOODFILL = 'f'; const char CAPS_FLAG_HIDDEN = 'H'; const char CAPS_FLAG_REACHABLE = 'R'; - const char CAPS_FLAG_UNREACHABLE = 'U'; + const char CAPS_FLAG_UNREACHABLE = 'U'; /* bandwidth flags */ const char CAPS_FLAG_LOW_BANDWIDTH1 = 'K'; /* < 12 KBps */ const char CAPS_FLAG_LOW_BANDWIDTH2 = 'L'; /* 12-48 KBps */ @@ -34,7 +34,7 @@ namespace data const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2000 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2000 KBps */ - + const char CAPS_FLAG_SSU_TESTING = 'B'; const char CAPS_FLAG_SSU_INTRODUCER = 'C'; @@ -44,13 +44,13 @@ namespace data public: enum SupportedTranports - { + { eNTCPV4 = 0x01, eNTCPV6 = 0x02, eSSUV4 = 0x04, eSSUV6 = 0x08 }; - + enum Caps { eFloodfill = 0x01, @@ -71,7 +71,7 @@ namespace data }; typedef Tag<32> IntroKey; // should be castable to MacKey and AESKey - struct Introducer + struct Introducer { Introducer (): iExp (0) {}; boost::asio::ip::address iHost; @@ -85,9 +85,9 @@ namespace data { int mtu; IntroKey key; // intro key for SSU - std::vector introducers; + std::vector introducers; }; - + struct Address { TransportStyle transportStyle; @@ -98,23 +98,23 @@ namespace data uint8_t cost; std::unique_ptr ssu; // not null for SSU - bool IsCompatible (const boost::asio::ip::address& other) const + bool IsCompatible (const boost::asio::ip::address& other) const { return (host.is_v4 () && other.is_v4 ()) || (host.is_v6 () && other.is_v6 ()); - } + } bool operator==(const Address& other) const { return transportStyle == other.transportStyle && host == other.host && port == other.port; - } + } bool operator!=(const Address& other) const { return !(*this == other); - } + } }; - typedef std::list > Addresses; + typedef std::list > Addresses; RouterInfo (); RouterInfo (const std::string& fullPath); @@ -122,7 +122,7 @@ namespace data RouterInfo& operator=(const RouterInfo& ) = default; RouterInfo (const uint8_t * buf, int len); ~RouterInfo (); - + std::shared_ptr GetRouterIdentity () const { return m_RouterIdentity; }; void SetRouterIdentity (std::shared_ptr identity); std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); }; @@ -131,7 +131,7 @@ namespace data std::shared_ptr GetNTCPAddress (bool v4only = true) const; std::shared_ptr GetSSUAddress (bool v4only = true) const; std::shared_ptr GetSSUV6Address () const; - + void AddNTCPAddress (const char * host, int port); void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0); bool AddIntroducer (const Introducer& introducer); @@ -156,37 +156,37 @@ namespace data bool IsPeerTesting () const { return m_Caps & eSSUTesting; }; bool IsHidden () const { return m_Caps & eHidden; }; bool IsHighBandwidth () const { return m_Caps & RouterInfo::eHighBandwidth; }; - bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; }; - - uint8_t GetCaps () const { return m_Caps; }; + bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; }; + + uint8_t GetCaps () const { return m_Caps; }; void SetCaps (uint8_t caps); void SetCaps (const char * caps); - void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; + void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; bool IsUnreachable () const { return m_IsUnreachable; }; const uint8_t * GetBuffer () const { return m_Buffer; }; const uint8_t * LoadBuffer (); // load if necessary - int GetBufferLen () const { return m_BufferLen; }; + int GetBufferLen () const { return m_BufferLen; }; void CreateBuffer (const PrivateKeys& privateKeys); bool IsUpdated () const { return m_IsUpdated; }; - void SetUpdated (bool updated) { m_IsUpdated = updated; }; + void SetUpdated (bool updated) { m_IsUpdated = updated; }; bool SaveToFile (const std::string& fullPath); std::shared_ptr GetProfile () const; void SaveProfile () { if (m_Profile) m_Profile->Save (GetIdentHash ()); }; - + void Update (const uint8_t * buf, int len); void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; }; - bool IsNewer (const uint8_t * buf, size_t len) const; + bool IsNewer (const uint8_t * buf, size_t len) const; /** return true if we are in a router family and the signature is valid */ bool IsFamily(const std::string & fam) const; - + // implements RoutingDestination std::shared_ptr GetIdentity () const { return m_RouterIdentity; }; - void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const; + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const; bool IsDestination () const { return false; }; @@ -201,7 +201,7 @@ namespace data void WriteString (const std::string& str, std::ostream& s) const; void ExtractCaps (const char * value); std::shared_ptr GetAddress (TransportStyle s, bool v4only, bool v6only = false) const; - void UpdateCapsProperty (); + void UpdateCapsProperty (); private: @@ -210,13 +210,13 @@ namespace data uint8_t * m_Buffer; size_t m_BufferLen; uint64_t m_Timestamp; - boost::shared_ptr m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9 + boost::shared_ptr m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9 std::map m_Properties; bool m_IsUpdated, m_IsUnreachable; uint8_t m_SupportedTransports, m_Caps; mutable std::shared_ptr m_Profile; - }; -} + }; +} } #endif diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp index d8688442..e7b62e48 100644 --- a/libi2pd/SSU.cpp +++ b/libi2pd/SSU.cpp @@ -13,32 +13,32 @@ namespace transport SSUServer::SSUServer (const boost::asio::ip::address & addr, int port): m_OnlyV6(true), m_IsRunning(false), - m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr), - m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), + m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr), + m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6), - m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint), - m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service), - m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service), - m_TerminationTimerV6 (m_ServiceV6) + m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint), + m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service), + m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service), + m_TerminationTimerV6 (m_ServiceV6) { OpenSocketV6 (); } - + SSUServer::SSUServer (int port): m_OnlyV6(false), m_IsRunning(false), m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr), - m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), + m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6), - m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port), - m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6), + m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port), + m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service), - m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6) + m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6) { OpenSocket (); if (context.SupportsV6 ()) OpenSocketV6 (); } - + SSUServer::~SSUServer () { } @@ -46,11 +46,11 @@ namespace transport void SSUServer::OpenSocket () { m_Socket.open (boost::asio::ip::udp::v4()); - m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE)); + m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE)); m_Socket.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE)); m_Socket.bind (m_Endpoint); } - + void SSUServer::OpenSocketV6 () { m_SocketV6.open (boost::asio::ip::udp::v6()); @@ -58,8 +58,8 @@ namespace transport m_SocketV6.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE)); m_SocketV6.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE)); m_SocketV6.bind (m_EndpointV6); - } - + } + void SSUServer::Start () { m_IsRunning = true; @@ -68,16 +68,16 @@ namespace transport m_ReceiversThread = new std::thread (std::bind (&SSUServer::RunReceivers, this)); m_Thread = new std::thread (std::bind (&SSUServer::Run, this)); m_ReceiversService.post (std::bind (&SSUServer::Receive, this)); - ScheduleTermination (); + ScheduleTermination (); } if (context.SupportsV6 ()) - { + { m_ReceiversThreadV6 = new std::thread (std::bind (&SSUServer::RunReceiversV6, this)); m_ThreadV6 = new std::thread (std::bind (&SSUServer::RunV6, this)); - m_ReceiversServiceV6.post (std::bind (&SSUServer::ReceiveV6, this)); - ScheduleTerminationV6 (); + m_ReceiversServiceV6.post (std::bind (&SSUServer::ReceiveV6, this)); + ScheduleTerminationV6 (); } - SchedulePeerTestsCleanupTimer (); + SchedulePeerTestsCleanupTimer (); ScheduleIntroducersUpdateTimer (); // wait for 30 seconds and decide if we need introducers } @@ -94,135 +94,135 @@ namespace transport m_ReceiversService.stop (); m_ReceiversServiceV6.stop (); if (m_ReceiversThread) - { - m_ReceiversThread->join (); + { + m_ReceiversThread->join (); delete m_ReceiversThread; m_ReceiversThread = nullptr; } if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = nullptr; } if (m_ReceiversThreadV6) - { - m_ReceiversThreadV6->join (); + { + m_ReceiversThreadV6->join (); delete m_ReceiversThreadV6; m_ReceiversThreadV6 = nullptr; } if (m_ThreadV6) - { - m_ThreadV6->join (); + { + m_ThreadV6->join (); delete m_ThreadV6; m_ThreadV6 = nullptr; } } - void SSUServer::Run () - { + void SSUServer::Run () + { while (m_IsRunning) { try - { + { m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "SSU: server runtime exception: ", ex.what ()); - } - } + } + } } - void SSUServer::RunV6 () - { + void SSUServer::RunV6 () + { while (m_IsRunning) { try - { + { m_ServiceV6.run (); } catch (std::exception& ex) { LogPrint (eLogError, "SSU: v6 server runtime exception: ", ex.what ()); - } - } - } + } + } + } - void SSUServer::RunReceivers () - { + void SSUServer::RunReceivers () + { while (m_IsRunning) { try - { + { m_ReceiversService.run (); } catch (std::exception& ex) { LogPrint (eLogError, "SSU: receivers runtime exception: ", ex.what ()); - } - } - } - - void SSUServer::RunReceiversV6 () - { + } + } + } + + void SSUServer::RunReceiversV6 () + { while (m_IsRunning) { try - { + { m_ReceiversServiceV6.run (); } catch (std::exception& ex) { LogPrint (eLogError, "SSU: v6 receivers runtime exception: ", ex.what ()); - } - } - } + } + } + } void SSUServer::AddRelay (uint32_t tag, std::shared_ptr relay) { m_Relays[tag] = relay; - } + } void SSUServer::RemoveRelay (uint32_t tag) { m_Relays.erase (tag); - } - + } + std::shared_ptr SSUServer::FindRelaySession (uint32_t tag) { auto it = m_Relays.find (tag); if (it != m_Relays.end ()) - { + { if (it->second->GetState () == eSessionStateEstablished) return it->second; else - m_Relays.erase (it); - } + m_Relays.erase (it); + } return nullptr; } void SSUServer::Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to) { - if (to.protocol () == boost::asio::ip::udp::v4()) + if (to.protocol () == boost::asio::ip::udp::v4()) m_Socket.send_to (boost::asio::buffer (buf, len), to); else m_SocketV6.send_to (boost::asio::buffer (buf, len), to); - } + } void SSUServer::Receive () { SSUPacket * packet = new SSUPacket (); m_Socket.async_receive_from (boost::asio::buffer (packet->buf, SSU_MTU_V4), packet->from, - std::bind (&SSUServer::HandleReceivedFrom, this, std::placeholders::_1, std::placeholders::_2, packet)); + std::bind (&SSUServer::HandleReceivedFrom, this, std::placeholders::_1, std::placeholders::_2, packet)); } void SSUServer::ReceiveV6 () { SSUPacket * packet = new SSUPacket (); m_SocketV6.async_receive_from (boost::asio::buffer (packet->buf, SSU_MTU_V6), packet->from, - std::bind (&SSUServer::HandleReceivedFromV6, this, std::placeholders::_1, std::placeholders::_2, packet)); - } + std::bind (&SSUServer::HandleReceivedFromV6, this, std::placeholders::_1, std::placeholders::_2, packet)); + } void SSUServer::HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet) { @@ -235,13 +235,13 @@ namespace transport boost::system::error_code ec; size_t moreBytes = m_Socket.available(ec); if (!ec) - { + { while (moreBytes && packets.size () < 25) { packet = new SSUPacket (); packet->len = m_Socket.receive_from (boost::asio::buffer (packet->buf, SSU_MTU_V4), packet->from, 0, ec); if (!ec) - { + { packets.push_back (packet); moreBytes = m_Socket.available(ec); if (ec) break; @@ -251,15 +251,15 @@ namespace transport LogPrint (eLogError, "SSU: receive_from error: ", ec.message ()); delete packet; break; - } + } } - } + } m_Service.post (std::bind (&SSUServer::HandleReceivedPackets, this, packets, &m_Sessions)); Receive (); } else - { + { delete packet; if (ecode != boost::asio::error::operation_aborted) { @@ -268,7 +268,7 @@ namespace transport OpenSocket (); Receive (); } - } + } } void SSUServer::HandleReceivedFromV6 (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet) @@ -298,15 +298,15 @@ namespace transport LogPrint (eLogError, "SSU: v6 receive_from error: ", ec.message ()); delete packet; break; - } + } } } - + m_ServiceV6.post (std::bind (&SSUServer::HandleReceivedPackets, this, packets, &m_SessionsV6)); ReceiveV6 (); } else - { + { delete packet; if (ecode != boost::asio::error::operation_aborted) { @@ -315,17 +315,17 @@ namespace transport OpenSocketV6 (); ReceiveV6 (); } - } + } } - void SSUServer::HandleReceivedPackets (std::vector packets, + void SSUServer::HandleReceivedPackets (std::vector packets, std::map > * sessions) { - std::shared_ptr session; + std::shared_ptr session; for (auto& packet: packets) { try - { + { if (!session || session->GetRemoteEndpoint () != packet->from) // we received packet for other session than previous { if (session) session->FlushData (); @@ -341,13 +341,13 @@ namespace transport } } session->ProcessNextMessage (packet->buf, packet->len, packet->from); - } + } catch (std::exception& ex) { LogPrint (eLogError, "SSU: HandleReceivedPackets ", ex.what ()); if (session) session->FlushData (); session = nullptr; - } + } delete packet; } if (session) session->FlushData (); @@ -362,21 +362,21 @@ namespace transport if (session || !context.SupportsV6 ()) return session; // try v6 - address = router->GetSSUV6Address (); + address = router->GetSSUV6Address (); if (!address) return nullptr; return FindSession (boost::asio::ip::udp::endpoint (address->host, address->port)); - } + } std::shared_ptr SSUServer::FindSession (const boost::asio::ip::udp::endpoint& e) const { - auto& sessions = e.address ().is_v6 () ? m_SessionsV6 : m_Sessions; + auto& sessions = e.address ().is_v6 () ? m_SessionsV6 : m_Sessions; auto it = sessions.find (e); if (it != sessions.end ()) return it->second; else return nullptr; } - + void SSUServer::CreateSession (std::shared_ptr router, bool peerTest, bool v4only) { auto address = router->GetSSUAddress (v4only || !context.SupportsV6 ()); @@ -385,7 +385,7 @@ namespace transport else LogPrint (eLogWarning, "SSU: Router ", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), " doesn't have SSU address"); } - + void SSUServer::CreateSession (std::shared_ptr router, const boost::asio::ip::address& addr, int port, bool peerTest) { @@ -403,27 +403,27 @@ namespace transport } void SSUServer::CreateDirectSession (std::shared_ptr router, boost::asio::ip::udp::endpoint remoteEndpoint, bool peerTest) - { - auto& sessions = remoteEndpoint.address ().is_v6 () ? m_SessionsV6 : m_Sessions; + { + auto& sessions = remoteEndpoint.address ().is_v6 () ? m_SessionsV6 : m_Sessions; auto it = sessions.find (remoteEndpoint); if (it != sessions.end ()) - { + { auto session = it->second; if (peerTest && session->GetState () == eSessionStateEstablished) session->SendPeerTest (); - } + } else { - // otherwise create new session + // otherwise create new session auto session = std::make_shared (*this, remoteEndpoint, router, peerTest); sessions[remoteEndpoint] = session; - // connect + // connect LogPrint (eLogDebug, "SSU: Creating new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ", remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ()); session->Connect (); } } - + void SSUServer::CreateSessionThroughIntroducer (std::shared_ptr router, bool peerTest) { if (router && router->UsesIntroducer ()) @@ -435,13 +435,13 @@ namespace transport auto it = m_Sessions.find (remoteEndpoint); // check if session is presented already if (it != m_Sessions.end ()) - { + { auto session = it->second; if (peerTest && session->GetState () == eSessionStateEstablished) session->SendPeerTest (); - return; - } - // create new session + return; + } + // create new session int numIntroducers = address->ssu->introducers.size (); if (numIntroducers > 0) { @@ -455,52 +455,52 @@ namespace transport if (intr->iExp > 0 && ts > intr->iExp) continue; // skip expired introducer boost::asio::ip::udp::endpoint ep (intr->iHost, intr->iPort); if (ep.address ().is_v4 ()) // ipv4 only - { + { if (!introducer) introducer = intr; // we pick first one for now - it = m_Sessions.find (ep); + it = m_Sessions.find (ep); if (it != m_Sessions.end ()) { introducerSession = it->second; - break; - } + break; + } } } if (!introducer) { LogPrint (eLogWarning, "SSU: Can't connect to unreachable router and no ipv4 non-expired introducers presented"); return; - } + } - if (introducerSession) // session found + if (introducerSession) // session found LogPrint (eLogWarning, "SSU: Session to introducer already exists"); else // create new { LogPrint (eLogDebug, "SSU: Creating new session to introducer ", introducer->iHost); boost::asio::ip::udp::endpoint introducerEndpoint (introducer->iHost, introducer->iPort); introducerSession = std::make_shared (*this, introducerEndpoint, router); - m_Sessions[introducerEndpoint] = introducerSession; + m_Sessions[introducerEndpoint] = introducerSession; } -#if BOOST_VERSION >= 104900 +#if BOOST_VERSION >= 104900 if (!address->host.is_unspecified () && address->port) #endif { - // create session + // create session auto session = std::make_shared (*this, remoteEndpoint, router, peerTest); m_Sessions[remoteEndpoint] = session; // introduce LogPrint (eLogInfo, "SSU: Introduce new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] through introducer ", introducer->iHost, ":", introducer->iPort); - session->WaitForIntroduction (); + session->WaitForIntroduction (); if (i2p::context.GetRouterInfo ().UsesIntroducer ()) // if we are unreachable { uint8_t buf[1]; Send (buf, 0, remoteEndpoint); // send HolePunch - } + } } introducerSession->Introduce (*introducer, router); } - else + else LogPrint (eLogWarning, "SSU: Can't connect to unreachable router and no introducers present"); } else @@ -518,8 +518,8 @@ namespace transport m_SessionsV6.erase (ep); else m_Sessions.erase (ep); - } - } + } + } void SSUServer::DeleteAllSessions () { @@ -543,15 +543,15 @@ namespace transport auto ind = rand () % filteredSessions.size (); return filteredSessions[ind]; } - return nullptr; + return nullptr; } std::shared_ptr SSUServer::GetRandomEstablishedV4Session (std::shared_ptr excluded) // v4 only { return GetRandomV4Session ( - [excluded](std::shared_ptr session)->bool - { - return session->GetState () == eSessionStateEstablished && session != excluded; + [excluded](std::shared_ptr session)->bool + { + return session->GetState () == eSessionStateEstablished && session != excluded; } ); } @@ -567,15 +567,15 @@ namespace transport auto ind = rand () % filteredSessions.size (); return filteredSessions[ind]; } - return nullptr; + return nullptr; } std::shared_ptr SSUServer::GetRandomEstablishedV6Session (std::shared_ptr excluded) // v6 only { return GetRandomV6Session ( - [excluded](std::shared_ptr session)->bool - { - return session->GetState () == eSessionStateEstablished && session != excluded; + [excluded](std::shared_ptr session)->bool + { + return session->GetState () == eSessionStateEstablished && session != excluded; } ); } @@ -587,18 +587,18 @@ namespace transport for (int i = 0; i < maxNumIntroducers; i++) { auto session = GetRandomV4Session ( - [&ret, ts](std::shared_ptr session)->bool - { + [&ret, ts](std::shared_ptr session)->bool + { return session->GetRelayTag () && !ret.count (session.get ()) && session->GetState () == eSessionStateEstablished && - ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION; + ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION; } - ); + ); if (session) { ret.insert (session.get ()); break; - } + } } return ret; } @@ -607,7 +607,7 @@ namespace transport { m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL)); m_IntroducersUpdateTimer.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer, - this, std::placeholders::_1)); + this, std::placeholders::_1)); } void SSUServer::HandleIntroducersUpdateTimer (const boost::system::error_code& ecode) @@ -620,7 +620,7 @@ namespace transport // we still don't know if we need introducers ScheduleIntroducersUpdateTimer (); return; - } + } if (i2p::context.GetStatus () == eRouterStatusOK) return; // we don't need introducers anymore // we are firewalled if (!i2p::context.IsUnreachable ()) i2p::context.SetUnreachable (); @@ -628,7 +628,7 @@ namespace transport size_t numIntroducers = 0; uint32_t ts = i2p::util::GetSecondsSinceEpoch (); for (const auto& it : m_Introducers) - { + { auto session = FindSession (it); if (session && ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION) { @@ -636,7 +636,7 @@ namespace transport newList.push_back (it); numIntroducers++; } - else + else i2p::context.RemoveIntroducer (it); } @@ -658,16 +658,16 @@ namespace transport if (newList.size () >= SSU_MAX_NUM_INTRODUCERS) break; } } - } + } m_Introducers = newList; if (m_Introducers.size () < SSU_MAX_NUM_INTRODUCERS) { auto introducer = i2p::data::netdb.GetRandomIntroducer (); if (introducer) CreateSession (introducer); - } + } ScheduleIntroducersUpdateTimer (); - } + } } void SSUServer::NewPeerTest (uint32_t nonce, PeerTestParticipant role, std::shared_ptr session) @@ -682,7 +682,7 @@ namespace transport return it->second.role; else return ePeerTestParticipantUnknown; - } + } std::shared_ptr SSUServer::GetPeerTestSession (uint32_t nonce) { @@ -698,26 +698,26 @@ namespace transport auto it = m_PeerTests.find (nonce); if (it != m_PeerTests.end ()) it->second.role = role; - } - + } + void SSUServer::RemovePeerTest (uint32_t nonce) { m_PeerTests.erase (nonce); - } + } void SSUServer::SchedulePeerTestsCleanupTimer () { m_PeerTestsCleanupTimer.expires_from_now (boost::posix_time::seconds(SSU_PEER_TEST_TIMEOUT)); m_PeerTestsCleanupTimer.async_wait (std::bind (&SSUServer::HandlePeerTestsCleanupTimer, - this, std::placeholders::_1)); + this, std::placeholders::_1)); } void SSUServer::HandlePeerTestsCleanupTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) { - int numDeleted = 0; - uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); + int numDeleted = 0; + uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it = m_PeerTests.begin (); it != m_PeerTests.end ();) { if (ts > it->second.creationTime + SSU_PEER_TEST_TIMEOUT*1000LL) @@ -744,21 +744,21 @@ namespace transport void SSUServer::HandleTerminationTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { auto ts = i2p::util::GetSecondsSinceEpoch (); for (auto& it: m_Sessions) if (it.second->IsTerminationTimeoutExpired (ts)) { auto session = it.second; - m_Service.post ([session] - { + m_Service.post ([session] + { LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); session->Failed (); - }); + }); } - ScheduleTermination (); - } - } + ScheduleTermination (); + } + } void SSUServer::ScheduleTerminationV6 () { @@ -770,21 +770,21 @@ namespace transport void SSUServer::HandleTerminationTimerV6 (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { auto ts = i2p::util::GetSecondsSinceEpoch (); for (auto& it: m_SessionsV6) if (it.second->IsTerminationTimeoutExpired (ts)) { auto session = it.second; - m_ServiceV6.post ([session] - { + m_ServiceV6.post ([session] + { LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); session->Failed (); - }); + }); } - ScheduleTerminationV6 (); - } - } + ScheduleTerminationV6 (); + } + } } } diff --git a/libi2pd/SSU.h b/libi2pd/SSU.h index ee49c6a4..10e5ec06 100644 --- a/libi2pd/SSU.h +++ b/libi2pd/SSU.h @@ -20,8 +20,8 @@ namespace i2p { namespace transport { - const int SSU_KEEP_ALIVE_INTERVAL = 30; // 30 seconds - const int SSU_PEER_TEST_TIMEOUT = 60; // 60 seconds + const int SSU_KEEP_ALIVE_INTERVAL = 30; // 30 seconds + const int SSU_PEER_TEST_TIMEOUT = 60; // 60 seconds const int SSU_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds const size_t SSU_MAX_NUM_INTRODUCERS = 3; @@ -33,8 +33,8 @@ namespace transport i2p::crypto::AESAlignedBuffer buf; // max MTU + iv + size boost::asio::ip::udp::endpoint from; size_t len; - }; - + }; + class SSUServer { public: @@ -45,7 +45,7 @@ namespace transport void Start (); void Stop (); void CreateSession (std::shared_ptr router, bool peerTest = false, bool v4only = false); - void CreateSession (std::shared_ptr router, + void CreateSession (std::shared_ptr router, const boost::asio::ip::address& addr, int port, bool peerTest = false); void CreateDirectSession (std::shared_ptr router, boost::asio::ip::udp::endpoint remoteEndpoint, bool peerTest); std::shared_ptr FindSession (std::shared_ptr router) const; @@ -53,11 +53,11 @@ namespace transport std::shared_ptr GetRandomEstablishedV4Session (std::shared_ptr excluded); std::shared_ptr GetRandomEstablishedV6Session (std::shared_ptr excluded); void DeleteSession (std::shared_ptr session); - void DeleteAllSessions (); + void DeleteAllSessions (); boost::asio::io_service& GetService () { return m_Service; }; boost::asio::io_service& GetServiceV6 () { return m_ServiceV6; }; - const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; }; + const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; }; void Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); void AddRelay (uint32_t tag, std::shared_ptr relay); void RemoveRelay (uint32_t tag); @@ -68,7 +68,7 @@ namespace transport std::shared_ptr GetPeerTestSession (uint32_t nonce); void UpdatePeerTest (uint32_t nonce, PeerTestParticipant role); void RemovePeerTest (uint32_t nonce); - + private: void OpenSocket (); @@ -84,13 +84,13 @@ namespace transport void HandleReceivedPackets (std::vector packets, std::map >* sessions); - void CreateSessionThroughIntroducer (std::shared_ptr router, bool peerTest = false); + void CreateSessionThroughIntroducer (std::shared_ptr router, bool peerTest = false); template std::shared_ptr GetRandomV4Session (Filter filter); template - std::shared_ptr GetRandomV6Session (Filter filter); + std::shared_ptr GetRandomV6Session (Filter filter); - std::set FindIntroducers (int maxNumIntroducers); + std::set FindIntroducers (int maxNumIntroducers); void ScheduleIntroducersUpdateTimer (); void HandleIntroducersUpdateTimer (const boost::system::error_code& ecode); @@ -111,10 +111,10 @@ namespace transport PeerTestParticipant role; std::shared_ptr session; // for Bob to Alice }; - - bool m_OnlyV6; + + bool m_OnlyV6; bool m_IsRunning; - std::thread * m_Thread, * m_ThreadV6, * m_ReceiversThread, * m_ReceiversThreadV6; + std::thread * m_Thread, * m_ThreadV6, * m_ReceiversThread, * m_ReceiversThreadV6; boost::asio::io_service m_Service, m_ServiceV6, m_ReceiversService, m_ReceiversServiceV6; boost::asio::io_service::work m_Work, m_WorkV6, m_ReceiversWork, m_ReceiversWorkV6; boost::asio::ip::udp::endpoint m_Endpoint, m_EndpointV6; @@ -125,7 +125,7 @@ namespace transport std::map > m_Sessions, m_SessionsV6; std::map > m_Relays; // we are introducer std::map m_PeerTests; // nonce -> creation time in milliseconds - + public: // for HTTP only const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index 67394d98..dcc28325 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -28,9 +28,9 @@ namespace transport } SSUData::SSUData (SSUSession& session): - m_Session (session), m_ResendTimer (session.GetService ()), - m_IncompleteMessagesCleanupTimer (session.GetService ()), - m_MaxPacketSize (session.IsV6 () ? SSU_V6_MAX_PACKET_SIZE : SSU_V4_MAX_PACKET_SIZE), + m_Session (session), m_ResendTimer (session.GetService ()), + m_IncompleteMessagesCleanupTimer (session.GetService ()), + m_MaxPacketSize (session.IsV6 () ? SSU_V6_MAX_PACKET_SIZE : SSU_V4_MAX_PACKET_SIZE), m_PacketSize (m_MaxPacketSize), m_LastMessageReceivedTime (0) { } @@ -42,8 +42,8 @@ namespace transport void SSUData::Start () { ScheduleIncompleteMessagesCleanup (); - } - + } + void SSUData::Stop () { m_ResendTimer.cancel (); @@ -51,8 +51,8 @@ namespace transport m_IncompleteMessages.clear (); m_SentMessages.clear (); m_ReceivedMessages.clear (); - } - + } + void SSUData::AdjustPacketSize (std::shared_ptr remoteRouter) { if (!remoteRouter) return; @@ -72,11 +72,11 @@ namespace transport LogPrint (eLogDebug, "SSU: MTU=", ssuAddress->ssu->mtu, " packet size=", m_PacketSize); } else - { + { LogPrint (eLogWarning, "SSU: Unexpected MTU ", ssuAddress->ssu->mtu); m_PacketSize = m_MaxPacketSize; - } - } + } + } } void SSUData::UpdatePacketSize (const i2p::data::IdentHash& remoteIdent) @@ -91,11 +91,11 @@ namespace transport auto it = m_SentMessages.find (msgID); if (it != m_SentMessages.end ()) { - m_SentMessages.erase (it); + m_SentMessages.erase (it); if (m_SentMessages.empty ()) m_ResendTimer.cancel (); } - } + } void SSUData::ProcessAcks (uint8_t *& buf, uint8_t flag) { @@ -117,7 +117,7 @@ namespace transport { uint32_t msgID = bufbe32toh (buf); buf += 4; // msgID - auto it = m_SentMessages.find (msgID); + auto it = m_SentMessages.find (msgID); // process individual Ack bitfields bool isNonLast = false; int fragment = 0; @@ -127,26 +127,26 @@ namespace transport isNonLast = bitfield & 0x80; bitfield &= 0x7F; // clear MSB if (bitfield && it != m_SentMessages.end ()) - { - int numSentFragments = it->second->fragments.size (); + { + int numSentFragments = it->second->fragments.size (); // process bits uint8_t mask = 0x01; for (int j = 0; j < 7; j++) - { + { if (bitfield & mask) { if (fragment < numSentFragments) it->second->fragments[fragment].reset (nullptr); - } + } fragment++; mask <<= 1; } - } + } buf++; } - while (isNonLast); - } - } + while (isNonLast); + } + } } void SSUData::ProcessFragments (uint8_t * buf) @@ -154,7 +154,7 @@ namespace transport uint8_t numFragments = *buf; // number of fragments buf++; for (int i = 0; i < numFragments; i++) - { + { uint32_t msgID = bufbe32toh (buf); // message ID buf += 4; uint8_t frag[4] = {0}; @@ -162,8 +162,8 @@ namespace transport buf += 3; uint32_t fragmentInfo = bufbe32toh (frag); // fragment info uint16_t fragmentSize = fragmentInfo & 0x3FFF; // bits 0 - 13 - bool isLast = fragmentInfo & 0x010000; // bit 16 - uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17 + bool isLast = fragmentInfo & 0x010000; // bit 16 + uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17 if (fragmentSize >= SSU_V4_MAX_PACKET_SIZE) { LogPrint (eLogError, "SSU: Fragment size ", fragmentSize, " exceeds max SSU packet size"); @@ -172,12 +172,12 @@ namespace transport // find message with msgID auto it = m_IncompleteMessages.find (msgID); - if (it == m_IncompleteMessages.end ()) + if (it == m_IncompleteMessages.end ()) { // create new message auto msg = NewI2NPShortMessage (); msg->len -= I2NP_SHORT_HEADER_SIZE; - it = m_IncompleteMessages.insert (std::make_pair (msgID, + it = m_IncompleteMessages.insert (std::make_pair (msgID, std::unique_ptr(new IncompleteMessage (msg)))).first; } std::unique_ptr& incompleteMessage = it->second; @@ -204,10 +204,10 @@ namespace transport } if (isLast) LogPrint (eLogDebug, "SSU: Message ", msgID, " complete"); - } - } + } + } else - { + { if (fragmentNum < incompleteMessage->nextFragmentNum) // duplicate fragment LogPrint (eLogWarning, "SSU: Duplicate fragment ", (int)fragmentNum, " of message ", msgID, ", ignored"); @@ -218,28 +218,28 @@ namespace transport auto savedFragment = new Fragment (fragmentNum, buf, fragmentSize, isLast); if (incompleteMessage->savedFragments.insert (std::unique_ptr(savedFragment)).second) incompleteMessage->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch (); - else + else LogPrint (eLogWarning, "SSU: Fragment ", (int)fragmentNum, " of message ", msgID, " already saved"); } isLast = false; - } + } if (isLast) { // delete incomplete message auto msg = incompleteMessage->msg; incompleteMessage->msg = nullptr; - m_IncompleteMessages.erase (msgID); + m_IncompleteMessages.erase (msgID); // process message SendMsgAck (msgID); msg->FromSSU (msgID); if (m_Session.GetState () == eSessionStateEstablished) { if (!m_ReceivedMessages.count (msgID)) - { + { m_ReceivedMessages.insert (msgID); m_LastMessageReceivedTime = i2p::util::GetSecondsSinceEpoch (); - if (!msg->IsExpired ()) + if (!msg->IsExpired ()) { #ifdef WITH_EVENTS QueueIntEvent("transport.recvmsg", m_Session.GetIdentHashBase64(), 1); @@ -248,10 +248,10 @@ namespace transport } else LogPrint (eLogDebug, "SSU: message expired"); - } + } else LogPrint (eLogWarning, "SSU: Message ", msgID, " already received"); - } + } else { // we expect DeliveryStatus @@ -259,22 +259,22 @@ namespace transport { LogPrint (eLogDebug, "SSU: session established"); m_Session.Established (); - } + } else LogPrint (eLogError, "SSU: unexpected message ", (int)msg->GetTypeID ()); - } - } + } + } else - SendFragmentAck (msgID, fragmentNum); + SendFragmentAck (msgID, fragmentNum); buf += fragmentSize; - } + } } void SSUData::FlushReceivedMessage () { m_Handler.Flush (); - } - + } + void SSUData::ProcessMessage (uint8_t * buf, size_t len) { //uint8_t * start = buf; @@ -303,25 +303,25 @@ namespace transport { LogPrint (eLogWarning, "SSU: message ", msgID, " already sent"); return; - } + } if (m_SentMessages.empty ()) // schedule resend at first message only ScheduleResend (); - - auto ret = m_SentMessages.insert (std::make_pair (msgID, std::unique_ptr(new SentMessage))); + + auto ret = m_SentMessages.insert (std::make_pair (msgID, std::unique_ptr(new SentMessage))); std::unique_ptr& sentMessage = ret.first->second; - if (ret.second) + if (ret.second) { sentMessage->nextResendTime = i2p::util::GetSecondsSinceEpoch () + RESEND_INTERVAL; sentMessage->numResends = 0; - } + } auto& fragments = sentMessage->fragments; - size_t payloadSize = m_PacketSize - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3) + size_t payloadSize = m_PacketSize - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3) size_t len = msg->GetLength (); uint8_t * msgBuf = msg->GetSSUHeader (); uint32_t fragmentNum = 0; while (len > 0) - { + { Fragment * fragment = new Fragment; fragment->fragmentNum = fragmentNum; uint8_t * buf = fragment->buf; @@ -337,39 +337,39 @@ namespace transport uint32_t fragmentInfo = (fragmentNum << 17); if (isLast) fragmentInfo |= 0x010000; - + fragmentInfo |= size; fragmentInfo = htobe32 (fragmentInfo); memcpy (payload, (uint8_t *)(&fragmentInfo) + 1, 3); payload += 3; memcpy (payload, msgBuf, size); - + size += payload - buf; if (size & 0x0F) // make sure 16 bytes boundary size = ((size >> 4) + 1) << 4; // (/16 + 1)*16 - fragment->len = size; + fragment->len = size; fragments.push_back (std::unique_ptr (fragment)); - + // encrypt message with session key m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size); try - { + { m_Session.Send (buf, size); } catch (boost::system::system_error& ec) { LogPrint (eLogWarning, "SSU: Can't send data fragment ", ec.what ()); - } + } if (!isLast) - { + { len -= payloadSize; msgBuf += payloadSize; - } + } else len = 0; fragmentNum++; - } - } + } + } void SSUData::SendMsgAck (uint32_t msgID) { @@ -398,27 +398,27 @@ namespace transport uint8_t buf[64 + 18] = {0}; uint8_t * payload = buf + sizeof (SSUHeader); *payload = DATA_FLAG_ACK_BITFIELDS_INCLUDED; // flag - payload++; + payload++; *payload = 1; // number of ACK bitfields payload++; // one ack - *(uint32_t *)(payload) = htobe32 (msgID); // msgID + *(uint32_t *)(payload) = htobe32 (msgID); // msgID payload += 4; div_t d = div (fragmentNum, 7); memset (payload, 0x80, d.quot); // 0x80 means non-last - payload += d.quot; + payload += d.quot; *payload = 0x01 << d.rem; // set corresponding bit payload++; *payload = 0; // number of fragments - size_t len = d.quot < 4 ? 48 : 64; // 48 = 37 + 7 + 4 (3+1) + size_t len = d.quot < 4 ? 48 : 64; // 48 = 37 + 7 + 4 (3+1) // encrypt message with session key m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, len); m_Session.Send (buf, len); - } + } void SSUData::ScheduleResend() - { + { m_ResendTimer.cancel (); m_ResendTimer.expires_from_now (boost::posix_time::seconds(RESEND_INTERVAL)); auto s = m_Session.shared_from_this(); @@ -435,7 +435,7 @@ namespace transport for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();) { if (ts >= it->second->nextResendTime) - { + { if (it->second->numResends < MAX_NUM_RESENDS) { for (auto& f: it->second->fragments) @@ -455,13 +455,13 @@ namespace transport it->second->numResends++; it->second->nextResendTime += it->second->numResends*RESEND_INTERVAL; ++it; - } + } else { LogPrint (eLogInfo, "SSU: message has not been ACKed after ", MAX_NUM_RESENDS, " attempts, deleted"); it = m_SentMessages.erase (it); - } - } + } + } else ++it; } @@ -472,9 +472,9 @@ namespace transport { LogPrint (eLogError, "SSU: resend window exceeds max size. Session terminated"); m_Session.Close (); - } - } - } + } + } + } void SSUData::ScheduleIncompleteMessagesCleanup () { @@ -484,7 +484,7 @@ namespace transport m_IncompleteMessagesCleanupTimer.async_wait ([s](const boost::system::error_code& ecode) { s->m_Data.HandleIncompleteMessagesCleanupTimer (ecode); }); } - + void SSUData::HandleIncompleteMessagesCleanupTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) @@ -496,18 +496,18 @@ namespace transport { LogPrint (eLogWarning, "SSU: message ", it->first, " was not completed in ", INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT, " seconds, deleted"); it = m_IncompleteMessages.erase (it); - } + } else ++it; - } + } // decay if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES || i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL) m_ReceivedMessages.clear (); - + ScheduleIncompleteMessagesCleanup (); - } - } + } + } } } diff --git a/libi2pd/SSUData.h b/libi2pd/SSUData.h index 8f625fe1..0ef31b10 100644 --- a/libi2pd/SSUData.h +++ b/libi2pd/SSUData.h @@ -24,7 +24,7 @@ namespace transport const size_t SSU_MTU_V6 = 1488; #endif const size_t IPV4_HEADER_SIZE = 20; - const size_t IPV6_HEADER_SIZE = 40; + const size_t IPV6_HEADER_SIZE = 40; const size_t UDP_HEADER_SIZE = 8; const size_t SSU_V4_MAX_PACKET_SIZE = SSU_MTU_V4 - IPV4_HEADER_SIZE - UDP_HEADER_SIZE; // 1456 const size_t SSU_V6_MAX_PACKET_SIZE = SSU_MTU_V6 - IPV6_HEADER_SIZE - UDP_HEADER_SIZE; // 1440 @@ -40,7 +40,7 @@ namespace transport const uint8_t DATA_FLAG_REQUEST_PREVIOUS_ACKS = 0x08; const uint8_t DATA_FLAG_EXPLICIT_CONGESTION_NOTIFICATION = 0x10; const uint8_t DATA_FLAG_ACK_BITFIELDS_INCLUDED = 0x40; - const uint8_t DATA_FLAG_EXPLICIT_ACKS_INCLUDED = 0x80; + const uint8_t DATA_FLAG_EXPLICIT_ACKS_INCLUDED = 0x80; struct Fragment { @@ -50,27 +50,27 @@ namespace transport uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18]; // use biggest Fragment () = default; - Fragment (int n, const uint8_t * b, int l, bool last): - fragmentNum (n), len (l), isLast (last) { memcpy (buf, b, len); }; - }; + Fragment (int n, const uint8_t * b, int l, bool last): + fragmentNum (n), len (l), isLast (last) { memcpy (buf, b, len); }; + }; struct FragmentCmp { bool operator() (const std::unique_ptr& f1, const std::unique_ptr& f2) const - { - return f1->fragmentNum < f2->fragmentNum; + { + return f1->fragmentNum < f2->fragmentNum; }; - }; - + }; + struct IncompleteMessage { std::shared_ptr msg; - int nextFragmentNum; + int nextFragmentNum; uint32_t lastFragmentInsertTime; // in seconds std::set, FragmentCmp> savedFragments; - + IncompleteMessage (std::shared_ptr m): msg (m), nextFragmentNum (0), lastFragmentInsertTime (0) {}; - void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize); + void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize); }; struct SentMessage @@ -78,24 +78,24 @@ namespace transport std::vector > fragments; uint32_t nextResendTime; // in seconds int numResends; - }; - + }; + class SSUSession; class SSUData { public: - SSUData (SSUSession& session); + SSUData (SSUSession& session); ~SSUData (); void Start (); - void Stop (); - + void Stop (); + void ProcessMessage (uint8_t * buf, size_t len); void FlushReceivedMessage (); void Send (std::shared_ptr msg); - void AdjustPacketSize (std::shared_ptr remoteRouter); + void AdjustPacketSize (std::shared_ptr remoteRouter); void UpdatePacketSize (const i2p::data::IdentHash& remoteIdent); private: @@ -104,16 +104,16 @@ namespace transport void SendFragmentAck (uint32_t msgID, int fragmentNum); void ProcessAcks (uint8_t *& buf, uint8_t flag); void ProcessFragments (uint8_t * buf); - void ProcessSentMessageAck (uint32_t msgID); + void ProcessSentMessageAck (uint32_t msgID); void ScheduleResend (); - void HandleResendTimer (const boost::system::error_code& ecode); + void HandleResendTimer (const boost::system::error_code& ecode); void ScheduleIncompleteMessagesCleanup (); - void HandleIncompleteMessagesCleanupTimer (const boost::system::error_code& ecode); - - - private: + void HandleIncompleteMessagesCleanupTimer (const boost::system::error_code& ecode); + + + private: SSUSession& m_Session; std::map > m_IncompleteMessages; @@ -123,7 +123,7 @@ namespace transport int m_MaxPacketSize, m_PacketSize; i2p::I2NPMessagesHandler m_Handler; uint32_t m_LastMessageReceivedTime; // in second - }; + }; } } diff --git a/libi2pd/SSUSession.cpp b/libi2pd/SSUSession.cpp index b7493814..2a8cd2d5 100644 --- a/libi2pd/SSUSession.cpp +++ b/libi2pd/SSUSession.cpp @@ -13,12 +13,12 @@ namespace i2p namespace transport { SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, - std::shared_ptr router, bool peerTest ): - TransportSession (router, SSU_TERMINATION_TIMEOUT), - m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_ConnectTimer (GetService ()), - m_IsPeerTest (peerTest),m_State (eSessionStateUnknown), m_IsSessionKey (false), + std::shared_ptr router, bool peerTest ): + TransportSession (router, SSU_TERMINATION_TIMEOUT), + m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_ConnectTimer (GetService ()), + m_IsPeerTest (peerTest),m_State (eSessionStateUnknown), m_IsSessionKey (false), m_RelayTag (0), m_SentRelayTag (0), m_Data (*this), m_IsDataReceived (false) - { + { if (router) { // we are client @@ -36,14 +36,14 @@ namespace transport } SSUSession::~SSUSession () - { - } - - boost::asio::io_service& SSUSession::GetService () - { - return IsV6 () ? m_Server.GetServiceV6 () : m_Server.GetService (); + { } - + + boost::asio::io_service& SSUSession::GetService () + { + return IsV6 () ? m_Server.GetServiceV6 () : m_Server.GetService (); + } + void SSUSession::CreateAESandMacKey (const uint8_t * pubKey) { uint8_t sharedKey[256]; @@ -55,14 +55,14 @@ namespace transport sessionKey[0] = 0; memcpy (sessionKey + 1, sharedKey, 31); memcpy (macKey, sharedKey + 31, 32); - } + } else if (sharedKey[0]) { memcpy (sessionKey, sharedKey, 32); memcpy (macKey, sharedKey + 32, 32); - } + } else - { + { // find first non-zero byte uint8_t * nonZero = sharedKey + 1; while (!*nonZero) @@ -72,16 +72,16 @@ namespace transport { LogPrint (eLogWarning, "SSU: first 32 bytes of shared key is all zeros. Ignored"); return; - } + } } - + memcpy (sessionKey, nonZero, 32); SHA256(nonZero, 64 - (nonZero - sharedKey), macKey); } m_IsSessionKey = true; m_SessionKeyEncryption.SetKey (m_SessionKey); m_SessionKeyDecryption.SetKey (m_SessionKey); - } + } void SSUSession::ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { @@ -96,40 +96,40 @@ namespace transport } else { - if (!len) return; // ignore zero-length packets + if (!len) return; // ignore zero-length packets if (m_State == eSessionStateEstablished) - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + if (m_IsSessionKey && Validate (buf, len, m_MacKey)) // try session key first - DecryptSessionKey (buf, len); - else + DecryptSessionKey (buf, len); + else { - if (m_State == eSessionStateEstablished) Reset (); // new session key required + if (m_State == eSessionStateEstablished) Reset (); // new session key required // try intro key depending on side if (Validate (buf, len, m_IntroKey)) Decrypt (buf, len, m_IntroKey); else - { + { // try own intro key auto address = i2p::context.GetRouterInfo ().GetSSUAddress (false); if (!address) { LogPrint (eLogInfo, "SSU is not supported"); return; - } + } if (Validate (buf, len, address->ssu->key)) Decrypt (buf, len, address->ssu->key); else { LogPrint (eLogWarning, "SSU: MAC verification failed ", len, " bytes from ", senderEndpoint); - m_Server.DeleteSession (shared_from_this ()); + m_Server.DeleteSession (shared_from_this ()); return; - } - } - } + } + } + } // successfully decrypted ProcessMessage (buf, len, senderEndpoint); - } + } } size_t SSUSession::GetSSUHeaderSize (const uint8_t * buf) const @@ -158,14 +158,14 @@ namespace transport ProcessData (buf + headerSize, len - headerSize); break; case PAYLOAD_TYPE_SESSION_REQUEST: - ProcessSessionRequest (buf, len, senderEndpoint); // buf with header + ProcessSessionRequest (buf, len, senderEndpoint); // buf with header break; case PAYLOAD_TYPE_SESSION_CREATED: ProcessSessionCreated (buf, len); // buf with header break; case PAYLOAD_TYPE_SESSION_CONFIRMED: ProcessSessionConfirmed (buf, len); // buf with header - break; + break; case PAYLOAD_TYPE_PEER_TEST: LogPrint (eLogDebug, "SSU: peer test received"); ProcessPeerTest (buf + headerSize, len - headerSize, senderEndpoint); @@ -173,9 +173,9 @@ namespace transport case PAYLOAD_TYPE_SESSION_DESTROYED: { LogPrint (eLogDebug, "SSU: session destroy received"); - m_Server.DeleteSession (shared_from_this ()); + m_Server.DeleteSession (shared_from_this ()); break; - } + } case PAYLOAD_TYPE_RELAY_RESPONSE: ProcessRelayResponse (buf + headerSize, len - headerSize); if (m_State != eSessionStateEstablished) @@ -197,7 +197,7 @@ namespace transport void SSUSession::ProcessSessionRequest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { LogPrint (eLogDebug, "SSU message: session request"); - bool sendRelayTag = true; + bool sendRelayTag = true; auto headerSize = sizeof (SSUHeader); if (((SSUHeader *)buf)->IsExtendedOptions ()) { @@ -206,14 +206,14 @@ namespace transport if (extendedOptionsLen >= 3) // options are presented { uint16_t flags = bufbe16toh (buf + headerSize); - sendRelayTag = flags & EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG; + sendRelayTag = flags & EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG; } headerSize += extendedOptionsLen; - } + } if (headerSize >= len) { LogPrint (eLogError, "Session reaquest header size ", headerSize, " exceeds packet length ", len); - return; + return; } m_RemoteEndpoint = senderEndpoint; if (!m_DHKeysPair) @@ -232,14 +232,14 @@ namespace transport LogPrint (eLogDebug, "SSU message: session created"); m_ConnectTimer.cancel (); // connect timer - SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time - auto headerSize = GetSSUHeaderSize (buf); + SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time + auto headerSize = GetSSUHeaderSize (buf); if (headerSize >= len) { LogPrint (eLogError, "Session created header size ", headerSize, " exceeds packet length ", len); - return; - } - uint8_t * payload = buf + headerSize; + return; + } + uint8_t * payload = buf + headerSize; uint8_t * y = payload; CreateAESandMacKey (y); s.Insert (m_DHKeysPair->GetPublicKey (), 256); // x @@ -250,18 +250,18 @@ namespace transport uint8_t * ourAddress = payload; boost::asio::ip::address ourIP; if (addressSize == 4) // v4 - { + { boost::asio::ip::address_v4::bytes_type bytes; memcpy (bytes.data (), ourAddress, 4); ourIP = boost::asio::ip::address_v4 (bytes); - } + } else // v6 { boost::asio::ip::address_v6::bytes_type bytes; memcpy (bytes.data (), ourAddress, 16); ourIP = boost::asio::ip::address_v6 (bytes); - } - s.Insert (ourAddress, addressSize); // our IP + } + s.Insert (ourAddress, addressSize); // our IP payload += addressSize; // address uint16_t ourPort = bufbe16toh (payload); s.Insert (payload, 2); // our port @@ -271,19 +271,19 @@ namespace transport else s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP v6 s.Insert (htobe16 (m_RemoteEndpoint.port ())); // remote port - s.Insert (payload, 8); // relayTag and signed on time + s.Insert (payload, 8); // relayTag and signed on time m_RelayTag = bufbe32toh (payload); payload += 4; // relayTag if (i2p::context.GetStatus () == eRouterStatusTesting) - { + { auto ts = i2p::util::GetSecondsSinceEpoch (); uint32_t signedOnTime = bufbe32toh(payload); if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) { - LogPrint (eLogError, "SSU: clock skew detected ", (int)ts - signedOnTime, ". Check your clock"); + LogPrint (eLogError, "SSU: clock skew detected ", (int)ts - signedOnTime, ". Check your clock"); i2p::context.SetError (eRouterErrorClockSkew); } - } + } payload += 4; // signed on time // decrypt signature size_t signatureLen = m_RemoteIdentity->GetSignatureLen (); @@ -304,34 +304,34 @@ namespace transport LogPrint (eLogError, "SSU: message 'created' signature verification failed"); Failed (); } - } + } void SSUSession::ProcessSessionConfirmed (const uint8_t * buf, size_t len) { - LogPrint (eLogDebug, "SSU: Session confirmed received"); - auto headerSize = GetSSUHeaderSize (buf); + LogPrint (eLogDebug, "SSU: Session confirmed received"); + auto headerSize = GetSSUHeaderSize (buf); if (headerSize >= len) { LogPrint (eLogError, "SSU: Session confirmed header size ", len, " exceeds packet length ", len); - return; - } + return; + } const uint8_t * payload = buf + headerSize; payload++; // identity fragment info - uint16_t identitySize = bufbe16toh (payload); + uint16_t identitySize = bufbe16toh (payload); payload += 2; // size of identity fragment auto identity = std::make_shared (payload, identitySize); auto existing = i2p::data::netdb.FindRouter (identity->GetIdentHash ()); // check if exists already SetRemoteIdentity (existing ? existing->GetRouterIdentity () : identity); m_Data.UpdatePacketSize (m_RemoteIdentity->GetIdentHash ()); - payload += identitySize; // identity + payload += identitySize; // identity auto ts = i2p::util::GetSecondsSinceEpoch (); - uint32_t signedOnTime = bufbe32toh(payload); + uint32_t signedOnTime = bufbe32toh(payload); if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) { - LogPrint (eLogError, "SSU message 'confirmed' time difference ", (int)ts - signedOnTime, " exceeds clock skew"); + LogPrint (eLogError, "SSU message 'confirmed' time difference ", (int)ts - signedOnTime, " exceeds clock skew"); Failed (); return; - } + } if (m_SignedData) m_SignedData->Insert (payload, 4); // insert Alice's signed on time payload += 4; // signed-on time @@ -345,7 +345,7 @@ namespace transport m_Data.Send (CreateDeliveryStatusMsg (0)); Established (); } - else + else { LogPrint (eLogError, "SSU message 'confirmed' signature verification failed"); Failed (); @@ -353,33 +353,33 @@ namespace transport } void SSUSession::SendSessionRequest () - { + { uint8_t buf[320 + 18] = {0}; // 304 bytes for ipv4, 320 for ipv6 uint8_t * payload = buf + sizeof (SSUHeader); uint8_t flag = 0; // fill extended options, 3 bytes extended options don't change message size if (i2p::context.GetStatus () == eRouterStatusOK) // we don't need relays - { + { // tell out peer to now assign relay tag flag = SSU_HEADER_EXTENDED_OPTIONS_INCLUDED; *payload = 2; payload++; // 1 byte length uint16_t flags = 0; // clear EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG - htobe16buf (payload, flags); + htobe16buf (payload, flags); payload += 2; - } + } // fill payload memcpy (payload, m_DHKeysPair->GetPublicKey (), 256); // x bool isV4 = m_RemoteEndpoint.address ().is_v4 (); if (isV4) { - payload[256] = 4; - memcpy (payload + 257, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4); + payload[256] = 4; + memcpy (payload + 257, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4); } else { - payload[256] = 16; - memcpy (payload + 257, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16); - } + payload[256] = 16; + memcpy (payload + 257, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16); + } // encrypt and send uint8_t iv[16]; RAND_bytes (iv, 16); // random iv @@ -395,7 +395,7 @@ namespace transport LogPrint (eLogInfo, "SSU is not supported"); return; } - + uint8_t buf[96 + 18] = {0}; uint8_t * payload = buf + sizeof (SSUHeader); htobe32buf (payload, introducer.iTag); @@ -405,17 +405,17 @@ namespace transport htobuf16(payload, 0); // port = 0 payload += 2; *payload = 0; // challenge - payload++; + payload++; memcpy (payload, (const uint8_t *)address->ssu->key, 32); payload += 32; - htobe32buf (payload, nonce); // nonce + htobe32buf (payload, nonce); // nonce uint8_t iv[16]; RAND_bytes (iv, 16); // random iv if (m_State == eSessionStateEstablished) FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, m_SessionKey, iv, m_MacKey); else - FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, introducer.iKey, iv, introducer.iKey); + FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, introducer.iKey, iv, introducer.iKey); m_Server.Send (buf, 96, m_RemoteEndpoint); } @@ -428,7 +428,7 @@ namespace transport LogPrint (eLogInfo, "SSU is not supported"); return; } - SignedData s; // x,y, remote IP, remote port, our IP, our port, relayTag, signed on time + SignedData s; // x,y, remote IP, remote port, our IP, our port, relayTag, signed on time s.Insert (x, 256); // x uint8_t buf[384 + 18] = {0}; @@ -441,7 +441,7 @@ namespace transport // ipv4 *payload = 4; payload++; - memcpy (payload, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4); + memcpy (payload, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4); s.Insert (payload, 4); // remote endpoint IP V4 payload += 4; } @@ -450,7 +450,7 @@ namespace transport // ipv6 *payload = 16; payload++; - memcpy (payload, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16); + memcpy (payload, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16); s.Insert (payload, 16); // remote endpoint IP V6 payload += 16; } @@ -467,20 +467,20 @@ namespace transport RAND_bytes((uint8_t *)&m_SentRelayTag, 4); if (!m_SentRelayTag) m_SentRelayTag = 1; } - htobe32buf (payload, m_SentRelayTag); - payload += 4; // relay tag + htobe32buf (payload, m_SentRelayTag); + payload += 4; // relay tag htobe32buf (payload, i2p::util::GetSecondsSinceEpoch ()); // signed on time payload += 4; - s.Insert (payload - 8, 4); // relayTag + s.Insert (payload - 8, 4); // relayTag // we have to store this signed data for session confirmed - // same data but signed on time, it will Alice's there - m_SignedData = std::unique_ptr(new SignedData (s)); - s.Insert (payload - 4, 4); // BOB's signed on time + // same data but signed on time, it will Alice's there + m_SignedData = std::unique_ptr(new SignedData (s)); + s.Insert (payload - 4, 4); // BOB's signed on time s.Sign (i2p::context.GetPrivateKeys (), payload); // DSA signature uint8_t iv[16]; RAND_bytes (iv, 16); // random iv - // encrypt signature and padding with newly created session key + // encrypt signature and padding with newly created session key size_t signatureLen = i2p::context.GetIdentity ()->GetSignatureLen (); size_t paddingSize = signatureLen & 0x0F; // %16 if (paddingSize > 0) @@ -493,9 +493,9 @@ namespace transport m_SessionKeyEncryption.Encrypt (payload, signatureLen, payload); payload += signatureLen; size_t msgLen = payload - buf; - + // encrypt message with intro key - FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, msgLen, m_IntroKey, iv, m_IntroKey); + FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, msgLen, m_IntroKey, iv, m_IntroKey); Send (buf, msgLen); } @@ -518,21 +518,21 @@ namespace transport if (paddingSize > 0) paddingSize = 16 - paddingSize; RAND_bytes(payload, paddingSize); // fill padding with random payload += paddingSize; // padding size - // signature - SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, our signed on time + // signature + SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, our signed on time s.Insert (m_DHKeysPair->GetPublicKey (), 256); // x s.Insert (y, 256); // y s.Insert (ourAddress, ourAddressLen); // our address/port as seem by party if (m_RemoteEndpoint.address ().is_v4 ()) s.Insert (m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data (), 4); // remote IP V4 else - s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP V6 + s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP V6 s.Insert (htobe16 (m_RemoteEndpoint.port ())); // remote port s.Insert (htobe32 (m_RelayTag)); // relay tag s.Insert (htobe32 (signedOnTime)); // signed on time - s.Sign (i2p::context.GetPrivateKeys (), payload); // DSA signature + s.Sign (i2p::context.GetPrivateKeys (), payload); // DSA signature payload += signatureLen; - + size_t msgLen = payload - buf; uint8_t iv[16]; RAND_bytes (iv, 16); // random iv @@ -547,7 +547,7 @@ namespace transport auto session = m_Server.FindRelaySession (relayTag); if (session) { - buf += 4; // relay tag + buf += 4; // relay tag uint8_t size = *buf; buf++; // size buf += size; // address @@ -560,7 +560,7 @@ namespace transport uint32_t nonce = bufbe32toh (buf); SendRelayResponse (nonce, from, introKey, session->m_RemoteEndpoint); SendRelayIntro (session, from); - } + } } void SSUSession::SendRelayResponse (uint32_t nonce, const boost::asio::ip::udp::endpoint& from, @@ -577,7 +577,7 @@ namespace transport *payload = 4; payload++; // size htobe32buf (payload, to.address ().to_v4 ().to_ulong ()); // Charlie's IP - payload += 4; // address + payload += 4; // address htobe16buf (payload, to.port ()); // Charlie's port payload += 2; // port // Alice @@ -587,25 +587,25 @@ namespace transport *payload = 4; payload++; // size memcpy (payload, from.address ().to_v4 ().to_bytes ().data (), 4); // Alice's IP V4 - payload += 4; // address + payload += 4; // address } else { *payload = 16; payload++; // size memcpy (payload, from.address ().to_v6 ().to_bytes ().data (), 16); // Alice's IP V6 - payload += 16; // address + payload += 16; // address } htobe16buf (payload, from.port ()); // Alice's port payload += 2; // port - htobe32buf (payload, nonce); + htobe32buf (payload, nonce); if (m_State == eSessionStateEstablished) - { + { // encrypt with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, isV4 ? 64 : 80); Send (buf, isV4 ? 64 : 80); - } + } else { // ecrypt with Alice's intro key @@ -613,45 +613,45 @@ namespace transport RAND_bytes (iv, 16); // random iv FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, isV4 ? 64 : 80, introKey, iv, introKey); m_Server.Send (buf, isV4 ? 64 : 80, from); - } + } LogPrint (eLogDebug, "SSU: relay response sent"); - } + } void SSUSession::SendRelayIntro (std::shared_ptr session, const boost::asio::ip::udp::endpoint& from) { - if (!session) return; + if (!session) return; // Alice's address always v4 if (!from.address ().is_v4 ()) { LogPrint (eLogWarning, "SSU: Alice's IP must be v4"); return; - } + } uint8_t buf[48 + 18] = {0}; uint8_t * payload = buf + sizeof (SSUHeader); *payload = 4; payload++; // size htobe32buf (payload, from.address ().to_v4 ().to_ulong ()); // Alice's IP - payload += 4; // address + payload += 4; // address htobe16buf (payload, from.port ()); // Alice's port payload += 2; // port - *payload = 0; // challenge size + *payload = 0; // challenge size uint8_t iv[16]; RAND_bytes (iv, 16); // random iv FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_INTRO, buf, 48, session->m_SessionKey, iv, session->m_MacKey); m_Server.Send (buf, 48, session->m_RemoteEndpoint); LogPrint (eLogDebug, "SSU: relay intro sent"); } - + void SSUSession::ProcessRelayResponse (const uint8_t * buf, size_t len) { - LogPrint (eLogDebug, "SSU message: Relay response received"); - uint8_t remoteSize = *buf; + LogPrint (eLogDebug, "SSU message: Relay response received"); + uint8_t remoteSize = *buf; buf++; // remote size boost::asio::ip::address_v4 remoteIP (bufbe32toh (buf)); buf += remoteSize; // remote address uint16_t remotePort = bufbe16toh (buf); buf += 2; // remote port - uint8_t ourSize = *buf; + uint8_t ourSize = *buf; buf++; // our size boost::asio::ip::address ourIP; if (ourSize == 4) @@ -675,7 +675,7 @@ namespace transport buf += 4; // nonce auto it = m_RelayRequests.find (nonce); if (it != m_RelayRequests.end ()) - { + { // check if we are waiting for introduction boost::asio::ip::udp::endpoint remoteEndpoint (remoteIP, remotePort); if (!m_Server.FindSession (remoteEndpoint)) @@ -686,10 +686,10 @@ namespace transport if (i2p::context.GetRouterInfo ().UsesIntroducer ()) // if we are unreachable m_Server.Send (buf, 0, remoteEndpoint); // send HolePunch m_Server.CreateDirectSession (it->second, remoteEndpoint, false); - } + } // delete request m_RelayRequests.erase (it); - } + } else LogPrint (eLogError, "SSU: Unsolicited RelayResponse, nonce=", nonce); } @@ -708,11 +708,11 @@ namespace transport } else LogPrint (eLogWarning, "SSU: Address size ", size, " is not supported"); - } + } - void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, + void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey, const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag) - { + { if (len < sizeof (SSUHeader)) { LogPrint (eLogError, "SSU: Unexpected packet length ", len); @@ -753,18 +753,18 @@ namespace transport memcpy (buf + len, header->iv, 16); htobe16buf (buf + len + 16, encryptedLen); i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac); - } - + } + void SSUSession::Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey) { if (len < sizeof (SSUHeader)) { LogPrint (eLogError, "SSU: Unexpected packet length ", len); return; - } + } SSUHeader * header = (SSUHeader *)buf; uint8_t * encrypted = &header->flag; - uint16_t encryptedLen = len - (encrypted - buf); + uint16_t encryptedLen = len - (encrypted - buf); i2p::crypto::CBCDecryption decryption; decryption.SetKey (aesKey); decryption.SetIV (header->iv); @@ -777,24 +777,24 @@ namespace transport { LogPrint (eLogError, "SSU: Unexpected packet length ", len); return; - } + } SSUHeader * header = (SSUHeader *)buf; uint8_t * encrypted = &header->flag; - uint16_t encryptedLen = len - (encrypted - buf); + uint16_t encryptedLen = len - (encrypted - buf); if (encryptedLen > 0) - { + { m_SessionKeyDecryption.SetIV (header->iv); m_SessionKeyDecryption.Decrypt (encrypted, encryptedLen, encrypted); - } - } - + } + } + bool SSUSession::Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey) { if (len < sizeof (SSUHeader)) { LogPrint (eLogError, "SSU: Unexpected packet length ", len); return false; - } + } SSUHeader * header = (SSUHeader *)buf; uint8_t * encrypted = &header->flag; uint16_t encryptedLen = len - (encrypted - buf); @@ -809,12 +809,12 @@ namespace transport void SSUSession::Connect () { if (m_State == eSessionStateUnknown) - { + { // set connect timer ScheduleConnectTimer (); m_DHKeysPair = transports.GetNextDHKeysPair (); SendSessionRequest (); - } + } } void SSUSession::WaitForConnect () @@ -830,7 +830,7 @@ namespace transport m_ConnectTimer.cancel (); m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); } void SSUSession::HandleConnectTimer (const boost::system::error_code& ecode) @@ -840,14 +840,14 @@ namespace transport // timeout expired LogPrint (eLogWarning, "SSU: session with ", m_RemoteEndpoint, " was not established after ", SSU_CONNECT_TIMEOUT, " seconds"); Failed (); - } - } - + } + } + void SSUSession::Introduce (const i2p::data::RouterInfo::Introducer& introducer, std::shared_ptr to) { if (m_State == eSessionStateUnknown) - { + { // set connect timer m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, @@ -865,7 +865,7 @@ namespace transport // set connect timer m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); } void SSUSession::Close () @@ -873,7 +873,7 @@ namespace transport SendSessionDestroyed (); Reset (); m_State = eSessionStateClosed; - } + } void SSUSession::Reset () { @@ -882,10 +882,10 @@ namespace transport m_Data.Stop (); m_ConnectTimer.cancel (); if (m_SentRelayTag) - { + { m_Server.RemoveRelay (m_SentRelayTag); // relay tag is not valid anymore m_SentRelayTag = 0; - } + } m_DHKeysPair = nullptr; m_SignedData = nullptr; m_IsSessionKey = false; @@ -908,20 +908,20 @@ namespace transport if (m_SentRelayTag) m_Server.AddRelay (m_SentRelayTag, shared_from_this ()); m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - } + } void SSUSession::Failed () { if (m_State != eSessionStateFailed) - { + { m_State = eSessionStateFailed; - m_Server.DeleteSession (shared_from_this ()); - } - } + m_Server.DeleteSession (shared_from_this ()); + } + } void SSUSession::SendI2NPMessages (const std::vector >& msgs) { - GetService ().post (std::bind (&SSUSession::PostI2NPMessages, shared_from_this (), msgs)); + GetService ().post (std::bind (&SSUSession::PostI2NPMessages, shared_from_this (), msgs)); } void SSUSession::PostI2NPMessages (std::vector > msgs) @@ -931,7 +931,7 @@ namespace transport for (const auto& it: msgs) if (it) m_Data.Send (it); } - } + } void SSUSession::ProcessData (uint8_t * buf, size_t len) { @@ -942,29 +942,29 @@ namespace transport void SSUSession::FlushData () { if (m_IsDataReceived) - { + { m_Data.FlushReceivedMessage (); m_IsDataReceived = false; - } + } } void SSUSession::ProcessPeerTest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { uint32_t nonce = bufbe32toh (buf); // 4 bytes - uint8_t size = buf[4]; // 1 byte + uint8_t size = buf[4]; // 1 byte const uint8_t * address = buf + 5; // big endian, size bytes uint16_t port = buf16toh(buf + size + 5); // big endian, 2 bytes const uint8_t * introKey = buf + size + 7; - if (port && (size != 4) && (size != 16)) + if (port && (size != 4) && (size != 16)) { LogPrint (eLogWarning, "SSU: Address of ", size, " bytes not supported"); return; - } + } switch (m_Server.GetPeerTestParticipant (nonce)) - { - // existing test + { + // existing test case ePeerTestParticipantAlice1: - { + { if (m_Server.GetPeerTestSession (nonce) == shared_from_this ()) // Alice-Bob { LogPrint (eLogDebug, "SSU: peer test from Bob. We are Alice"); @@ -981,7 +981,7 @@ namespace transport SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, true, false); // to Charlie } break; - } + } case ePeerTestParticipantAlice2: { if (m_Server.GetPeerTestSession (nonce) == shared_from_this ()) // Alice-Bob @@ -994,8 +994,8 @@ namespace transport m_Server.RemovePeerTest (nonce); } break; - } - case ePeerTestParticipantBob: + } + case ePeerTestParticipantBob: { LogPrint (eLogDebug, "SSU: peer test from Charlie. We are Bob"); auto session = m_Server.GetPeerTestSession (nonce); // session with Alice from PeerTest @@ -1005,13 +1005,13 @@ namespace transport break; } case ePeerTestParticipantCharlie: - { + { LogPrint (eLogDebug, "SSU: peer test from Alice. We are Charlie"); SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey); // to Alice with her actual address m_Server.RemovePeerTest (nonce); // nonce has been used break; } - // test not found + // test not found case ePeerTestParticipantUnknown: { if (m_State == eSessionStateEstablished) @@ -1034,7 +1034,7 @@ namespace transport boost::asio::ip::address_v6::bytes_type bytes; memcpy (bytes.data (), address, 16); addr = boost::asio::ip::address_v6 (bytes); - } + } SendPeerTest (nonce, addr, be16toh (port), introKey); // to Alice with her address received from Bob } else @@ -1044,26 +1044,26 @@ namespace transport if (session) { m_Server.NewPeerTest (nonce, ePeerTestParticipantBob, shared_from_this ()); - session->SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, false); // to Charlie with Alice's actual address - } + session->SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, false); // to Charlie with Alice's actual address + } } } else LogPrint (eLogError, "SSU: unexpected peer test"); } - } + } } - - void SSUSession::SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, + + void SSUSession::SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, const uint8_t * introKey, bool toAddress, bool sendAddress) // toAddress is true for Alice<->Chalie communications only - // sendAddress is false if message comes from Alice + // sendAddress is false if message comes from Alice { uint8_t buf[80 + 18] = {0}; uint8_t iv[16]; uint8_t * payload = buf + sizeof (SSUHeader); htobe32buf (payload, nonce); - payload += 4; // nonce + payload += 4; // nonce // address and port if (sendAddress) { @@ -1075,11 +1075,11 @@ namespace transport else if (address.is_v6 ()) { *payload = 16; - memcpy (payload + 1, address.to_v6 ().to_bytes ().data (), 16); // our IP V6 + memcpy (payload + 1, address.to_v6 ().to_bytes ().data (), 16); // our IP V6 } else *payload = 0; - payload += (payload[0] + 1); + payload += (payload[0] + 1); } else { @@ -1096,27 +1096,27 @@ namespace transport if (addr) memcpy (payload, addr->ssu->key, 32); // intro key else - LogPrint (eLogInfo, "SSU is not supported. Can't send peer test"); - } - else + LogPrint (eLogInfo, "SSU is not supported. Can't send peer test"); + } + else memcpy (payload, introKey, 32); // intro key - // send + // send RAND_bytes (iv, 16); // random iv if (toAddress) - { + { // encrypt message with specified intro key FillHeaderAndEncrypt (PAYLOAD_TYPE_PEER_TEST, buf, 80, introKey, iv, introKey); boost::asio::ip::udp::endpoint e (address, port); m_Server.Send (buf, 80, e); - } + } else { // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_PEER_TEST, buf, 80); Send (buf, 80); } - } + } void SSUSession::SendPeerTest () { @@ -1134,23 +1134,23 @@ namespace transport m_IsPeerTest = false; m_Server.NewPeerTest (nonce, ePeerTestParticipantAlice1, shared_from_this ()); SendPeerTest (nonce, boost::asio::ip::address(), 0, address->ssu->key, false, false); // address and port always zero for Alice - } + } void SSUSession::SendKeepAlive () { if (m_State == eSessionStateEstablished) - { + { uint8_t buf[48 + 18] = {0}; uint8_t * payload = buf + sizeof (SSUHeader); *payload = 0; // flags payload++; - *payload = 0; // num fragments + *payload = 0; // num fragments // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); Send (buf, 48); LogPrint (eLogDebug, "SSU: keep-alive sent"); m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - } + } } void SSUSession::SendSessionDestroyed () @@ -1170,31 +1170,31 @@ namespace transport } LogPrint (eLogDebug, "SSU: session destroyed sent"); } - } + } void SSUSession::Send (uint8_t type, const uint8_t * payload, size_t len) { uint8_t buf[SSU_MTU_V4 + 18] = {0}; - size_t msgSize = len + sizeof (SSUHeader); + size_t msgSize = len + sizeof (SSUHeader); size_t paddingSize = msgSize & 0x0F; // %16 if (paddingSize > 0) msgSize += (16 - paddingSize); if (msgSize > SSU_MTU_V4) { LogPrint (eLogWarning, "SSU: payload size ", msgSize, " exceeds MTU"); return; - } + } memcpy (buf + sizeof (SSUHeader), payload, len); // encrypt message with session key FillHeaderAndEncrypt (type, buf, msgSize); Send (buf, msgSize); - } + } void SSUSession::Send (const uint8_t * buf, size_t size) { m_NumSentBytes += size; i2p::transport::transports.UpdateSentBytes (size); m_Server.Send (buf, size, m_RemoteEndpoint); - } + } } } diff --git a/libi2pd/SSUSession.h b/libi2pd/SSUSession.h index af13c645..8247c420 100644 --- a/libi2pd/SSUSession.h +++ b/libi2pd/SSUSession.h @@ -19,15 +19,15 @@ namespace transport uint8_t mac[16]; uint8_t iv[16]; uint8_t flag; - uint8_t time[4]; + uint8_t time[4]; uint8_t GetPayloadType () const { return flag >> 4; }; - bool IsExtendedOptions () const { return flag & SSU_HEADER_EXTENDED_OPTIONS_INCLUDED; }; + bool IsExtendedOptions () const { return flag & SSU_HEADER_EXTENDED_OPTIONS_INCLUDED; }; }; const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes - const int SSU_CLOCK_SKEW = 60; // in seconds + const int SSU_CLOCK_SKEW = 60; // in seconds // payload types (4 bits) const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0; @@ -45,12 +45,12 @@ namespace transport enum SessionState { - eSessionStateUnknown, + eSessionStateUnknown, eSessionStateIntroduced, eSessionStateEstablished, eSessionStateClosed, eSessionStateFailed - }; + }; enum PeerTestParticipant { @@ -60,7 +60,7 @@ namespace transport ePeerTestParticipantBob, ePeerTestParticipantCharlie }; - + class SSUServer; class SSUSession: public TransportSession, public std::enable_shared_from_this { @@ -68,12 +68,12 @@ namespace transport SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, std::shared_ptr router = nullptr, bool peerTest = false); - void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); + void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); ~SSUSession (); - + void Connect (); void WaitForConnect (); - void Introduce (const i2p::data::RouterInfo::Introducer& introducer, + void Introduce (const i2p::data::RouterInfo::Introducer& introducer, std::shared_ptr to); // Alice to Charlie void WaitForIntroduction (); void Close (); @@ -82,23 +82,23 @@ namespace transport boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); }; void SendI2NPMessages (const std::vector >& msgs); - void SendPeerTest (); // Alice + void SendPeerTest (); // Alice SessionState GetState () const { return m_State; }; size_t GetNumSentBytes () const { return m_NumSentBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; - - void SendKeepAlive (); - uint32_t GetRelayTag () const { return m_RelayTag; }; + + void SendKeepAlive (); + uint32_t GetRelayTag () const { return m_RelayTag; }; const i2p::data::RouterInfo::IntroKey& GetIntroKey () const { return m_IntroKey; }; uint32_t GetCreationTime () const { return m_CreationTime; }; void FlushData (); - + private: boost::asio::io_service& GetService (); - void CreateAESandMacKey (const uint8_t * pubKey); + void CreateAESandMacKey (const uint8_t * pubKey); size_t GetSSUHeaderSize (const uint8_t * buf) const; void PostI2NPMessages (std::vector > msgs); void ProcessMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); // call for established session @@ -119,23 +119,23 @@ namespace transport void ScheduleConnectTimer (); void HandleConnectTimer (const boost::system::error_code& ecode); void ProcessPeerTest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); - void SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, const uint8_t * introKey, bool toAddress = true, bool sendAddress = true); - void ProcessData (uint8_t * buf, size_t len); + void SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, const uint8_t * introKey, bool toAddress = true, bool sendAddress = true); + void ProcessData (uint8_t * buf, size_t len); void SendSessionDestroyed (); void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key - void Send (const uint8_t * buf, size_t size); - - void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey, + void Send (const uint8_t * buf, size_t size); + + void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey, const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag = 0); - void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key + void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key void Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey); void DecryptSessionKey (uint8_t * buf, size_t len); - bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey); + bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey); void Reset (); - + private: - + friend class SSUData; // TODO: change in later SSUServer& m_Server; boost::asio::ip::udp::endpoint m_RemoteEndpoint; diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index c5c2419b..aded9bc8 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -16,24 +16,24 @@ namespace crypto BIGNUM * tmp = BN_new (); q = BN_new (); - // 2^255-19 - BN_set_bit (q, 255); // 2^255 + // 2^255-19 + BN_set_bit (q, 255); // 2^255 BN_sub_word (q, 19); - + l = BN_new (); // 2^252 + 27742317777372353535851937790883648493 BN_set_bit (l, 252); two_252_2 = BN_dup (l); BN_dec2bn (&tmp, "27742317777372353535851937790883648493"); - BN_add (l, l, tmp); - BN_sub_word (two_252_2, 2); // 2^252 - 2 + BN_add (l, l, tmp); + BN_sub_word (two_252_2, 2); // 2^252 - 2 // -121665*inv(121666) d = BN_new (); BN_set_word (tmp, 121666); - BN_mod_inverse (tmp, tmp, q, ctx); + BN_mod_inverse (tmp, tmp, q, ctx); BN_set_word (d, 121665); - BN_set_negative (d, 1); + BN_set_negative (d, 1); BN_mul (d, d, tmp, ctx); // 2^((q-1)/4) @@ -41,20 +41,20 @@ namespace crypto BN_free (tmp); tmp = BN_dup (q); BN_sub_word (tmp, 1); - BN_div_word (tmp, 4); + BN_div_word (tmp, 4); BN_set_word (I, 2); BN_mod_exp (I, I, tmp, q, ctx); - BN_free (tmp); - - // 4*inv(5) - BIGNUM * By = BN_new (); + BN_free (tmp); + + // 4*inv(5) + BIGNUM * By = BN_new (); BN_set_word (By, 5); - BN_mod_inverse (By, By, q, ctx); + BN_mod_inverse (By, By, q, ctx); BN_mul_word (By, 4); - BIGNUM * Bx = RecoverX (By, ctx); + BIGNUM * Bx = RecoverX (By, ctx); BN_mod (Bx, Bx, q, ctx); // % q - BN_mod (By, By, q, ctx); // % q - + BN_mod (By, By, q, ctx); // % q + // precalculate Bi256 table Bi256Carry = { Bx, By }; // B for (int i = 0; i < 32; i++) @@ -70,7 +70,7 @@ namespace crypto BN_CTX_free (ctx); } - Ed25519 (const Ed25519& other): q (BN_dup (other.q)), l (BN_dup (other.l)), + Ed25519 (const Ed25519& other): q (BN_dup (other.q)), l (BN_dup (other.l)), d (BN_dup (other.d)), I (BN_dup (other.I)), two_252_2 (BN_dup (other.two_252_2)), Bi256Carry (other.Bi256Carry) { @@ -106,9 +106,9 @@ namespace crypto bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const { - BN_CTX * ctx = BN_CTX_new (); + BN_CTX * ctx = BN_CTX_new (); BIGNUM * h = DecodeBN<64> (digest); - // signature 0..31 - R, 32..63 - S + // signature 0..31 - R, 32..63 - S // B*S = R + PK*h => R = B*S - PK*h // we don't decode R, but encode (B*S - PK*h) auto Bs = MulB (signature + EDDSA25519_SIGNATURE_LENGTH/2, ctx); // B*S; @@ -117,14 +117,14 @@ namespace crypto uint8_t diff[32]; EncodePoint (Normalize (Sum (Bs, -PKh, ctx), ctx), diff); // Bs - PKh encoded bool passed = !memcmp (signature, diff, 32); // R - BN_free (h); + BN_free (h); BN_CTX_free (ctx); if (!passed) LogPrint (eLogError, "25519 signature verification failed"); - return passed; + return passed; } - void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, + void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const { BN_CTX * bnCtx = BN_CTX_new (); @@ -138,14 +138,14 @@ namespace crypto BIGNUM * r = DecodeBN<32> (digest); // DecodeBN<64> (digest); // for test vectors // calculate R uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf - EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); // EncodePoint (Mul (B, r, bnCtx), R); // for test vectors + EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); // EncodePoint (Mul (B, r, bnCtx), R); // for test vectors // calculate S SHA512_Init (&ctx); SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R SHA512_Update (&ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key SHA512_Update (&ctx, buf, len); // data SHA512_Final (digest, &ctx); - BIGNUM * h = DecodeBN<64> (digest); + BIGNUM * h = DecodeBN<64> (digest); // S = (r + h*a) % l BIGNUM * a = DecodeBN (expandedPrivateKey); // left half of expanded key BN_mod_mul (h, h, a, l, bnCtx); // %l @@ -156,7 +156,7 @@ namespace crypto BN_CTX_free (bnCtx); } - private: + private: EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const { @@ -165,9 +165,9 @@ namespace crypto // z3 = (z1*z2-d*t1*t2)*(z1*z2+d*t1*t2) // t3 = (y1*y2+x1*x2)*(x1*y2+y1*x2) BIGNUM * x3 = BN_new (), * y3 = BN_new (), * z3 = BN_new (), * t3 = BN_new (); - - BN_mul (x3, p1.x, p2.x, ctx); // A = x1*x2 - BN_mul (y3, p1.y, p2.y, ctx); // B = y1*y2 + + BN_mul (x3, p1.x, p2.x, ctx); // A = x1*x2 + BN_mul (y3, p1.y, p2.y, ctx); // B = y1*y2 BN_CTX_start (ctx); BIGNUM * t1 = p1.t, * t2 = p2.t; @@ -189,10 +189,10 @@ namespace crypto BN_copy (z3, p2.z); // D = z2 else BN_one (z3); // D = 1 - } + } BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx); - BN_add (E, p1.x, p1.y); + BN_add (E, p1.x, p1.y); BN_add (F, p2.x, p2.y); BN_mul (E, E, F, ctx); // (x1 + y1)*(x2 + y2) BN_sub (E, E, x3); @@ -202,9 +202,9 @@ namespace crypto BN_add (H, y3, x3); // H = B + A BN_mod_mul (x3, E, F, q, ctx); // x3 = E*F - BN_mod_mul (y3, G, H, q, ctx); // y3 = G*H - BN_mod_mul (z3, F, G, q, ctx); // z3 = F*G - BN_mod_mul (t3, E, H, q, ctx); // t3 = E*H + BN_mod_mul (y3, G, H, q, ctx); // y3 = G*H + BN_mod_mul (z3, F, G, q, ctx); // z3 = F*G + BN_mod_mul (t3, E, H, q, ctx); // t3 = E*H BN_CTX_end (ctx); @@ -215,40 +215,40 @@ namespace crypto { BN_CTX_start (ctx); BIGNUM * x2 = BN_CTX_get (ctx), * y2 = BN_CTX_get (ctx), * z2 = BN_CTX_get (ctx), * t2 = BN_CTX_get (ctx); - - BN_sqr (x2, p.x, ctx); // x2 = A = x^2 - BN_sqr (y2, p.y, ctx); // y2 = B = y^2 + + BN_sqr (x2, p.x, ctx); // x2 = A = x^2 + BN_sqr (y2, p.y, ctx); // y2 = B = y^2 if (p.t) BN_sqr (t2, p.t, ctx); // t2 = t^2 else { BN_mul (t2, p.x, p.y, ctx); // t = x*y BN_sqr (t2, t2, ctx); // t2 = t^2 - } - BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2 + } + BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2 if (p.z) - BN_sqr (z2, p.z, ctx); // z2 = D = z^2 + BN_sqr (z2, p.z, ctx); // z2 = D = z^2 else BN_one (z2); // z2 = 1 BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx); // E = (x+y)*(x+y)-A-B = x^2+y^2+2xy-A-B = 2xy BN_mul (E, p.x, p.y, ctx); - BN_lshift1 (E, E); // E =2*x*y + BN_lshift1 (E, E); // E =2*x*y BN_sub (F, z2, t2); // F = D - C - BN_add (G, z2, t2); // G = D + C + BN_add (G, z2, t2); // G = D + C BN_add (H, y2, x2); // H = B + A BN_mod_mul (p.x, E, F, q, ctx); // x2 = E*F - BN_mod_mul (p.y, G, H, q, ctx); // y2 = G*H + BN_mod_mul (p.y, G, H, q, ctx); // y2 = G*H if (!p.z) p.z = BN_new (); - BN_mod_mul (p.z, F, G, q, ctx); // z2 = F*G + BN_mod_mul (p.z, F, G, q, ctx); // z2 = F*G if (!p.t) p.t = BN_new (); - BN_mod_mul (p.t, E, H, q, ctx); // t2 = E*H + BN_mod_mul (p.t, E, H, q, ctx); // t2 = E*H BN_CTX_end (ctx); } - + EDDSAPoint Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const { BIGNUM * zero = BN_new (), * one = BN_new (); @@ -262,10 +262,10 @@ namespace crypto Double (res, ctx); if (BN_is_bit_set (e, i)) res = Sum (res, p, ctx); } - } + } return res; - } - + } + EDDSAPoint MulB (const uint8_t * e, BN_CTX * ctx) const // B*e, e is 32 bytes Little Endian { BIGNUM * zero = BN_new (), * one = BN_new (); @@ -275,15 +275,15 @@ namespace crypto for (int i = 0; i < 32; i++) { uint8_t x = e[i]; - if (carry) - { - if (x < 255) - { - x++; + if (carry) + { + if (x < 255) + { + x++; carry = false; - } - else - x = 0; + } + else + x = 0; } if (x > 0) { @@ -293,7 +293,7 @@ namespace crypto { res = Sum (res, -Bi256[i][255-x], ctx); // -Bi[256-x] carry = true; - } + } } } if (carry) res = Sum (res, Bi256Carry, ctx); @@ -320,9 +320,9 @@ namespace crypto BIGNUM * x2 = BN_CTX_get (ctx), * y2 = BN_CTX_get (ctx), * tmp = BN_CTX_get (ctx); BN_sqr (x2, p.x, ctx); // x^2 BN_sqr (y2, p.y, ctx); // y^2 - // y^2 - x^2 - 1 - d*x^2*y^2 + // y^2 - x^2 - 1 - d*x^2*y^2 BN_mul (tmp, d, x2, ctx); - BN_mul (tmp, tmp, y2, ctx); + BN_mul (tmp, tmp, y2, ctx); BN_sub (tmp, y2, tmp); BN_sub (tmp, tmp, x2); BN_sub_word (tmp, 1); @@ -330,25 +330,25 @@ namespace crypto bool ret = BN_is_zero (tmp); BN_CTX_end (ctx); return ret; - } + } BIGNUM * RecoverX (const BIGNUM * y, BN_CTX * ctx) const { BN_CTX_start (ctx); BIGNUM * y2 = BN_CTX_get (ctx), * xx = BN_CTX_get (ctx); BN_sqr (y2, y, ctx); // y^2 - // xx = (y^2 -1)*inv(d*y^2 +1) + // xx = (y^2 -1)*inv(d*y^2 +1) BN_mul (xx, d, y2, ctx); BN_add_word (xx, 1); BN_mod_inverse (xx, xx, q, ctx); BN_sub_word (y2, 1); BN_mul (xx, y2, xx, ctx); - // x = srqt(xx) = xx^(2^252-2) + // x = srqt(xx) = xx^(2^252-2) BIGNUM * x = BN_new (); BN_mod_exp (x, xx, two_252_2, q, ctx); - // check (x^2 -xx) % q + // check (x^2 -xx) % q BN_sqr (y2, x, ctx); - BN_mod_sub (y2, y2, xx, q, ctx); + BN_mod_sub (y2, y2, xx, q, ctx); if (!BN_is_zero (y2)) BN_mod_mul (x, x, I, q, ctx); if (BN_is_odd (x)) @@ -373,18 +373,18 @@ namespace crypto BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y); BIGNUM * x = RecoverX (y, ctx); if (BN_is_bit_set (x, 0) != isHighestBitSet) - BN_sub (x, q, x); // x = q - x - BIGNUM * z = BN_new (), * t = BN_new (); + BN_sub (x, q, x); // x = q - x + BIGNUM * z = BN_new (), * t = BN_new (); BN_one (z); BN_mod_mul (t, x, y, q, ctx); // pre-calculate t EDDSAPoint p {x, y, z, t}; - if (!IsOnCurve (p, ctx)) + if (!IsOnCurve (p, ctx)) LogPrint (eLogError, "Decoded point is not on 25519"); return p; } - + void EncodePoint (const EDDSAPoint& p, uint8_t * buf) const { - EncodeBN (p.y, buf,EDDSA25519_PUBLIC_KEY_LENGTH); + EncodeBN (p.y, buf,EDDSA25519_PUBLIC_KEY_LENGTH); if (BN_is_bit_set (p.x, 0)) // highest bit buf[EDDSA25519_PUBLIC_KEY_LENGTH - 1] |= 0x80; // set highest bit } @@ -413,12 +413,12 @@ namespace crypto uint8_t tmp = buf[i]; buf[i] = buf[len -1 - i]; buf[len -1 - i] = tmp; - } + } } private: - - BIGNUM * q, * l, * d, * I; + + BIGNUM * q, * l, * d, * I; // transient values BIGNUM * two_252_2; // 2^252-2 EDDSAPoint Bi256[32][128]; // per byte, Bi256[i][j] = (256+j+1)^i*B, we don't store zeroes @@ -437,14 +437,14 @@ namespace crypto g_Ed25519.reset (c); else delete c; - } - return g_Ed25519; - } - + } + return g_Ed25519; + } + EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey) { - memcpy (m_PublicKeyEncoded, signingKey, EDDSA25519_PUBLIC_KEY_LENGTH); + memcpy (m_PublicKeyEncoded, signingKey, EDDSA25519_PUBLIC_KEY_LENGTH); BN_CTX * ctx = BN_CTX_new (); m_PublicKey = GetEd25519 ()->DecodePublicKey (m_PublicKeyEncoded, ctx); BN_CTX_free (ctx); @@ -457,40 +457,40 @@ namespace crypto SHA512_Init (&ctx); SHA512_Update (&ctx, signature, EDDSA25519_SIGNATURE_LENGTH/2); // R SHA512_Update (&ctx, m_PublicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key - SHA512_Update (&ctx, buf, len); // data + SHA512_Update (&ctx, buf, len); // data SHA512_Final (digest, &ctx); - + return GetEd25519 ()->Verify (m_PublicKey, digest, signature); } EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey) - { + { // expand key SHA512 (signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH, m_ExpandedPrivateKey); - m_ExpandedPrivateKey[0] &= 0xF8; // drop last 3 bits + m_ExpandedPrivateKey[0] &= 0xF8; // drop last 3 bits m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] &= 0x3F; // drop first 2 bits m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] |= 0x40; // set second bit - + // generate and encode public key - BN_CTX * ctx = BN_CTX_new (); + BN_CTX * ctx = BN_CTX_new (); auto publicKey = GetEd25519 ()->GeneratePublicKey (m_ExpandedPrivateKey, ctx); - GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx); - + GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx); + if (signingPublicKey && memcmp (m_PublicKeyEncoded, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH)) { // keys don't match, it means older key with 0x1F LogPrint (eLogWarning, "Older EdDSA key detected"); - m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] &= 0xDF; // drop third bit + m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] &= 0xDF; // drop third bit publicKey = GetEd25519 ()->GeneratePublicKey (m_ExpandedPrivateKey, ctx); - GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx); + GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx); } BN_CTX_free (ctx); - } - + } + void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const { GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature); - } + } } } diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index 531fdfdf..1e7db9f7 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -18,7 +18,7 @@ namespace crypto class Verifier { public: - + virtual ~Verifier () {}; virtual bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const = 0; virtual size_t GetPublicKeyLen () const = 0; @@ -30,12 +30,12 @@ namespace crypto { public: - virtual ~Signer () {}; - virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0; + virtual ~Signer () {}; + virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0; }; const size_t DSA_PUBLIC_KEY_LENGTH = 128; - const size_t DSA_SIGNATURE_LENGTH = 40; + const size_t DSA_SIGNATURE_LENGTH = 40; const size_t DSA_PRIVATE_KEY_LENGTH = DSA_SIGNATURE_LENGTH/2; class DSAVerifier: public Verifier { @@ -51,7 +51,7 @@ namespace crypto { DSA_free (m_PublicKey); } - + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { // calculate SHA1 digest @@ -64,11 +64,11 @@ namespace crypto int ret = DSA_do_verify (digest, 20, sig, m_PublicKey); DSA_SIG_free(sig); return ret; - } + } size_t GetPublicKeyLen () const { return DSA_PUBLIC_KEY_LENGTH; }; size_t GetSignatureLen () const { return DSA_SIGNATURE_LENGTH; }; - + private: DSA * m_PublicKey; @@ -89,7 +89,7 @@ namespace crypto { DSA_free (m_PrivateKey); } - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { uint8_t digest[20]; @@ -115,21 +115,21 @@ namespace crypto DSA_get0_key(dsa, &pub_key, &priv_key); bn2buf (priv_key, signingPrivateKey, DSA_PRIVATE_KEY_LENGTH); bn2buf (pub_key, signingPublicKey, DSA_PUBLIC_KEY_LENGTH); - DSA_free (dsa); - } + DSA_free (dsa); + } struct SHA256Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { SHA256 (buf, len, digest); } enum { hashLen = 32 }; - }; + }; struct SHA384Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { SHA384 (buf, len, digest); @@ -139,7 +139,7 @@ namespace crypto }; struct SHA512Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { SHA512 (buf, len, digest); @@ -147,10 +147,10 @@ namespace crypto enum { hashLen = 64 }; }; - + template class ECDSAVerifier: public Verifier - { + { public: ECDSAVerifier (const uint8_t * signingKey) @@ -166,7 +166,7 @@ namespace crypto { EC_KEY_free (m_PublicKey); } - + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { uint8_t digest[Hash::hashLen]; @@ -179,12 +179,12 @@ namespace crypto int ret = ECDSA_do_verify (digest, Hash::hashLen, sig, m_PublicKey); ECDSA_SIG_free(sig); return ret; - } - + } + size_t GetPublicKeyLen () const { return keyLen; }; size_t GetSignatureLen () const { return keyLen; }; // signature length = key length - + private: EC_KEY * m_PublicKey; @@ -198,14 +198,14 @@ namespace crypto ECDSASigner (const uint8_t * signingPrivateKey) { m_PrivateKey = EC_KEY_new_by_curve_name (curve); - EC_KEY_set_private_key (m_PrivateKey, BN_bin2bn (signingPrivateKey, keyLen/2, NULL)); + EC_KEY_set_private_key (m_PrivateKey, BN_bin2bn (signingPrivateKey, keyLen/2, NULL)); } ~ECDSASigner () { EC_KEY_free (m_PrivateKey); } - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { uint8_t digest[Hash::hashLen]; @@ -235,18 +235,18 @@ namespace crypto bn2buf (x, signingPublicKey, keyLen/2); bn2buf (y, signingPublicKey + keyLen/2, keyLen/2); BN_free (x); BN_free (y); - EC_KEY_free (signingKey); + EC_KEY_free (signingKey); } // ECDSA_SHA256_P256 - const size_t ECDSAP256_KEY_LENGTH = 64; + const size_t ECDSAP256_KEY_LENGTH = 64; typedef ECDSAVerifier ECDSAP256Verifier; typedef ECDSASigner ECDSAP256Signer; inline void CreateECDSAP256RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { CreateECDSARandomKeys (NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH, signingPrivateKey, signingPublicKey); - } + } // ECDSA_SHA384_P384 const size_t ECDSAP384_KEY_LENGTH = 96; @@ -256,7 +256,7 @@ namespace crypto inline void CreateECDSAP384RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { CreateECDSARandomKeys (NID_secp384r1, ECDSAP384_KEY_LENGTH, signingPrivateKey, signingPublicKey); - } + } // ECDSA_SHA512_P521 const size_t ECDSAP521_KEY_LENGTH = 132; @@ -269,7 +269,7 @@ namespace crypto } // RSA - template + template class RSAVerifier: public Verifier { public: @@ -284,23 +284,23 @@ namespace crypto { RSA_free (m_PublicKey); } - - bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const + + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { uint8_t digest[Hash::hashLen]; Hash::CalculateHash (buf, len, digest); return RSA_verify (type, digest, Hash::hashLen, signature, GetSignatureLen (), m_PublicKey); } size_t GetPublicKeyLen () const { return keyLen; } - size_t GetSignatureLen () const { return keyLen; } + size_t GetSignatureLen () const { return keyLen; } size_t GetPrivateKeyLen () const { return GetSignatureLen ()*2; }; private: - - RSA * m_PublicKey; - }; - + RSA * m_PublicKey; + }; + + template class RSASigner: public Signer { @@ -317,7 +317,7 @@ namespace crypto { RSA_free (m_PrivateKey); } - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { uint8_t digest[Hash::hashLen]; @@ -325,11 +325,11 @@ namespace crypto unsigned int signatureLen = keyLen; RSA_sign (type, digest, Hash::hashLen, signature, &signatureLen, m_PrivateKey); } - + private: RSA * m_PrivateKey; - }; + }; inline void CreateRSARandomKeys (size_t publicKeyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { @@ -337,14 +337,14 @@ namespace crypto BIGNUM * e = BN_dup (GetRSAE ()); // make it non-const RSA_generate_key_ex (rsa, publicKeyLen*8, e, NULL); const BIGNUM * n, * d, * e1; - RSA_get0_key (rsa, &n, &e1, &d); + RSA_get0_key (rsa, &n, &e1, &d); bn2buf (n, signingPrivateKey, publicKeyLen); bn2buf (d, signingPrivateKey + publicKeyLen, publicKeyLen); bn2buf (n, signingPublicKey, publicKeyLen); BN_free (e); // this e is not assigned to rsa->e RSA_free (rsa); - } - + } + // RSA_SHA256_2048 const size_t RSASHA2562048_KEY_LENGTH = 256; typedef RSAVerifier RSASHA2562048Verifier; @@ -353,7 +353,7 @@ namespace crypto // RSA_SHA384_3072 const size_t RSASHA3843072_KEY_LENGTH = 384; typedef RSAVerifier RSASHA3843072Verifier; - typedef RSASigner RSASHA3843072Signer; + typedef RSASigner RSASHA3843072Signer; // RSA_SHA512_4096 const size_t RSASHA5124096_KEY_LENGTH = 512; @@ -379,7 +379,7 @@ namespace crypto {} ~EDDSAPoint () { BN_free (x); BN_free (y); BN_free(z); BN_free(t); } - EDDSAPoint& operator=(EDDSAPoint&& other) + EDDSAPoint& operator=(EDDSAPoint&& other) { if (this != &other) { @@ -389,9 +389,9 @@ namespace crypto BN_free (t); t = other.t; other.t = nullptr; } return *this; - } + } - EDDSAPoint& operator=(const EDDSAPoint& other) + EDDSAPoint& operator=(const EDDSAPoint& other) { if (this != &other) { @@ -412,11 +412,11 @@ namespace crypto if (t) { t1 = BN_dup (t); BN_set_negative (t1, !BN_is_negative (t)); }; return EDDSAPoint {x1, y1, z1, t1}; } - }; + }; const size_t EDDSA25519_PUBLIC_KEY_LENGTH = 32; const size_t EDDSA25519_SIGNATURE_LENGTH = 64; - const size_t EDDSA25519_PRIVATE_KEY_LENGTH = 32; + const size_t EDDSA25519_PRIVATE_KEY_LENGTH = 32; class EDDSA25519Verifier: public Verifier { public: @@ -429,7 +429,7 @@ namespace crypto private: - EDDSAPoint m_PublicKey; + EDDSAPoint m_PublicKey; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; }; @@ -437,14 +437,14 @@ namespace crypto { public: - EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr); - // we pass signingPublicKey to check if it matches private key - void Sign (const uint8_t * buf, int len, uint8_t * signature) const; + EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr); + // we pass signingPublicKey to check if it matches private key + void Sign (const uint8_t * buf, int len, uint8_t * signature) const; const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; - + private: - uint8_t m_ExpandedPrivateKey[64]; + uint8_t m_ExpandedPrivateKey[64]; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; }; @@ -456,22 +456,22 @@ namespace crypto } - // ГОСТ Р 34.11 + // ГОСТ Р 34.11 struct GOSTR3411_256_Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { - GOSTR3411_2012_256 (buf, len, digest); + GOSTR3411_2012_256 (buf, len, digest); } enum { hashLen = 32 }; }; struct GOSTR3411_512_Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { - GOSTR3411_2012_512 (buf, len, digest); + GOSTR3411_2012_512 (buf, len, digest); } enum { hashLen = 64 }; @@ -487,7 +487,7 @@ namespace crypto public: enum { keyLen = Hash::hashLen }; - + GOSTR3410Verifier (GOSTR3410ParamSet paramSet, const uint8_t * signingKey): m_ParamSet (paramSet) { @@ -497,7 +497,7 @@ namespace crypto BN_free (x); BN_free (y); } ~GOSTR3410Verifier () { EC_POINT_free (m_PublicKey); } - + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { uint8_t digest[Hash::hashLen]; @@ -506,7 +506,7 @@ namespace crypto BIGNUM * r = BN_bin2bn (signature, GetSignatureLen ()/2, NULL); BIGNUM * s = BN_bin2bn (signature + GetSignatureLen ()/2, GetSignatureLen ()/2, NULL); bool ret = GetGOSTR3410Curve (m_ParamSet)->Verify (m_PublicKey, d, r, s); - BN_free (d); BN_free (r); BN_free (s); + BN_free (d); BN_free (r); BN_free (s); return ret; } @@ -517,7 +517,7 @@ namespace crypto GOSTR3410ParamSet m_ParamSet; EC_POINT * m_PublicKey; - }; + }; template class GOSTR3410Signer: public Signer @@ -525,11 +525,11 @@ namespace crypto public: enum { keyLen = Hash::hashLen }; - + GOSTR3410Signer (GOSTR3410ParamSet paramSet, const uint8_t * signingPrivateKey): m_ParamSet (paramSet) - { - m_PrivateKey = BN_bin2bn (signingPrivateKey, keyLen, nullptr); + { + m_PrivateKey = BN_bin2bn (signingPrivateKey, keyLen, nullptr); } ~GOSTR3410Signer () { BN_free (m_PrivateKey); } @@ -537,19 +537,19 @@ namespace crypto { uint8_t digest[Hash::hashLen]; Hash::CalculateHash (buf, len, digest); - BIGNUM * d = BN_bin2bn (digest, Hash::hashLen, nullptr); + BIGNUM * d = BN_bin2bn (digest, Hash::hashLen, nullptr); BIGNUM * r = BN_new (), * s = BN_new (); GetGOSTR3410Curve (m_ParamSet)->Sign (m_PrivateKey, d, r, s); bn2buf (r, signature, keyLen); bn2buf (s, signature + keyLen, keyLen); BN_free (d); BN_free (r); BN_free (s); } - + private: GOSTR3410ParamSet m_ParamSet; BIGNUM * m_PrivateKey; - }; + }; inline void CreateGOSTR3410RandomKeys (GOSTR3410ParamSet paramSet, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { @@ -557,7 +557,7 @@ namespace crypto auto keyLen = curve->GetKeyLen (); RAND_bytes (signingPrivateKey, keyLen); BIGNUM * priv = BN_bin2bn (signingPrivateKey, keyLen, nullptr); - + auto pub = curve->MulP (priv); BN_free (priv); BIGNUM * x = BN_new (), * y = BN_new (); @@ -565,7 +565,7 @@ namespace crypto EC_POINT_free (pub); bn2buf (x, signingPublicKey, keyLen); bn2buf (y, signingPublicKey + keyLen, keyLen); - BN_free (x); BN_free (y); + BN_free (x); BN_free (y); } typedef GOSTR3410Verifier GOSTR3410_256_Verifier; diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 16ccf555..37d9d2c4 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -12,11 +12,11 @@ namespace i2p namespace stream { void SendBufferQueue::Add (const uint8_t * buf, size_t len, SendHandler handler) - { + { m_Buffers.push_back (std::make_shared(buf, len, handler)); m_Size += len; } - + size_t SendBufferQueue::Get (uint8_t * buf, size_t len) { size_t offset = 0; @@ -30,7 +30,7 @@ namespace stream memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem); offset += rem; m_Buffers.pop_front (); // delete it - } + } else { // partially @@ -38,23 +38,23 @@ namespace stream memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), len - offset); nextBuffer->offset += (len - offset); offset = len; // break - } - } + } + } m_Size -= offset; return offset; - } + } - void SendBufferQueue::CleanUp () - { + void SendBufferQueue::CleanUp () + { if (!m_Buffers.empty ()) - { + { for (auto it: m_Buffers) it->Cancel (); - m_Buffers.clear (); + m_Buffers.clear (); m_Size = 0; - } + } } - + Stream::Stream (boost::asio::io_service& service, StreamingDestination& local, std::shared_ptr remote, int port): m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), @@ -100,7 +100,7 @@ namespace stream { std::unique_lock l(m_SendBufferMutex); m_SendBuffer.CleanUp (); - } + } while (!m_ReceiveQueue.empty ()) { auto packet = m_ReceiveQueue.front (); @@ -1108,7 +1108,7 @@ namespace stream } else // we must save old acceptor and set it back { - m_Acceptor = std::bind (&StreamingDestination::AcceptOnceAcceptor, this, + m_Acceptor = std::bind (&StreamingDestination::AcceptOnceAcceptor, this, std::placeholders::_1, acceptor, m_Acceptor); } }); @@ -1118,8 +1118,8 @@ namespace stream { m_Acceptor = prev; acceptor (stream); - } - + } + void StreamingDestination::HandlePendingIncomingTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 93cf2a9f..887f21c2 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -41,40 +41,40 @@ namespace stream const size_t STREAMING_MTU = 1730; const size_t MAX_PACKET_SIZE = 4096; - const size_t COMPRESSION_THRESHOLD_SIZE = 66; - const int MAX_NUM_RESEND_ATTEMPTS = 6; + const size_t COMPRESSION_THRESHOLD_SIZE = 66; + const int MAX_NUM_RESEND_ATTEMPTS = 6; const int WINDOW_SIZE = 6; // in messages const int MIN_WINDOW_SIZE = 1; - const int MAX_WINDOW_SIZE = 128; + const int MAX_WINDOW_SIZE = 128; const int INITIAL_RTT = 8000; // in milliseconds const int INITIAL_RTO = 9000; // in milliseconds const int SYN_TIMEOUT = 200; // how long we wait for SYN after follow-on, in milliseconds const size_t MAX_PENDING_INCOMING_BACKLOG = 128; const int PENDING_INCOMING_TIMEOUT = 10; // in seconds - const int MAX_RECEIVE_TIMEOUT = 30; // 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"; /** default maximum connections attempts per minute per destination */ const uint32_t DEFAULT_MAX_CONNS_PER_MIN = 600; - /** + /** * max banned destinations per local destination * TODO: make configurable */ const uint16_t MAX_BANNED_CONNS = 9999; - /** + /** * length of a ban in ms - * TODO: make configurable + * TODO: make configurable */ const uint64_t DEFAULT_BAN_INTERVAL = 60 * 60 * 1000; - + struct Packet { size_t len, offset; - uint8_t buf[MAX_PACKET_SIZE]; + uint8_t buf[MAX_PACKET_SIZE]; uint64_t sendTime; - + Packet (): len (0), offset (0), sendTime (0) {}; uint8_t * GetBuffer () { return buf + offset; }; size_t GetLength () const { return len - offset; }; @@ -93,15 +93,15 @@ namespace stream bool IsSYN () const { return GetFlags () & PACKET_FLAG_SYNCHRONIZE; }; bool IsNoAck () const { return GetFlags () & PACKET_FLAG_NO_ACK; }; - }; + }; struct PacketCmp { bool operator() (const Packet * p1, const Packet * p2) const - { - return p1->GetSeqn () < p2->GetSeqn (); + { + return p1->GetSeqn () < p2->GetSeqn (); }; - }; + }; typedef std::function SendHandler; struct SendBuffer @@ -115,16 +115,16 @@ namespace stream { buf = new uint8_t[len]; memcpy (buf, b, len); - } + } ~SendBuffer () { delete[] buf; if (handler) handler(boost::system::error_code ()); - } + } size_t GetRemainingSize () const { return len - offset; }; - const uint8_t * GetRemaningBuffer () const { return buf + offset; }; + const uint8_t * GetRemaningBuffer () const { return buf + offset; }; void Cancel () { if (handler) handler (boost::asio::error::make_error_code (boost::asio::error::operation_aborted)); handler = nullptr; }; - }; + }; class SendBufferQueue { @@ -133,18 +133,18 @@ namespace stream SendBufferQueue (): m_Size (0) {}; ~SendBufferQueue () { CleanUp (); }; - void Add (const uint8_t * buf, size_t len, SendHandler handler); - size_t Get (uint8_t * buf, size_t len); + void Add (const uint8_t * buf, size_t len, SendHandler handler); + size_t Get (uint8_t * buf, size_t len); size_t GetSize () const { return m_Size; }; bool IsEmpty () const { return m_Buffers.empty (); }; void CleanUp (); - - private: + + private: std::list > m_Buffers; size_t m_Size; - }; - + }; + enum StreamStatus { eStreamStatusNew = 0, @@ -152,16 +152,16 @@ namespace stream eStreamStatusReset, eStreamStatusClosing, eStreamStatusClosed - }; - + }; + class StreamingDestination; class Stream: public std::enable_shared_from_this - { + { public: - Stream (boost::asio::io_service& service, StreamingDestination& local, + Stream (boost::asio::io_service& service, StreamingDestination& local, std::shared_ptr remote, int port = 0); // outgoing - Stream (boost::asio::io_service& service, StreamingDestination& local); // incoming + Stream (boost::asio::io_service& service, StreamingDestination& local); // incoming ~Stream (); uint32_t GetSendStreamID () const { return m_SendStreamID; }; @@ -172,15 +172,15 @@ namespace stream bool IsEstablished () const { return m_SendStreamID; }; StreamStatus GetStatus () const { return m_Status; }; StreamingDestination& GetLocalDestination () { return m_LocalDestination; }; - + void HandleNextPacket (Packet * packet); size_t Send (const uint8_t * buf, size_t len); void AsyncSend (const uint8_t * buf, size_t len, SendHandler handler); - + template void AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout = 0); size_t ReadSome (uint8_t * buf, size_t len) { return ConcatenatePackets (buf, len); }; - + void Close (); void Cancel () { m_ReceiveTimer.cancel (); }; @@ -194,11 +194,11 @@ namespace stream /** don't call me */ void Terminate (); - + private: void CleanUp (); - + void SendBuffer (); void SendQuickAck (); void SendClose (); @@ -212,14 +212,14 @@ namespace stream size_t ConcatenatePackets (uint8_t * buf, size_t len); void UpdateCurrentRemoteLease (bool expired = false); - + template 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); void HandleAckSendTimer (const boost::system::error_code& ecode); - + private: boost::asio::io_service& m_Service; @@ -254,16 +254,16 @@ namespace stream typedef std::function)> Acceptor; StreamingDestination (std::shared_ptr owner, uint16_t localPort = 0, bool gzip = true); - ~StreamingDestination (); + ~StreamingDestination (); void Start (); void Stop (); std::shared_ptr CreateNewOutgoingStream (std::shared_ptr remote, int port = 0); - void DeleteStream (std::shared_ptr stream); + void DeleteStream (std::shared_ptr stream); void SetAcceptor (const Acceptor& acceptor); void ResetAcceptor (); - bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; + bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; void AcceptOnce (const Acceptor& acceptor); std::shared_ptr GetOwner () const { return m_Owner; }; @@ -278,11 +278,11 @@ namespace stream Packet * NewPacket () { return m_PacketsPool.Acquire (); } void DeletePacket (Packet * p) { m_PacketsPool.Release (p); } - - private: + + private: void AcceptOnceAcceptor (std::shared_ptr stream, Acceptor acceptor, Acceptor prev); - + void HandleNextPacket (Packet * packet); std::shared_ptr CreateNewIncomingStream (); void HandlePendingIncomingTimer (const boost::system::error_code& ecode); @@ -293,7 +293,7 @@ namespace stream bool DropNewStream(const i2p::data::IdentHash & ident); void ScheduleConnTrack(); - + private: std::shared_ptr m_Owner; @@ -306,7 +306,7 @@ namespace stream std::list > m_PendingIncomingStreams; boost::asio::deadline_timer m_PendingIncomingTimer; std::map > m_SavedPackets; // receiveStreamID->packets, arrived before SYN - + std::mutex m_ConnsMutex; /** how many connections per minute did each identity have */ std::map m_Conns; @@ -318,15 +318,15 @@ namespace stream i2p::util::MemoryPool m_PacketsPool; bool m_EnableDrop; - + public: i2p::data::GzipInflator m_Inflator; i2p::data::GzipDeflator m_Deflator; - + // for HTTP only const decltype(m_Streams)& GetStreams () const { return m_Streams; }; - }; + }; //------------------------------------------------- @@ -345,7 +345,7 @@ namespace stream s->m_ReceiveTimer.async_wait ([=](const boost::system::error_code& ecode) { s->HandleReceiveTimer (ecode, buffer, handler, timeout - t); }); } - }); + }); } template @@ -355,27 +355,27 @@ namespace stream if (received > 0) handler (boost::system::error_code (), received); else if (ecode == boost::asio::error::operation_aborted) - { - // timeout not expired + { + // timeout not expired if (m_Status == eStreamStatusReset) handler (boost::asio::error::make_error_code (boost::asio::error::connection_reset), 0); else - handler (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), 0); - } + handler (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), 0); + } else - { + { // timeout expired 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); - } - } + AsyncReceive (buffer, handler, remainingTimeout); + } + } } -} -} +} +} #endif diff --git a/libi2pd/Tag.h b/libi2pd/Tag.h index 3977fd29..03e3bc06 100644 --- a/libi2pd/Tag.h +++ b/libi2pd/Tag.h @@ -56,7 +56,7 @@ public: { RAND_bytes(m_Buf, sz); } - + std::string ToBase64 () const { char str[sz*2]; diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index 3131fb6a..9e9b4e63 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -40,7 +40,7 @@ namespace util int i = 0; while (!socket.available() && i < 10) // 10 seconds max { - std::this_thread::sleep_for (std::chrono::seconds(1)); + std::this_thread::sleep_for (std::chrono::seconds(1)); i++; } if (socket.available ()) diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp index bcba4d60..1adc4178 100644 --- a/libi2pd/TransitTunnel.cpp +++ b/libi2pd/TransitTunnel.cpp @@ -10,58 +10,58 @@ namespace i2p { namespace tunnel -{ - TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey): +{ + TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey): TunnelBase (receiveTunnelID, nextTunnelID, nextIdent) - { + { m_Encryption.SetKeys (layerKey, ivKey); - } + } void TransitTunnel::EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out) - { - m_Encryption.Encrypt (in->GetPayload () + 4, out->GetPayload () + 4); + { + m_Encryption.Encrypt (in->GetPayload () + 4, out->GetPayload () + 4); i2p::transport::transports.UpdateTotalTransitTransmittedBytes (TUNNEL_DATA_MSG_SIZE); - } + } TransitTunnelParticipant::~TransitTunnelParticipant () { - } - + } + void TransitTunnelParticipant::HandleTunnelDataMsg (std::shared_ptr tunnelMsg) { auto newMsg = CreateEmptyTunnelDataMsg (); EncryptTunnelMsg (tunnelMsg, newMsg); - + m_NumTransmittedBytes += tunnelMsg->GetLength (); htobe32buf (newMsg->GetPayload (), GetNextTunnelID ()); - newMsg->FillI2NPMessageHeader (eI2NPTunnelData); + newMsg->FillI2NPMessageHeader (eI2NPTunnelData); m_TunnelDataMsgs.push_back (newMsg); } void TransitTunnelParticipant::FlushTunnelDataMsgs () { if (!m_TunnelDataMsgs.empty ()) - { + { auto num = m_TunnelDataMsgs.size (); if (num > 1) LogPrint (eLogDebug, "TransitTunnel: ", GetTunnelID (), "->", GetNextTunnelID (), " ", num); i2p::transport::transports.SendMessages (GetNextIdentHash (), m_TunnelDataMsgs); m_TunnelDataMsgs.clear (); - } - } - + } + } + void TransitTunnel::SendTunnelDataMsg (std::shared_ptr msg) - { + { LogPrint (eLogError, "TransitTunnel: We are not a gateway for ", GetTunnelID ()); - } + } void TransitTunnel::HandleTunnelDataMsg (std::shared_ptr tunnelMsg) { LogPrint (eLogError, "TransitTunnel: Incoming tunnel message is not supported ", GetTunnelID ()); - } - + } + void TransitTunnelGateway::SendTunnelDataMsg (std::shared_ptr msg) { TunnelMessageBlock block; @@ -69,43 +69,43 @@ namespace tunnel block.data = msg; std::unique_lock l(m_SendMutex); m_Gateway.PutTunnelDataMsg (block); - } + } void TransitTunnelGateway::FlushTunnelDataMsgs () { std::unique_lock l(m_SendMutex); m_Gateway.SendBuffer (); - } - + } + void TransitTunnelEndpoint::HandleTunnelDataMsg (std::shared_ptr tunnelMsg) { auto newMsg = CreateEmptyTunnelDataMsg (); EncryptTunnelMsg (tunnelMsg, newMsg); - + LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ()); - m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); + m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); } - + std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey, + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey, bool isGateway, bool isEndpoint) { if (isEndpoint) - { + { LogPrint (eLogDebug, "TransitTunnel: endpoint ", receiveTunnelID, " created"); return std::make_shared (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey); - } + } else if (isGateway) - { + { LogPrint (eLogInfo, "TransitTunnel: gateway ", receiveTunnelID, " created"); return std::make_shared (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey); - } - else - { + } + else + { LogPrint (eLogDebug, "TransitTunnel: ", receiveTunnelID, "->", nextTunnelID, " created"); return std::make_shared (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey); - } - } + } + } } } diff --git a/libi2pd/TransitTunnel.h b/libi2pd/TransitTunnel.h index eec244ce..4dbeb3b5 100644 --- a/libi2pd/TransitTunnel.h +++ b/libi2pd/TransitTunnel.h @@ -14,34 +14,34 @@ namespace i2p { namespace tunnel -{ - class TransitTunnel: public TunnelBase +{ + class TransitTunnel: public TunnelBase { public: TransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey); - + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey); + virtual size_t GetNumTransmittedBytes () const { return 0; }; // implements TunnelBase void SendTunnelDataMsg (std::shared_ptr msg); void HandleTunnelDataMsg (std::shared_ptr tunnelMsg); - void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); + void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); private: - + i2p::crypto::TunnelEncryption m_Encryption; - }; + }; class TransitTunnelParticipant: public TransitTunnel { public: TransitTunnelParticipant (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * nextIdent, uint32_t nextTunnelID, const uint8_t * layerKey,const uint8_t * ivKey): - TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, + TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_NumTransmittedBytes (0) {}; ~TransitTunnelParticipant (); @@ -53,51 +53,51 @@ namespace tunnel size_t m_NumTransmittedBytes; std::vector > m_TunnelDataMsgs; - }; - + }; + class TransitTunnelGateway: public TransitTunnel { public: TransitTunnelGateway (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * nextIdent, uint32_t nextTunnelID, const uint8_t * layerKey,const uint8_t * ivKey): - TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, + TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_Gateway(this) {}; void SendTunnelDataMsg (std::shared_ptr msg); void FlushTunnelDataMsgs (); size_t GetNumTransmittedBytes () const { return m_Gateway.GetNumSentBytes (); }; - + private: std::mutex m_SendMutex; TunnelGateway m_Gateway; - }; + }; class TransitTunnelEndpoint: public TransitTunnel { public: TransitTunnelEndpoint (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * nextIdent, uint32_t nextTunnelID, const uint8_t * layerKey,const uint8_t * ivKey): TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_Endpoint (false) {}; // transit endpoint is always outbound void Cleanup () { m_Endpoint.Cleanup (); } - + void HandleTunnelDataMsg (std::shared_ptr tunnelMsg); size_t GetNumTransmittedBytes () const { return m_Endpoint.GetNumReceivedBytes (); } - + private: TunnelEndpoint m_Endpoint; }; - + std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey, + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey, bool isGateway, bool isEndpoint); } } diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 5950fb06..62bed352 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -20,42 +20,42 @@ namespace transport public: SignedData () {} - SignedData (const SignedData& other) + SignedData (const SignedData& other) { m_Stream << other.m_Stream.rdbuf (); - } - void Insert (const uint8_t * buf, size_t len) - { - m_Stream.write ((char *)buf, len); - } + } + void Insert (const uint8_t * buf, size_t len) + { + m_Stream.write ((char *)buf, len); + } template void Insert (T t) { - m_Stream.write ((char *)&t, sizeof (T)); + m_Stream.write ((char *)&t, sizeof (T)); } bool Verify (std::shared_ptr ident, const uint8_t * signature) const { - return ident->Verify ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); + return ident->Verify ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); } void Sign (const i2p::data::PrivateKeys& keys, uint8_t * signature) const { - keys.Sign ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); - } + keys.Sign ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); + } private: - + std::stringstream m_Stream; - }; + }; class TransportSession { public: - TransportSession (std::shared_ptr router, int terminationTimeout): - m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), + TransportSession (std::shared_ptr router, int terminationTimeout): + m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()) { if (router) @@ -66,30 +66,30 @@ namespace transport virtual void Done () = 0; std::string GetIdentHashBase64() const { return m_RemoteIdentity ? m_RemoteIdentity->GetIdentHash().ToBase64() : ""; } - + std::shared_ptr GetRemoteIdentity () { return m_RemoteIdentity; }; void SetRemoteIdentity (std::shared_ptr ident) { m_RemoteIdentity = ident; }; - + size_t GetNumSentBytes () const { return m_NumSentBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; bool IsOutgoing () const { return m_IsOutgoing; }; - + int GetTerminationTimeout () const { return m_TerminationTimeout; }; - void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; - bool IsTerminationTimeoutExpired (uint64_t ts) const - { return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); }; + void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; + bool IsTerminationTimeoutExpired (uint64_t ts) const + { return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); }; virtual void SendI2NPMessages (const std::vector >& msgs) = 0; - + protected: - std::shared_ptr m_RemoteIdentity; + std::shared_ptr m_RemoteIdentity; std::shared_ptr m_DHKeysPair; // X - for client and Y - for server size_t m_NumSentBytes, m_NumReceivedBytes; bool m_IsOutgoing; int m_TerminationTimeout; uint64_t m_LastActivityTimestamp; - }; + }; } } diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 6ae1e119..e2c12b83 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -2,7 +2,7 @@ #include "I2PEndian.h" #include #include -#include +#include #include "Crypto.h" #include "RouterContext.h" #include "Log.h" @@ -20,8 +20,8 @@ namespace i2p { namespace tunnel -{ - Tunnel::Tunnel (std::shared_ptr config): +{ + Tunnel::Tunnel (std::shared_ptr config): TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()), m_Config (config), m_Pool (nullptr), m_State (eTunnelStatePending), m_IsRecreated (false), m_Latency (0) @@ -38,7 +38,7 @@ namespace tunnel std::string peers = i2p::context.GetIdentity()->GetIdentHash().ToBase64(); #endif auto numHops = m_Config->GetNumHops (); - int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops; + int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops; auto msg = NewI2NPShortMessage (); *msg->GetPayload () = numRecords; msg->len += numRecords*TUNNEL_BUILD_RECORD_SIZE + 1; @@ -48,20 +48,20 @@ namespace tunnel std::random_shuffle (recordIndicies.begin(), recordIndicies.end()); // create real records - uint8_t * records = msg->GetPayload () + 1; + uint8_t * records = msg->GetPayload () + 1; TunnelHopConfig * hop = m_Config->GetFirstHop (); int i = 0; BN_CTX * ctx = BN_CTX_new (); while (hop) { uint32_t msgID; - if (hop->next) // we set replyMsgID for last hop only + if (hop->next) // we set replyMsgID for last hop only RAND_bytes ((uint8_t *)&msgID, 4); else msgID = replyMsgID; int idx = recordIndicies[i]; - hop->CreateBuildRequestRecord (records + idx*TUNNEL_BUILD_RECORD_SIZE, msgID, ctx); - hop->recordIndex = idx; + hop->CreateBuildRequestRecord (records + idx*TUNNEL_BUILD_RECORD_SIZE, msgID, ctx); + hop->recordIndex = idx; i++; #ifdef WITH_EVENTS peers += ":" + hop->ident->GetIdentHash().ToBase64(); @@ -76,7 +76,7 @@ namespace tunnel for (int i = numHops; i < numRecords; i++) { int idx = recordIndicies[i]; - RAND_bytes (records + idx*TUNNEL_BUILD_RECORD_SIZE, TUNNEL_BUILD_RECORD_SIZE); + RAND_bytes (records + idx*TUNNEL_BUILD_RECORD_SIZE, TUNNEL_BUILD_RECORD_SIZE); } // decrypt real records @@ -110,7 +110,7 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: TunnelBuildResponse ", (int)msg[0], " records."); i2p::crypto::CBCDecryption decryption; - TunnelHopConfig * hop = m_Config->GetLastHop (); + TunnelHopConfig * hop = m_Config->GetLastHop (); while (hop) { decryption.SetKey (hop->replyKey); @@ -142,12 +142,12 @@ namespace tunnel auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ()); if (profile) profile->TunnelBuildResponse (ret); - if (ret) + if (ret) // if any of participants declined the tunnel is not established - established = false; + established = false; hop = hop->next; } - if (established) + if (established) { // create tunnel decryptions from layer and iv keys in reverse order hop = m_Config->GetLastHop (); @@ -170,7 +170,7 @@ namespace tunnel auto latency = GetMeanLatency(); return latency >= lower && latency <= upper; } - + void Tunnel::EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out) { const uint8_t * inPayload = in->GetPayload () + 4; @@ -178,7 +178,7 @@ namespace tunnel for (auto& it: m_Hops) { it->decryption.Decrypt (inPayload, outPayload); - inPayload = outPayload; + inPayload = outPayload; } } @@ -210,11 +210,11 @@ namespace tunnel EmitTunnelEvent("tunnel.state", this, state); #endif } - + void Tunnel::PrintHops (std::stringstream& s) const { - // hops are in inverted order, we must print in direct order + // hops are in inverted order, we must print in direct order for (auto it = m_Hops.rbegin (); it != m_Hops.rend (); it++) { s << " ⇒ "; @@ -354,7 +354,7 @@ namespace tunnel { return GetPendingTunnel (replyMsgID, m_PendingInboundTunnels); } - + std::shared_ptr Tunnels::GetPendingOutboundTunnel (uint32_t replyMsgID) { return GetPendingTunnel (replyMsgID, m_PendingOutboundTunnels); @@ -374,7 +374,7 @@ namespace tunnel std::shared_ptr Tunnels::GetNextInboundTunnel () { - std::shared_ptr tunnel; + std::shared_ptr tunnel; size_t minReceived = 0; for (const auto& it : m_InboundTunnels) { @@ -405,7 +405,7 @@ namespace tunnel return tunnel; } - std::shared_ptr Tunnels::CreateTunnelPool (int numInboundHops, + std::shared_ptr Tunnels::CreateTunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels) { auto pool = std::make_shared (numInboundHops, numOutboundHops, numInboundTunnels, numOutboundTunnels); @@ -434,7 +434,7 @@ namespace tunnel pool->DetachTunnels (); } } - + void Tunnels::AddTransitTunnel (std::shared_ptr tunnel) { if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second) @@ -455,7 +455,7 @@ namespace tunnel m_Queue.WakeUp (); if (m_Thread) { - m_Thread->join (); + m_Thread->join (); delete m_Thread; m_Thread = 0; } @@ -484,11 +484,11 @@ namespace tunnel case eI2NPTunnelData: case eI2NPTunnelGateway: { - tunnelID = bufbe32toh (msg->GetPayload ()); + tunnelID = bufbe32toh (msg->GetPayload ()); if (tunnelID == prevTunnelID) tunnel = prevTunnel; else if (prevTunnel) - prevTunnel->FlushTunnelDataMsgs (); + prevTunnel->FlushTunnelDataMsgs (); if (!tunnel) tunnel = GetTunnel (tunnelID); @@ -561,9 +561,9 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID); if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply) - // transit DatabaseStore my contain new/updated RI + // transit DatabaseStore my contain new/updated RI // or DatabaseSearchReply with new routers - i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg)); + i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg)); tunnel->SendTunnelDataMsg (msg); } @@ -593,7 +593,7 @@ namespace tunnel auto pool = tunnel->GetTunnelPool(); switch (tunnel->GetState ()) { - case eTunnelStatePending: + case eTunnelStatePending: if (ts > tunnel->GetCreationTime () + TUNNEL_CREATION_TIMEOUT) { LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " timeout, deleted"); @@ -632,7 +632,7 @@ namespace tunnel #endif // for i2lua if(pool) pool->OnTunnelBuildResult(tunnel, eBuildResultRejected); - + it = pendingTunnels.erase (it); m_NumFailedTunnelCreations++; break; @@ -664,7 +664,7 @@ namespace tunnel // we don't have outbound tunnels in m_Tunnels it = m_OutboundTunnels.erase (it); } - else + else { if (tunnel->IsEstablished ()) { @@ -683,7 +683,7 @@ namespace tunnel } } - if (m_OutboundTunnels.size () < 3) + if (m_OutboundTunnels.size () < 3) { // trying to create one more oubound tunnel auto inboundTunnel = GetNextInboundTunnel (); @@ -715,7 +715,7 @@ namespace tunnel m_Tunnels.erase (tunnel->GetTunnelID ()); it = m_InboundTunnels.erase (it); } - else + else { if (tunnel->IsEstablished ()) { @@ -748,13 +748,13 @@ namespace tunnel int obLen; i2p::config::GetOption("exploratory.outbound.length", obLen); int ibNum; i2p::config::GetOption("exploratory.inbound.quantity", ibNum); int obNum; i2p::config::GetOption("exploratory.outbound.quantity", obNum); - m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum); + m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum); m_ExploratoryPool->SetLocalDestination (i2p::context.GetSharedDestination ()); } return; } - if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 3) + if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 3) { // trying to create one more inbound tunnel auto router = i2p::transport::transports.RoutesRestricted() ? @@ -783,7 +783,7 @@ namespace tunnel m_Tunnels.erase (tunnel->GetTunnelID ()); it = m_TransitTunnels.erase (it); } - else + else { tunnel->Cleanup (); it++; @@ -820,14 +820,14 @@ namespace tunnel auto newTunnel = std::make_shared (config); uint32_t replyMsgID; RAND_bytes ((uint8_t *)&replyMsgID, 4); - AddPendingTunnel (replyMsgID, newTunnel); + AddPendingTunnel (replyMsgID, newTunnel); newTunnel->Build (replyMsgID, outboundTunnel); return newTunnel; } std::shared_ptr Tunnels::CreateInboundTunnel (std::shared_ptr config, std::shared_ptr outboundTunnel) { - if (config) + if (config) return CreateTunnel(config, outboundTunnel); else return CreateZeroHopsInboundTunnel (); @@ -843,12 +843,12 @@ namespace tunnel void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel) { - m_PendingInboundTunnels[replyMsgID] = tunnel; + m_PendingInboundTunnels[replyMsgID] = tunnel; } void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel) { - m_PendingOutboundTunnels[replyMsgID] = tunnel; + m_PendingOutboundTunnels[replyMsgID] = tunnel; } void Tunnels::AddOutboundTunnel (std::shared_ptr newTunnel) @@ -872,7 +872,7 @@ namespace tunnel { // build symmetric outbound tunnel CreateTunnel (std::make_shared(newTunnel->GetInvertedPeers (), - newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash ()), + newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash ()), GetNextOutboundTunnel ()); } else diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 0c90c36c..38beccaa 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -36,7 +36,7 @@ namespace tunnel (void) t; #endif } - + template static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const T & val) { @@ -46,7 +46,7 @@ namespace tunnel (void) ev; (void) t; (void) val; -#endif +#endif } template @@ -58,13 +58,13 @@ namespace tunnel (void) ev; (void) t; (void) val; -#endif +#endif } - - const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes - const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute - const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes + + const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes + const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute + const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes const int TUNNEL_CREATION_TIMEOUT = 30; // 30 seconds const int STANDARD_NUM_RECORDS = 5; // in VariableTunnelBuild message @@ -77,8 +77,8 @@ namespace tunnel eTunnelStateTestFailed, eTunnelStateFailed, eTunnelStateExpiring - }; - + }; + class OutboundTunnel; class InboundTunnel; class Tunnel: public TunnelBase @@ -87,18 +87,18 @@ namespace tunnel { std::shared_ptr ident; i2p::crypto::TunnelDecryption decryption; - }; - + }; + public: Tunnel (std::shared_ptr config); ~Tunnel (); void Build (uint32_t replyMsgID, std::shared_ptr outboundTunnel = nullptr); - + std::shared_ptr GetTunnelConfig () const { return m_Config; } - std::vector > GetPeers () const; - std::vector > GetInvertedPeers () const; + std::vector > GetPeers () const; + std::vector > GetInvertedPeers () const; TunnelState GetState () const { return m_State; }; void SetState (TunnelState state); bool IsEstablished () const { return m_State == eTunnelStateEstablished; }; @@ -106,17 +106,17 @@ namespace tunnel bool IsRecreated () const { return m_IsRecreated; }; void SetIsRecreated () { m_IsRecreated = true; }; virtual bool IsInbound() const = 0; - + std::shared_ptr GetTunnelPool () const { return m_Pool; }; - void SetTunnelPool (std::shared_ptr pool) { m_Pool = pool; }; - + void SetTunnelPool (std::shared_ptr pool) { m_Pool = pool; }; + bool HandleTunnelBuildResponse (uint8_t * msg, size_t len); virtual void Print (std::stringstream&) const {}; - + // implements TunnelBase void SendTunnelDataMsg (std::shared_ptr msg); - void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); + void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); /** @brief add latency sample */ void AddLatencySample(const uint64_t ms) { m_Latency = (m_Latency + ms) >> 1; } @@ -124,12 +124,12 @@ namespace tunnel uint64_t GetMeanLatency() const { return m_Latency; } /** @brief return true if this tunnel's latency fits in range [lowerbound, upperbound] */ bool LatencyFitsRange(uint64_t lowerbound, uint64_t upperbound) const; - + bool LatencyIsKnown() const { return m_Latency > 0; } protected: void PrintHops (std::stringstream& s) const; - + private: std::shared_ptr m_Config; @@ -138,30 +138,30 @@ namespace tunnel TunnelState m_State; bool m_IsRecreated; uint64_t m_Latency; // in milliseconds - }; + }; - class OutboundTunnel: public Tunnel + class OutboundTunnel: public Tunnel { public: - OutboundTunnel (std::shared_ptr config): + OutboundTunnel (std::shared_ptr config): Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {}; void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg); virtual void SendTunnelDataMsg (const std::vector& msgs); // multiple messages - const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }; + const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }; virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }; void Print (std::stringstream& s) const; - + // implements TunnelBase void HandleTunnelDataMsg (std::shared_ptr tunnelMsg); bool IsInbound() const { return false; } - + private: std::mutex m_SendMutex; - TunnelGateway m_Gateway; + TunnelGateway m_Gateway; i2p::data::IdentHash m_EndpointIdentHash; }; @@ -176,27 +176,27 @@ namespace tunnel bool IsInbound() const { return true; } // override TunnelBase - void Cleanup () { m_Endpoint.Cleanup (); }; + void Cleanup () { m_Endpoint.Cleanup (); }; private: - TunnelEndpoint m_Endpoint; - }; - + TunnelEndpoint m_Endpoint; + }; + class ZeroHopsInboundTunnel: public InboundTunnel { public: ZeroHopsInboundTunnel (); - void SendTunnelDataMsg (std::shared_ptr msg); + void SendTunnelDataMsg (std::shared_ptr msg); void Print (std::stringstream& s) const; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; - + private: size_t m_NumReceivedBytes; - }; - + }; + class ZeroHopsOutboundTunnel: public OutboundTunnel { public: @@ -205,23 +205,23 @@ namespace tunnel void SendTunnelDataMsg (const std::vector& msgs); void Print (std::stringstream& s) const; size_t GetNumSentBytes () const { return m_NumSentBytes; }; - + private: size_t m_NumSentBytes; - }; + }; class Tunnels - { + { public: Tunnels (); ~Tunnels (); void Start (); - void Stop (); - - std::shared_ptr GetPendingInboundTunnel (uint32_t replyMsgID); - std::shared_ptr GetPendingOutboundTunnel (uint32_t replyMsgID); + void Stop (); + + std::shared_ptr GetPendingInboundTunnel (uint32_t replyMsgID); + std::shared_ptr GetPendingOutboundTunnel (uint32_t replyMsgID); std::shared_ptr GetNextInboundTunnel (); std::shared_ptr GetNextOutboundTunnel (); std::shared_ptr GetExploratoryPool () const { return m_ExploratoryPool; }; @@ -236,22 +236,22 @@ namespace tunnel void PostTunnelData (const std::vector >& msgs); void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel); void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel); - std::shared_ptr CreateTunnelPool (int numInboundHops, + std::shared_ptr CreateTunnelPool (int numInboundHops, int numOuboundHops, int numInboundTunnels, int numOutboundTunnels); void DeleteTunnelPool (std::shared_ptr pool); void StopTunnelPool (std::shared_ptr pool); - + private: - + template std::shared_ptr CreateTunnel (std::shared_ptr config, std::shared_ptr outboundTunnel = nullptr); template - std::shared_ptr GetPendingTunnel (uint32_t replyMsgID, const std::map >& pendingTunnels); + std::shared_ptr GetPendingTunnel (uint32_t replyMsgID, const std::map >& pendingTunnels); void HandleTunnelGatewayMsg (std::shared_ptr tunnel, std::shared_ptr msg); - void Run (); + void Run (); void ManageTunnels (); void ManageOutboundTunnels (); void ManageInboundTunnels (); @@ -260,14 +260,14 @@ namespace tunnel template void ManagePendingTunnels (PendingTunnels& pendingTunnels); void ManageTunnelPools (); - + std::shared_ptr CreateZeroHopsInboundTunnel (); - std::shared_ptr CreateZeroHopsOutboundTunnel (); + std::shared_ptr CreateZeroHopsOutboundTunnel (); private: bool m_IsRunning; - std::thread * m_Thread; + std::thread * m_Thread; std::map > m_PendingInboundTunnels; // by replyMsgID std::map > m_PendingOutboundTunnels; // by replyMsgID std::list > m_InboundTunnels; @@ -292,17 +292,17 @@ namespace tunnel size_t CountTransitTunnels() const; size_t CountInboundTunnels() const; size_t CountOutboundTunnels() const; - + int GetQueueSize () { return m_Queue.GetSize (); }; int GetTunnelCreationSuccessRate () const // in percents - { + { int totalNum = m_NumSuccesiveTunnelCreations + m_NumFailedTunnelCreations; return totalNum ? m_NumSuccesiveTunnelCreations*100/totalNum : 0; - } - }; + } + }; extern Tunnels tunnels; -} +} } #endif diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h index 770badf8..b07adf53 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -14,17 +14,17 @@ namespace tunnel const size_t TUNNEL_DATA_MSG_SIZE = 1028; const size_t TUNNEL_DATA_ENCRYPTED_SIZE = 1008; const size_t TUNNEL_DATA_MAX_PAYLOAD_SIZE = 1003; - - enum TunnelDeliveryType - { - eDeliveryTypeLocal = 0, + + enum TunnelDeliveryType + { + eDeliveryTypeLocal = 0, eDeliveryTypeTunnel = 1, eDeliveryTypeRouter = 2 - }; + }; struct TunnelMessageBlock { TunnelDeliveryType deliveryType; - i2p::data::IdentHash hash; + i2p::data::IdentHash hash; uint32_t tunnelID; std::shared_ptr data; }; @@ -33,12 +33,12 @@ namespace tunnel { public: - TunnelBase (uint32_t tunnelID, uint32_t nextTunnelID, i2p::data::IdentHash nextIdent): + TunnelBase (uint32_t tunnelID, uint32_t nextTunnelID, i2p::data::IdentHash nextIdent): m_TunnelID (tunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent), m_CreationTime (i2p::util::GetSecondsSinceEpoch ()) {}; virtual ~TunnelBase () {}; virtual void Cleanup () {}; - + virtual void HandleTunnelDataMsg (std::shared_ptr tunnelMsg) = 0; virtual void SendTunnelDataMsg (std::shared_ptr msg) = 0; virtual void FlushTunnelDataMsgs () {}; @@ -49,24 +49,24 @@ namespace tunnel uint32_t GetCreationTime () const { return m_CreationTime; }; void SetCreationTime (uint32_t t) { m_CreationTime = t; }; - + private: uint32_t m_TunnelID, m_NextTunnelID; i2p::data::IdentHash m_NextIdent; uint32_t m_CreationTime; // seconds since epoch - }; + }; struct TunnelCreationTimeCmp { bool operator() (std::shared_ptr t1, std::shared_ptr t2) const - { + { if (t1->GetCreationTime () != t2->GetCreationTime ()) - return t1->GetCreationTime () > t2->GetCreationTime (); + return t1->GetCreationTime () > t2->GetCreationTime (); else return t1 < t2; }; - }; + }; } } diff --git a/libi2pd/TunnelConfig.h b/libi2pd/TunnelConfig.h index 10e980ad..7267fc30 100644 --- a/libi2pd/TunnelConfig.h +++ b/libi2pd/TunnelConfig.h @@ -23,11 +23,11 @@ namespace tunnel uint8_t ivKey[32]; uint8_t replyKey[32]; uint8_t replyIV[16]; - bool isGateway, isEndpoint; - + bool isGateway, isEndpoint; + TunnelHopConfig * next, * prev; int recordIndex; // record # in tunnel build message - + TunnelHopConfig (std::shared_ptr r) { RAND_bytes (layerKey, 32); @@ -37,20 +37,20 @@ namespace tunnel RAND_bytes ((uint8_t *)&tunnelID, 4); isGateway = true; isEndpoint = true; - ident = r; - //nextRouter = nullptr; + ident = r; + //nextRouter = nullptr; nextTunnelID = 0; next = nullptr; prev = nullptr; - } + } void SetNextIdent (const i2p::data::IdentHash& ident) { nextIdent = ident; isEndpoint = false; RAND_bytes ((uint8_t *)&nextTunnelID, 4); - } + } void SetReplyHop (uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent) { @@ -58,35 +58,35 @@ namespace tunnel nextTunnelID = replyTunnelID; isEndpoint = true; } - + void SetNext (TunnelHopConfig * n) { next = n; if (next) - { + { next->prev = this; next->isGateway = false; isEndpoint = false; nextIdent = next->ident->GetIdentHash (); nextTunnelID = next->tunnelID; - } + } } void SetPrev (TunnelHopConfig * p) { prev = p; - if (prev) - { + if (prev) + { prev->next = this; prev->isEndpoint = false; isGateway = false; - } + } } void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx) const { uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; - htobe32buf (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); + htobe32buf (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); memcpy (clearText + BUILD_REQUEST_RECORD_OUR_IDENT_OFFSET, ident->GetIdentHash (), 32); htobe32buf (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID); memcpy (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, nextIdent, 32); @@ -98,44 +98,44 @@ namespace tunnel if (isGateway) flag |= 0x80; if (isEndpoint) flag |= 0x40; clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] = flag; - htobe32buf (clearText + BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetHoursSinceEpoch ()); - htobe32buf (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID); + htobe32buf (clearText + BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetHoursSinceEpoch ()); + htobe32buf (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID); RAND_bytes (clearText + BUILD_REQUEST_RECORD_PADDING_OFFSET, BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE - BUILD_REQUEST_RECORD_PADDING_OFFSET); i2p::crypto::ElGamalEncrypt (ident->GetEncryptionPublicKey (), clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx); memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); - } - }; + } + }; class TunnelConfig { - public: - + public: + TunnelConfig (std::vector > peers) // inbound { CreatePeers (peers); m_LastHop->SetNextIdent (i2p::context.GetIdentHash ()); } - TunnelConfig (std::vector > peers, + TunnelConfig (std::vector > peers, uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent) // outbound { CreatePeers (peers); m_FirstHop->isGateway = false; m_LastHop->SetReplyHop (replyTunnelID, replyIdent); } - + ~TunnelConfig () { TunnelHopConfig * hop = m_FirstHop; - + while (hop) { auto tmp = hop; hop = hop->next; delete tmp; - } + } } - + TunnelHopConfig * GetFirstHop () const { return m_FirstHop; @@ -149,63 +149,63 @@ namespace tunnel int GetNumHops () const { int num = 0; - TunnelHopConfig * hop = m_FirstHop; + TunnelHopConfig * hop = m_FirstHop; while (hop) { num++; hop = hop->next; - } + } return num; } bool IsEmpty () const { return !m_FirstHop; - } + } virtual bool IsInbound () const { return m_FirstHop->isGateway; } - virtual uint32_t GetTunnelID () const - { + virtual uint32_t GetTunnelID () const + { if (!m_FirstHop) return 0; - return IsInbound () ? m_LastHop->nextTunnelID : m_FirstHop->tunnelID; + return IsInbound () ? m_LastHop->nextTunnelID : m_FirstHop->tunnelID; } - virtual uint32_t GetNextTunnelID () const - { + virtual uint32_t GetNextTunnelID () const + { if (!m_FirstHop) return 0; - return m_FirstHop->tunnelID; + return m_FirstHop->tunnelID; } - virtual const i2p::data::IdentHash& GetNextIdentHash () const - { - return m_FirstHop->ident->GetIdentHash (); - } + virtual const i2p::data::IdentHash& GetNextIdentHash () const + { + return m_FirstHop->ident->GetIdentHash (); + } + + virtual const i2p::data::IdentHash& GetLastIdentHash () const + { + return m_LastHop->ident->GetIdentHash (); + } - virtual const i2p::data::IdentHash& GetLastIdentHash () const - { - return m_LastHop->ident->GetIdentHash (); - } - std::vector > GetPeers () const { std::vector > peers; - TunnelHopConfig * hop = m_FirstHop; + TunnelHopConfig * hop = m_FirstHop; while (hop) { peers.push_back (hop->ident); hop = hop->next; - } + } return peers; } - + protected: // this constructor can't be called from outside TunnelConfig (): m_FirstHop (nullptr), m_LastHop (nullptr) { } - + private: template @@ -217,13 +217,13 @@ namespace tunnel auto hop = new TunnelHopConfig (it); if (prev) prev->SetNext (hop); - else + else m_FirstHop = hop; prev = hop; - } + } m_LastHop = prev; } - + private: TunnelHopConfig * m_FirstHop, * m_LastHop; @@ -235,7 +235,7 @@ namespace tunnel ZeroHopsTunnelConfig () { RAND_bytes ((uint8_t *)&m_TunnelID, 4);}; - bool IsInbound () const { return true; }; // TODO: + bool IsInbound () const { return true; }; // TODO: uint32_t GetTunnelID () const { return m_TunnelID; }; uint32_t GetNextTunnelID () const { return m_TunnelID; }; const i2p::data::IdentHash& GetNextIdentHash () const { return i2p::context.GetIdentHash (); }; @@ -243,10 +243,10 @@ namespace tunnel private: - - uint32_t m_TunnelID; - }; -} -} + + uint32_t m_TunnelID; + }; +} +} #endif diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index aec53e66..eb922360 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -15,16 +15,16 @@ namespace tunnel { TunnelEndpoint::~TunnelEndpoint () { - } - + } + void TunnelEndpoint::HandleDecryptedTunnelDataMsg (std::shared_ptr msg) { m_NumReceivedBytes += TUNNEL_DATA_MSG_SIZE; - + uint8_t * decrypted = msg->GetPayload () + 20; // 4 + 16 uint8_t * zero = (uint8_t *)memchr (decrypted + 4, 0, TUNNEL_DATA_ENCRYPTED_SIZE - 4); // witout 4-byte checksum if (zero) - { + { uint8_t * fragment = zero + 1; // verify checksum memcpy (msg->GetPayload () + TUNNEL_DATA_MSG_SIZE, msg->GetPayload () + 4, 16); // copy iv to the end @@ -34,21 +34,21 @@ namespace tunnel { LogPrint (eLogError, "TunnelMessage: checksum verification failed"); return; - } + } // process fragments while (fragment < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE) { uint8_t flag = fragment[0]; fragment++; - - bool isFollowOnFragment = flag & 0x80, isLastFragment = true; + + bool isFollowOnFragment = flag & 0x80, isLastFragment = true; uint32_t msgID = 0; int fragmentNum = 0; TunnelMessageBlockEx m; if (!isFollowOnFragment) - { + { // first fragment - + m.deliveryType = (TunnelDeliveryType)((flag >> 5) & 0x03); switch (m.deliveryType) { @@ -61,31 +61,31 @@ namespace tunnel fragment += 32; // hash break; case eDeliveryTypeRouter: // 2 - m.hash = i2p::data::IdentHash (fragment); + m.hash = i2p::data::IdentHash (fragment); fragment += 32; // to hash break; default: ; - } + } bool isFragmented = flag & 0x08; if (isFragmented) { // Message ID - msgID = bufbe32toh (fragment); + msgID = bufbe32toh (fragment); fragment += 4; isLastFragment = false; - } + } } else { // follow on - msgID = bufbe32toh (fragment); // MessageID - fragment += 4; + msgID = bufbe32toh (fragment); // MessageID + fragment += 4; fragmentNum = (flag >> 1) & 0x3F; // 6 bits isLastFragment = flag & 0x01; - } - + } + uint16_t size = bufbe16toh (fragment); fragment += 2; @@ -106,7 +106,7 @@ namespace tunnel } else m.data = msg; - + if (!isFollowOnFragment && isLastFragment) HandleNextMessage (m); else @@ -127,18 +127,18 @@ namespace tunnel { m.nextFragmentNum = fragmentNum; HandleFollowOnFragment (msgID, isLastFragment, m); - } + } } - else + else LogPrint (eLogError, "TunnelMessage: Message is fragmented, but msgID is not presented"); - } - + } + fragment += size; - } - } + } + } else LogPrint (eLogError, "TunnelMessage: zero not found"); - } + } void TunnelEndpoint::HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, const TunnelMessageBlockEx& m) { @@ -151,7 +151,7 @@ namespace tunnel if (m.nextFragmentNum == msg.nextFragmentNum) { if (msg.data->len + size < I2NP_MAX_MESSAGE_SIZE) // check if message is not too long - { + { if (msg.data->len + size > msg.data->maxLen) { // LogPrint (eLogWarning, "TunnelMessage: I2NP message size ", msg.data->maxLen, " is not enough"); @@ -164,14 +164,14 @@ namespace tunnel if (isLastFragment) { // message complete - HandleNextMessage (msg); - m_IncompleteMessages.erase (it); - } + HandleNextMessage (msg); + m_IncompleteMessages.erase (it); + } else - { + { msg.nextFragmentNum++; HandleOutOfSequenceFragments (msgID, msg); - } + } } else { @@ -180,31 +180,31 @@ namespace tunnel } } else - { + { LogPrint (eLogWarning, "TunnelMessage: Unexpected fragment ", (int)m.nextFragmentNum, " instead ", (int)msg.nextFragmentNum, " of message ", msgID, ", saved"); AddOutOfSequenceFragment (msgID, m.nextFragmentNum, isLastFragment, m.data); } } else - { + { LogPrint (eLogWarning, "TunnelMessage: First fragment of message ", msgID, " not found, saved"); AddOutOfSequenceFragment (msgID, m.nextFragmentNum, isLastFragment, m.data); - } - } + } + } void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr data) { if (!m_OutOfSequenceFragments.insert ({{msgID, fragmentNum}, {isLastFragment, data, i2p::util::GetMillisecondsSinceEpoch () }}).second) LogPrint (eLogInfo, "TunnelMessage: duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID); - } + } void TunnelEndpoint::HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg) { - while (ConcatNextOutOfSequenceFragment (msgID, msg)) + while (ConcatNextOutOfSequenceFragment (msgID, msg)) { if (!msg.nextFragmentNum) // message complete { - HandleNextMessage (msg); + HandleNextMessage (msg); m_IncompleteMessages.erase (msgID); break; } @@ -215,7 +215,7 @@ namespace tunnel { auto it = m_OutOfSequenceFragments.find ({msgID, msg.nextFragmentNum}); if (it != m_OutOfSequenceFragments.end ()) - { + { LogPrint (eLogDebug, "TunnelMessage: Out-of-sequence fragment ", (int)msg.nextFragmentNum, " of message ", msgID, " found"); size_t size = it->second.data->GetLength (); if (msg.data->len + size > msg.data->maxLen) @@ -233,21 +233,21 @@ namespace tunnel else msg.nextFragmentNum++; m_OutOfSequenceFragments.erase (it); - return true; - } + return true; + } return false; - } - + } + void TunnelEndpoint::HandleNextMessage (const TunnelMessageBlock& msg) { if (!m_IsInbound && msg.data->IsExpired ()) { LogPrint (eLogInfo, "TunnelMessage: message expired"); return; - } + } uint8_t typeID = msg.data->GetTypeID (); LogPrint (eLogDebug, "TunnelMessage: handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID); - // catch RI or reply with new list of routers + // catch RI or reply with new list of routers if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) && !m_IsInbound && msg.deliveryType != eDeliveryTypeLocal) i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data)); @@ -263,15 +263,15 @@ namespace tunnel else LogPrint (eLogError, "TunnelMessage: Delivery type 'tunnel' arrived from an inbound tunnel, dropped"); break; - case eDeliveryTypeRouter: + case eDeliveryTypeRouter: if (!m_IsInbound) // outbound transit tunnel i2p::transport::transports.SendMessage (msg.hash, msg.data); - else // we shouldn't send this message. possible leakage + else // we shouldn't send this message. possible leakage LogPrint (eLogError, "TunnelMessage: Delivery type 'router' arrived from an inbound tunnel, dropped"); break; default: LogPrint (eLogError, "TunnelMessage: Unknown delivery type ", (int)msg.deliveryType); - }; + }; } void TunnelEndpoint::Cleanup () @@ -293,6 +293,6 @@ namespace tunnel else ++it; } - } -} + } +} } diff --git a/libi2pd/TunnelEndpoint.h b/libi2pd/TunnelEndpoint.h index e13ced34..c2ffe53d 100644 --- a/libi2pd/TunnelEndpoint.h +++ b/libi2pd/TunnelEndpoint.h @@ -12,26 +12,26 @@ namespace i2p namespace tunnel { class TunnelEndpoint - { + { struct TunnelMessageBlockEx: public TunnelMessageBlock { uint64_t receiveTime; // milliseconds since epoch uint8_t nextFragmentNum; - }; + }; struct Fragment { bool isLastFragment; std::shared_ptr data; uint64_t receiveTime; // milliseconds since epoch - }; - + }; + public: TunnelEndpoint (bool isInbound): m_IsInbound (isInbound), m_NumReceivedBytes (0) {}; ~TunnelEndpoint (); size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; - void Cleanup (); + void Cleanup (); void HandleDecryptedTunnelDataMsg (std::shared_ptr msg); @@ -42,16 +42,16 @@ namespace tunnel void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr data); bool ConcatNextOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg); // true if something added - void HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg); + void HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg); - private: + private: std::map m_IncompleteMessages; std::map, Fragment> m_OutOfSequenceFragments; // (msgID, fragment#)->fragment bool m_IsInbound; size_t m_NumReceivedBytes; - }; -} + }; +} } #endif diff --git a/libi2pd/TunnelGateway.cpp b/libi2pd/TunnelGateway.cpp index f8c5d031..e6bfdd84 100644 --- a/libi2pd/TunnelGateway.cpp +++ b/libi2pd/TunnelGateway.cpp @@ -10,8 +10,8 @@ namespace i2p { namespace tunnel { - TunnelGatewayBuffer::TunnelGatewayBuffer (): - m_CurrentTunnelDataMsg (nullptr), m_RemainingSize (0) + TunnelGatewayBuffer::TunnelGatewayBuffer (): + m_CurrentTunnelDataMsg (nullptr), m_RemainingSize (0) { RAND_bytes (m_NonZeroRandomBuffer, TUNNEL_DATA_MAX_PAYLOAD_SIZE); for (size_t i = 0; i < TUNNEL_DATA_MAX_PAYLOAD_SIZE; i++) @@ -21,31 +21,31 @@ namespace tunnel TunnelGatewayBuffer::~TunnelGatewayBuffer () { ClearTunnelDataMsgs (); - } - + } + void TunnelGatewayBuffer::PutI2NPMsg (const TunnelMessageBlock& block) { bool messageCreated = false; if (!m_CurrentTunnelDataMsg) - { + { CreateCurrentTunnelDataMessage (); messageCreated = true; - } + } // create delivery instructions uint8_t di[43]; // max delivery instruction length is 43 for tunnel size_t diLen = 1;// flag if (block.deliveryType != eDeliveryTypeLocal) // tunnel or router - { + { if (block.deliveryType == eDeliveryTypeTunnel) { htobe32buf (di + diLen, block.tunnelID); diLen += 4; // tunnelID } - + memcpy (di + diLen, block.hash, 32); diLen += 32; //len - } + } di[0] = block.deliveryType << 5; // set delivery type // create fragments @@ -62,21 +62,21 @@ namespace tunnel m_RemainingSize -= diLen + msg->GetLength (); if (!m_RemainingSize) CompleteCurrentTunnelDataMessage (); - } + } else { if (!messageCreated) // check if we should complete previous message - { + { size_t numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE; // length of bytes don't fit full tunnel message // every follow-on fragment adds 7 bytes - size_t nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE; + size_t nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE; if (!nonFit || nonFit > m_RemainingSize) { CompleteCurrentTunnelDataMessage (); CreateCurrentTunnelDataMessage (); - } - } + } + } if (diLen + 6 <= m_RemainingSize) { // delivery instructions fit @@ -97,16 +97,16 @@ namespace tunnel // follow on fragments int fragmentNumber = 1; while (size < msg->GetLength ()) - { + { CreateCurrentTunnelDataMessage (); uint8_t * buf = m_CurrentTunnelDataMsg->GetBuffer (); buf[0] = 0x80 | (fragmentNumber << 1); // frag bool isLastFragment = false; size_t s = msg->GetLength () - size; if (s > TUNNEL_DATA_MAX_PAYLOAD_SIZE - 7) // 7 follow on instructions - s = TUNNEL_DATA_MAX_PAYLOAD_SIZE - 7; + s = TUNNEL_DATA_MAX_PAYLOAD_SIZE - 7; else // last fragment - { + { buf[0] |= 0x01; isLastFragment = true; } @@ -119,7 +119,7 @@ namespace tunnel if(m_RemainingSize < (s+7)) { LogPrint (eLogError, "TunnelGateway: remaining size overflow: ", m_RemainingSize, " < ", s+7); } else { - m_RemainingSize -= s+7; + m_RemainingSize -= s+7; if (m_RemainingSize == 0) CompleteCurrentTunnelDataMessage (); } @@ -129,17 +129,17 @@ namespace tunnel size += s; fragmentNumber++; } - } + } else { // delivery instructions don't fit. Create new message CompleteCurrentTunnelDataMessage (); PutI2NPMsg (block); // don't delete msg because it's taken care inside - } - } + } + } } - + void TunnelGatewayBuffer::ClearTunnelDataMsgs () { m_TunnelDataMsgs.clear (); @@ -155,49 +155,49 @@ namespace tunnel m_CurrentTunnelDataMsg->offset += TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE; m_CurrentTunnelDataMsg->len = m_CurrentTunnelDataMsg->offset; m_RemainingSize = TUNNEL_DATA_MAX_PAYLOAD_SIZE; - } - + } + void TunnelGatewayBuffer::CompleteCurrentTunnelDataMessage () { if (!m_CurrentTunnelDataMsg) return; uint8_t * payload = m_CurrentTunnelDataMsg->GetBuffer (); size_t size = m_CurrentTunnelDataMsg->len - m_CurrentTunnelDataMsg->offset; - + m_CurrentTunnelDataMsg->offset = m_CurrentTunnelDataMsg->len - TUNNEL_DATA_MSG_SIZE - I2NP_HEADER_SIZE; uint8_t * buf = m_CurrentTunnelDataMsg->GetPayload (); - RAND_bytes (buf + 4, 16); // original IV - memcpy (payload + size, buf + 4, 16); // copy IV for checksum + RAND_bytes (buf + 4, 16); // original IV + memcpy (payload + size, buf + 4, 16); // copy IV for checksum uint8_t hash[32]; SHA256(payload, size+16, hash); - memcpy (buf+20, hash, 4); // checksum - payload[-1] = 0; // zero - ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1 + memcpy (buf+20, hash, 4); // checksum + payload[-1] = 0; // zero + ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1 if (paddingSize > 0) { - // non-zero padding + // non-zero padding auto randomOffset = rand () % (TUNNEL_DATA_MAX_PAYLOAD_SIZE - paddingSize + 1); - memcpy (buf + 24, m_NonZeroRandomBuffer + randomOffset, paddingSize); + memcpy (buf + 24, m_NonZeroRandomBuffer + randomOffset, paddingSize); } // we can't fill message header yet because encryption is required m_TunnelDataMsgs.push_back (m_CurrentTunnelDataMsg); m_CurrentTunnelDataMsg = nullptr; - } + } void TunnelGateway::SendTunnelDataMsg (const TunnelMessageBlock& block) { if (block.data) - { + { PutTunnelDataMsg (block); SendBuffer (); - } - } + } + } void TunnelGateway::PutTunnelDataMsg (const TunnelMessageBlock& block) { if (block.data) m_Buffer.PutI2NPMsg (block); - } + } void TunnelGateway::SendBuffer () { @@ -205,17 +205,17 @@ namespace tunnel std::vector > newTunnelMsgs; const auto& tunnelDataMsgs = m_Buffer.GetTunnelDataMsgs (); for (auto& tunnelMsg : tunnelDataMsgs) - { + { auto newMsg = CreateEmptyTunnelDataMsg (); - m_Tunnel->EncryptTunnelMsg (tunnelMsg, newMsg); + m_Tunnel->EncryptTunnelMsg (tunnelMsg, newMsg); htobe32buf (newMsg->GetPayload (), m_Tunnel->GetNextTunnelID ()); - newMsg->FillI2NPMessageHeader (eI2NPTunnelData); + newMsg->FillI2NPMessageHeader (eI2NPTunnelData); newTunnelMsgs.push_back (newMsg); m_NumSentBytes += TUNNEL_DATA_MSG_SIZE; - } + } m_Buffer.ClearTunnelDataMsgs (); i2p::transport::transports.SendMessages (m_Tunnel->GetNextIdentHash (), newTunnelMsgs); - } -} -} + } +} +} diff --git a/libi2pd/TunnelGateway.h b/libi2pd/TunnelGateway.h index 3642874c..7959b57b 100644 --- a/libi2pd/TunnelGateway.h +++ b/libi2pd/TunnelGateway.h @@ -16,7 +16,7 @@ namespace tunnel public: TunnelGatewayBuffer (); ~TunnelGatewayBuffer (); - void PutI2NPMsg (const TunnelMessageBlock& block); + void PutI2NPMsg (const TunnelMessageBlock& block); const std::vector >& GetTunnelDataMsgs () const { return m_TunnelDataMsgs; }; void ClearTunnelDataMsgs (); void CompleteCurrentTunnelDataMessage (); @@ -24,14 +24,14 @@ namespace tunnel private: void CreateCurrentTunnelDataMessage (); - + private: std::vector > m_TunnelDataMsgs; std::shared_ptr m_CurrentTunnelDataMsg; size_t m_RemainingSize; uint8_t m_NonZeroRandomBuffer[TUNNEL_DATA_MAX_PAYLOAD_SIZE]; - }; + }; class TunnelGateway { @@ -39,18 +39,18 @@ namespace tunnel TunnelGateway (TunnelBase * tunnel): m_Tunnel (tunnel), m_NumSentBytes (0) {}; - void SendTunnelDataMsg (const TunnelMessageBlock& block); + void SendTunnelDataMsg (const TunnelMessageBlock& block); void PutTunnelDataMsg (const TunnelMessageBlock& block); - void SendBuffer (); + void SendBuffer (); size_t GetNumSentBytes () const { return m_NumSentBytes; }; - + private: TunnelBase * m_Tunnel; TunnelGatewayBuffer m_Buffer; size_t m_NumSentBytes; - }; -} -} + }; +} +} #endif diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index 022280f8..415118ff 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -28,23 +28,23 @@ namespace api i2p::fs::DetectDataDir(datadir, false); i2p::fs::Init(); -#if defined(__x86_64__) +#if defined(__x86_64__) i2p::crypto::InitCrypto (false); #else i2p::crypto::InitCrypto (true); -#endif +#endif int netID; i2p::config::GetOption("netid", netID); i2p::context.SetNetID (netID); - i2p::context.Init (); + i2p::context.Init (); } void TerminateI2P () { i2p::crypto::TerminateCrypto (); - } - + } + void StartI2P (std::shared_ptr logStream) { if (logStream) @@ -75,8 +75,8 @@ namespace api void RunPeerTest () { i2p::transport::transports.PeerTest (); - } - + } + std::shared_ptr CreateLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params) { @@ -119,8 +119,8 @@ namespace api else { RequestLeaseSet (dest, remote); - return nullptr; - } + return nullptr; + } } void AcceptStream (std::shared_ptr dest, const i2p::stream::StreamingDestination::Acceptor& acceptor) diff --git a/libi2pd/api.h b/libi2pd/api.h index c010d82f..f64590d1 100644 --- a/libi2pd/api.h +++ b/libi2pd/api.h @@ -11,18 +11,18 @@ namespace i2p { namespace api { - // initialization start and stop + // initialization start and stop void InitI2P (int argc, char* argv[], const char * appName); void TerminateI2P (); void StartI2P (std::shared_ptr logStream = nullptr); // write system log to logStream, if not specified to .log in application's folder void StopI2P (); void RunPeerTest (); // should be called after UPnP - + // destinations std::shared_ptr CreateLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, - const std::map * params = nullptr); - std::shared_ptr CreateLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, + const std::map * params = nullptr); + std::shared_ptr CreateLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, const std::map * params = nullptr); // transient destinations usually not published void DestroyLocalDestination (std::shared_ptr dest); diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 5cc1fdb5..1395c2e6 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -8,7 +8,7 @@ #ifdef WIN32 #include #include -#include +#include #include #include #include @@ -167,7 +167,7 @@ namespace net } int GetMTUWindows(const boost::asio::ip::address& localAddress, int fallback) - { + { #ifdef UNICODE string localAddress_temporary = localAddress.to_string(); wstring localAddressUniversal(localAddress_temporary.begin(), localAddress_temporary.end()); @@ -181,7 +181,7 @@ namespace net return GetMTUWindowsIpv4(inputAddress, fallback); } else if(localAddress.is_v6()) { sockaddr_in6 inputAddress; - inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); + inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); return GetMTUWindowsIpv6(inputAddress, fallback); } else { LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported"); @@ -193,27 +193,27 @@ namespace net int GetMTUUnix(const boost::asio::ip::address& localAddress, int fallback) { ifaddrs* ifaddr, *ifa = nullptr; - if(getifaddrs(&ifaddr) == -1) + if(getifaddrs(&ifaddr) == -1) { LogPrint(eLogError, "NetIface: Can't call getifaddrs(): ", strerror(errno)); return fallback; } int family = 0; - // look for interface matching local address - for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) + // look for interface matching local address + for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { if(!ifa->ifa_addr) continue; family = ifa->ifa_addr->sa_family; - if(family == AF_INET && localAddress.is_v4()) + if(family == AF_INET && localAddress.is_v4()) { sockaddr_in* sa = (sockaddr_in*) ifa->ifa_addr; if(!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4)) break; // address matches - } - else if(family == AF_INET6 && localAddress.is_v6()) + } + else if(family == AF_INET6 && localAddress.is_v6()) { sockaddr_in6* sa = (sockaddr_in6*) ifa->ifa_addr; if(!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16)) @@ -221,28 +221,28 @@ namespace net } } int mtu = fallback; - if(ifa && family) + if(ifa && family) { // interface found? int fd = socket(family, SOCK_DGRAM, 0); - if(fd > 0) + if(fd > 0) { ifreq ifr; strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); // set interface for query - if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0) + if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0) mtu = ifr.ifr_mtu; // MTU else LogPrint (eLogError, "NetIface: Failed to run ioctl: ", strerror(errno)); close(fd); - } + } else LogPrint(eLogError, "NetIface: Failed to create datagram socket"); - } - else + } + else LogPrint(eLogWarning, "NetIface: interface for local address", localAddress.to_string(), " not found"); freeifaddrs(ifaddr); return mtu; - } + } #endif // WIN32 int GetMTU(const boost::asio::ip::address& localAddress) @@ -256,7 +256,7 @@ namespace net #endif return fallback; } - + const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6) { #ifdef WIN32 @@ -299,9 +299,9 @@ namespace net LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname); } return boost::asio::ip::address::from_string(fallback); - + #endif } -} +} } // util } // i2p diff --git a/libi2pd/util.h b/libi2pd/util.h index 813af0fb..e31e7b3f 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -38,15 +38,15 @@ namespace util public: MemoryPool (): m_Head (nullptr) {} - ~MemoryPool () - { - while (m_Head) + ~MemoryPool () + { + while (m_Head) { auto tmp = m_Head; m_Head = static_cast(*(void * *)m_Head); // next delete tmp; } - } + } template T * Acquire (TArgs&&... args) @@ -65,7 +65,7 @@ namespace util if (!t) return; t->~T (); *(void * *)t = m_Head; // next - m_Head = t; + m_Head = t; } template @@ -74,7 +74,7 @@ namespace util return std::unique_ptr >(Acquire (std::forward(args)...), std::bind (&MemoryPool::Release, this, std::placeholders::_1)); } - + template std::shared_ptr AcquireShared (TArgs&&... args) { @@ -85,7 +85,7 @@ namespace util protected: T * m_Head; - }; + }; template class MemoryPoolMt: public MemoryPool @@ -104,19 +104,19 @@ namespace util void ReleaseMt (T * t) { std::lock_guard l(m_Mutex); - this->Release (t); + this->Release (t); } templateclass C, typename... R> - void ReleaseMt(const C& c) + void ReleaseMt(const C& c) { std::lock_guard l(m_Mutex); for (auto& it: c) this->Release (it); - } + } private: - + std::mutex m_Mutex; }; diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index b40fadf6..7bcd1331 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -383,9 +383,9 @@ namespace client { it->second = ident->GetIdentHash (); m_Storage->AddAddress (ident); - LogPrint (eLogInfo, "Addressbook: updated host: ", name); + LogPrint (eLogInfo, "Addressbook: updated host: ", name); } - } + } else { m_Addresses.insert (std::make_pair (name, ident->GetIdentHash ())); diff --git a/libi2pd_client/AddressBook.h b/libi2pd_client/AddressBook.h index a1cb3def..3feb2ece 100644 --- a/libi2pd_client/AddressBook.h +++ b/libi2pd_client/AddressBook.h @@ -18,15 +18,15 @@ namespace i2p { namespace client { - const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes - const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes - const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) - const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes + const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes + const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes + const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) + const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second - const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; + const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54; - + inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); } class AddressBookStorage // interface for storage @@ -34,10 +34,10 @@ namespace client public: virtual ~AddressBookStorage () {}; - virtual std::shared_ptr GetAddress (const i2p::data::IdentHash& ident) const = 0; + virtual std::shared_ptr GetAddress (const i2p::data::IdentHash& ident) const = 0; virtual void AddAddress (std::shared_ptr address) = 0; virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0; - + virtual bool Init () = 0; virtual int Load (std::map& addresses) = 0; virtual int LoadLocal (std::map& addresses) = 0; @@ -45,7 +45,7 @@ namespace client virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0; virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0; - }; + }; class AddressBookSubscription; class AddressResolver; @@ -77,7 +77,7 @@ namespace client void StartSubscriptions (); void StopSubscriptions (); - + void LoadHosts (); void LoadSubscriptions (); void LoadLocal (); @@ -87,8 +87,8 @@ namespace client void StartLookups (); void StopLookups (); void HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - - private: + + private: std::mutex m_AddressBookMutex; std::map m_Addresses; @@ -112,7 +112,7 @@ namespace client private: bool MakeRequest (); - + private: AddressBook& m_Book; diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 6f2782df..2a18c8ba 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -8,7 +8,7 @@ namespace i2p { namespace client { - BOBI2PInboundTunnel::BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr localDestination): + BOBI2PInboundTunnel::BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr localDestination): BOBI2PTunnel (localDestination), m_Acceptor (localDestination->GetService (), ep) { } @@ -36,13 +36,13 @@ namespace client receiver->socket = std::make_shared (GetService ()); m_Acceptor.async_accept (*receiver->socket, std::bind (&BOBI2PInboundTunnel::HandleAccept, this, std::placeholders::_1, receiver)); - } + } void BOBI2PInboundTunnel::HandleAccept (const boost::system::error_code& ecode, std::shared_ptr receiver) { if (!ecode) { - Accept (); + Accept (); ReceiveAddress (receiver); } } @@ -50,12 +50,12 @@ namespace client void BOBI2PInboundTunnel::ReceiveAddress (std::shared_ptr receiver) { receiver->socket->async_read_some (boost::asio::buffer( - receiver->buffer + receiver->bufferOffset, - BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset), - std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this, + receiver->buffer + receiver->bufferOffset, + BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset), + std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this, std::placeholders::_1, std::placeholders::_2, receiver)); } - + void BOBI2PInboundTunnel::HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::shared_ptr receiver) { @@ -69,11 +69,11 @@ namespace client if (eol) { *eol = 0; - if (eol != receiver->buffer && eol[-1] == '\r') eol[-1] = 0; // workaround for Transmission, it sends '\r\n' terminated address + if (eol != receiver->buffer && eol[-1] == '\r') eol[-1] = 0; // workaround for Transmission, it sends '\r\n' terminated address receiver->data = (uint8_t *)eol + 1; receiver->dataLen = receiver->bufferOffset - (eol - receiver->buffer + 1); i2p::data::IdentHash ident; - if (!context.GetAddressBook ().GetIdentHash (receiver->buffer, ident)) + if (!context.GetAddressBook ().GetIdentHash (receiver->buffer, ident)) { LogPrint (eLogError, "BOB: address ", receiver->buffer, " not found"); return; @@ -82,7 +82,7 @@ namespace client if (leaseSet) CreateConnection (receiver, leaseSet); else - GetLocalDestination ()->RequestDestination (ident, + GetLocalDestination ()->RequestDestination (ident, std::bind (&BOBI2PInboundTunnel::HandleDestinationRequestComplete, this, std::placeholders::_1, receiver)); } @@ -92,7 +92,7 @@ namespace client ReceiveAddress (receiver); else LogPrint (eLogError, "BOB: missing inbound address"); - } + } } } @@ -102,7 +102,7 @@ namespace client CreateConnection (receiver, leaseSet); else LogPrint (eLogError, "BOB: LeaseSet for inbound destination not found"); - } + } void BOBI2PInboundTunnel::CreateConnection (std::shared_ptr receiver, std::shared_ptr leaseSet) { @@ -112,12 +112,12 @@ namespace client connection->I2PConnect (receiver->data, receiver->dataLen); } - BOBI2POutboundTunnel::BOBI2POutboundTunnel (const std::string& address, int port, + BOBI2POutboundTunnel::BOBI2POutboundTunnel (const std::string& address, int port, std::shared_ptr localDestination, bool quiet): BOBI2PTunnel (localDestination), m_Endpoint (boost::asio::ip::address::from_string (address), port), m_IsQuiet (quiet) { } - + void BOBI2POutboundTunnel::Start () { Accept (); @@ -126,11 +126,11 @@ namespace client void BOBI2POutboundTunnel::Stop () { ClearHandlers (); - } + } void BOBI2POutboundTunnel::Accept () { - auto localDestination = GetLocalDestination (); + auto localDestination = GetLocalDestination (); if (localDestination) localDestination->AcceptStreams (std::bind (&BOBI2POutboundTunnel::HandleAccept, this, std::placeholders::_1)); else @@ -140,54 +140,54 @@ namespace client void BOBI2POutboundTunnel::HandleAccept (std::shared_ptr stream) { if (stream) - { + { auto conn = std::make_shared (this, stream, std::make_shared (GetService ()), m_Endpoint, m_IsQuiet); AddHandler (conn); conn->Connect (); - } + } } BOBDestination::BOBDestination (std::shared_ptr localDestination): - m_LocalDestination (localDestination), + m_LocalDestination (localDestination), m_OutboundTunnel (nullptr), m_InboundTunnel (nullptr) { } - + BOBDestination::~BOBDestination () { delete m_OutboundTunnel; delete m_InboundTunnel; i2p::client::context.DeleteLocalDestination (m_LocalDestination); - } + } void BOBDestination::Start () { if (m_OutboundTunnel) m_OutboundTunnel->Start (); if (m_InboundTunnel) m_InboundTunnel->Start (); } - + void BOBDestination::Stop () - { + { StopTunnels (); m_LocalDestination->Stop (); - } + } void BOBDestination::StopTunnels () { if (m_OutboundTunnel) - { + { m_OutboundTunnel->Stop (); delete m_OutboundTunnel; m_OutboundTunnel = nullptr; - } + } if (m_InboundTunnel) - { + { m_InboundTunnel->Stop (); delete m_InboundTunnel; m_InboundTunnel = nullptr; - } - } - + } + } + void BOBDestination::CreateInboundTunnel (int port, const std::string& address) { if (!m_InboundTunnel) @@ -200,21 +200,21 @@ namespace client if (!ec) ep.address (addr); else - LogPrint (eLogError, "BOB: ", ec.message ()); - } + LogPrint (eLogError, "BOB: ", ec.message ()); + } m_InboundTunnel = new BOBI2PInboundTunnel (ep, m_LocalDestination); } } - + void BOBDestination::CreateOutboundTunnel (const std::string& address, int port, bool quiet) { if (!m_OutboundTunnel) m_OutboundTunnel = new BOBI2POutboundTunnel (address, port, m_LocalDestination, quiet); - } - - BOBCommandSession::BOBCommandSession (BOBCommandChannel& owner): + } + + BOBCommandSession::BOBCommandSession (BOBCommandChannel& owner): m_Owner (owner), m_Socket (m_Owner.GetService ()), - m_ReceiveBufferOffset (0), m_IsOpen (true), m_IsQuiet (false), m_IsActive (false), + m_ReceiveBufferOffset (0), m_IsOpen (true), m_IsQuiet (false), m_IsActive (false), m_InPort (0), m_OutPort (0), m_CurrentDestination (nullptr) { } @@ -226,13 +226,13 @@ namespace client void BOBCommandSession::Terminate () { m_Socket.close (); - m_IsOpen = false; + m_IsOpen = false; } void BOBCommandSession::Receive () { - m_Socket.async_read_some (boost::asio::buffer(m_ReceiveBuffer + m_ReceiveBufferOffset, BOB_COMMAND_BUFFER_SIZE - m_ReceiveBufferOffset), - std::bind(&BOBCommandSession::HandleReceived, shared_from_this (), + m_Socket.async_read_some (boost::asio::buffer(m_ReceiveBuffer + m_ReceiveBufferOffset, BOB_COMMAND_BUFFER_SIZE - m_ReceiveBufferOffset), + std::bind(&BOBCommandSession::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -243,29 +243,29 @@ namespace client LogPrint (eLogError, "BOB: command channel read error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) Terminate (); - } + } else - { - size_t size = m_ReceiveBufferOffset + bytes_transferred; + { + size_t size = m_ReceiveBufferOffset + bytes_transferred; m_ReceiveBuffer[size] = 0; char * eol = strchr (m_ReceiveBuffer, '\n'); if (eol) { *eol = 0; char * operand = strchr (m_ReceiveBuffer, ' '); - if (operand) - { + if (operand) + { *operand = 0; operand++; - } - else + } + else operand = eol; // process command auto& handlers = m_Owner.GetCommandHandlers (); auto it = handlers.find (m_ReceiveBuffer); if (it != handlers.end ()) (this->*(it->second))(operand, eol - operand); - else + else { LogPrint (eLogError, "BOB: unknown command ", m_ReceiveBuffer); SendReplyError ("unknown command"); @@ -283,15 +283,15 @@ namespace client LogPrint (eLogError, "BOB: Malformed input of the command channel"); Terminate (); } - } + } } } void BOBCommandSession::Send (size_t len) { - boost::asio::async_write (m_Socket, boost::asio::buffer (m_SendBuffer, len), + boost::asio::async_write (m_Socket, boost::asio::buffer (m_SendBuffer, len), boost::asio::transfer_all (), - std::bind(&BOBCommandSession::HandleSent, shared_from_this (), + std::bind(&BOBCommandSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -308,7 +308,7 @@ namespace client if (m_IsOpen) Receive (); else - Terminate (); + Terminate (); } } @@ -316,7 +316,7 @@ namespace client { #ifdef _MSC_VER size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_OK, msg); -#else +#else size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_OK, msg); #endif Send (len); @@ -326,12 +326,12 @@ namespace client { #ifdef _MSC_VER size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_ERROR, msg); -#else +#else size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_ERROR, msg); #endif - Send (len); + Send (len); } - + void BOBCommandSession::SendVersion () { size_t len = strlen (BOB_VERSION); @@ -343,12 +343,12 @@ namespace client { #ifdef _MSC_VER size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_DATA, nickname); -#else +#else size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_DATA, nickname); #endif - Send (len); + Send (len); } - + void BOBCommandSession::ZapCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: zap"); @@ -368,21 +368,21 @@ namespace client if (m_IsActive) { SendReplyError ("tunnel is active"); - return; + return; } if (!m_CurrentDestination) - { + { m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options)); m_Owner.AddDestination (m_Nickname, m_CurrentDestination); - } + } if (m_InPort) m_CurrentDestination->CreateInboundTunnel (m_InPort, m_Address); if (m_OutPort && !m_Address.empty ()) m_CurrentDestination->CreateOutboundTunnel (m_Address, m_OutPort, m_IsQuiet); - m_CurrentDestination->Start (); + m_CurrentDestination->Start (); SendReplyOK ("Tunnel starting"); m_IsActive = true; - } + } void BOBCommandSession::StopCommandHandler (const char * operand, size_t len) { @@ -401,8 +401,8 @@ namespace client else SendReplyError ("tunnel not found"); m_IsActive = false; - } - + } + void BOBCommandSession::SetNickCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: setnick ", operand); @@ -410,30 +410,30 @@ namespace client std::string msg ("Nickname set to "); msg += m_Nickname; SendReplyOK (msg.c_str ()); - } + } void BOBCommandSession::GetNickCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: getnick ", operand); - m_CurrentDestination = m_Owner.FindDestination (operand); + m_CurrentDestination = m_Owner.FindDestination (operand); if (m_CurrentDestination) { m_Keys = m_CurrentDestination->GetKeys (); m_Nickname = operand; } if (m_Nickname == operand) - { + { std::string msg ("Nickname set to "); msg += m_Nickname; SendReplyOK (msg.c_str ()); - } + } else - SendReplyError ("no nickname has been set"); - } + SendReplyError ("no nickname has been set"); + } void BOBCommandSession::NewkeysCommandHandler (const char * operand, size_t len) { - LogPrint (eLogDebug, "BOB: newkeys"); + LogPrint (eLogDebug, "BOB: newkeys"); i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; if (*operand) @@ -441,23 +441,23 @@ namespace client try { char * operand1 = (char *)strchr (operand, ' '); - if (operand1) + if (operand1) { *operand1 = 0; operand1++; cryptoType = std::stoi(operand1); } - signatureType = std::stoi(operand); + signatureType = std::stoi(operand); } catch (std::invalid_argument& ex) { LogPrint (eLogWarning, "BOB: newkeys ", ex.what ()); } - } - - + } + + m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType); SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ()); - } + } void BOBCommandSession::SetkeysCommandHandler (const char * operand, size_t len) { @@ -467,9 +467,9 @@ namespace client else SendReplyError ("invalid keys"); } - + void BOBCommandSession::GetkeysCommandHandler (const char * operand, size_t len) - { + { LogPrint (eLogDebug, "BOB: getkeys"); if (m_Keys.GetPublic ()) // keys are set ? SendReplyOK (m_Keys.ToBase64 ().c_str ()); @@ -484,15 +484,15 @@ namespace client SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ()); else SendReplyError ("keys are not set"); - } - + } + void BOBCommandSession::OuthostCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: outhost ", operand); m_Address = operand; SendReplyOK ("outhost set"); } - + void BOBCommandSession::OutportCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: outport ", operand); @@ -501,7 +501,7 @@ namespace client SendReplyOK ("outbound port set"); else SendReplyError ("port out of range"); - } + } void BOBCommandSession::InhostCommandHandler (const char * operand, size_t len) { @@ -509,7 +509,7 @@ namespace client m_Address = operand; SendReplyOK ("inhost set"); } - + void BOBCommandSession::InportCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: inport ", operand); @@ -518,7 +518,7 @@ namespace client SendReplyOK ("inbound port set"); else SendReplyError ("port out of range"); - } + } void BOBCommandSession::QuietCommandHandler (const char * operand, size_t len) { @@ -535,17 +535,17 @@ namespace client } else SendReplyError ("no nickname has been set"); - } - + } + void BOBCommandSession::LookupCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: lookup ", operand); i2p::data::IdentHash ident; - if (!context.GetAddressBook ().GetIdentHash (operand, ident)) + if (!context.GetAddressBook ().GetIdentHash (operand, ident)) { SendReplyError ("Address Not found"); return; - } + } auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); auto leaseSet = localDestination->FindLeaseSet (ident); if (leaseSet) @@ -553,14 +553,14 @@ namespace client else { auto s = shared_from_this (); - localDestination->RequestDestination (ident, + localDestination->RequestDestination (ident, [s](std::shared_ptr ls) { if (ls) s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ()); - else + else s->SendReplyError ("LeaseSet Not found"); - } + } ); } } @@ -571,7 +571,7 @@ namespace client m_Owner.DeleteDestination (m_Nickname); m_Nickname = ""; SendReplyOK ("cleared"); - } + } void BOBCommandSession::ListCommandHandler (const char * operand, size_t len) { @@ -580,26 +580,26 @@ namespace client for (const auto& it: destinations) SendData (it.first.c_str ()); SendReplyOK ("Listing done"); - } + } void BOBCommandSession::OptionCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: option ", operand); const char * value = strchr (operand, '='); if (value) - { + { std::string msg ("option "); *(const_cast(value)) = 0; - m_Options[operand] = value + 1; + m_Options[operand] = value + 1; msg += operand; *(const_cast(value)) = '='; msg += " set to "; - msg += value; + msg += value; SendReplyOK (msg.c_str ()); - } + } else SendReplyError ("malformed"); - } + } void BOBCommandSession::StatusCommandHandler (const char * operand, size_t len) { @@ -609,37 +609,37 @@ namespace client std::stringstream s; s << "DATA"; s << " NICKNAME: "; s << m_Nickname; if (m_CurrentDestination) - { + { if (m_CurrentDestination->GetLocalDestination ()->IsReady ()) s << " STARTING: false RUNNING: true STOPPING: false"; else s << " STARTING: true RUNNING: false STOPPING: false"; - } + } else s << " STARTING: false RUNNING: false STOPPING: false"; s << " KEYS: true"; s << " QUIET: "; s << (m_IsQuiet ? "true":"false"); if (m_InPort) - { + { s << " INPORT: " << m_InPort; s << " INHOST: " << (m_Address.length () > 0 ? m_Address : "127.0.0.1"); - } + } if (m_OutPort) - { + { s << " OUTPORT: " << m_OutPort; s << " OUTHOST: " << (m_Address.length () > 0 ? m_Address : "127.0.0.1"); - } + } SendReplyOK (s.str().c_str()); } else - SendReplyError ("no nickname has been set"); - } - + SendReplyError ("no nickname has been set"); + } + BOBCommandChannel::BOBCommandChannel (const std::string& address, int port): m_IsRunning (false), m_Thread (nullptr), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)) { // command -> handler - m_CommandHandlers[BOB_COMMAND_ZAP] = &BOBCommandSession::ZapCommandHandler; + m_CommandHandlers[BOB_COMMAND_ZAP] = &BOBCommandSession::ZapCommandHandler; m_CommandHandlers[BOB_COMMAND_QUIT] = &BOBCommandSession::QuitCommandHandler; m_CommandHandlers[BOB_COMMAND_START] = &BOBCommandSession::StartCommandHandler; m_CommandHandlers[BOB_COMMAND_STOP] = &BOBCommandSession::StopCommandHandler; @@ -680,35 +680,35 @@ namespace client m_IsRunning = false; for (auto& it: m_Destinations) it.second->Stop (); - m_Acceptor.cancel (); + m_Acceptor.cancel (); m_Service.stop (); if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = nullptr; - } + } } - - void BOBCommandChannel::Run () - { + + void BOBCommandChannel::Run () + { while (m_IsRunning) { try - { + { m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "BOB: runtime exception: ", ex.what ()); - } - } + } + } } void BOBCommandChannel::AddDestination (const std::string& name, BOBDestination * dest) { m_Destinations[name] = dest; - } + } void BOBCommandChannel::DeleteDestination (const std::string& name) { @@ -718,17 +718,17 @@ namespace client it->second->Stop (); delete it->second; m_Destinations.erase (it); - } - } - + } + } + BOBDestination * BOBCommandChannel::FindDestination (const std::string& name) { auto it = m_Destinations.find (name); if (it != m_Destinations.end ()) return it->second; - return nullptr; + return nullptr; } - + void BOBCommandChannel::Accept () { auto newSession = std::make_shared (*this); @@ -744,7 +744,7 @@ namespace client if (!ecode) { LogPrint (eLogInfo, "BOB: New command connection from ", session->GetSocket ().remote_endpoint ()); - session->SendVersion (); + session->SendVersion (); } else LogPrint (eLogError, "BOB: accept error: ", ecode.message ()); diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index bd29dafd..a2a24164 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -20,25 +20,25 @@ namespace client const char BOB_COMMAND_ZAP[] = "zap"; const char BOB_COMMAND_QUIT[] = "quit"; const char BOB_COMMAND_START[] = "start"; - const char BOB_COMMAND_STOP[] = "stop"; + const char BOB_COMMAND_STOP[] = "stop"; const char BOB_COMMAND_SETNICK[] = "setnick"; - const char BOB_COMMAND_GETNICK[] = "getnick"; + const char BOB_COMMAND_GETNICK[] = "getnick"; const char BOB_COMMAND_NEWKEYS[] = "newkeys"; const char BOB_COMMAND_GETKEYS[] = "getkeys"; const char BOB_COMMAND_SETKEYS[] = "setkeys"; const char BOB_COMMAND_GETDEST[] = "getdest"; - const char BOB_COMMAND_OUTHOST[] = "outhost"; + const char BOB_COMMAND_OUTHOST[] = "outhost"; const char BOB_COMMAND_OUTPORT[] = "outport"; - const char BOB_COMMAND_INHOST[] = "inhost"; + const char BOB_COMMAND_INHOST[] = "inhost"; const char BOB_COMMAND_INPORT[] = "inport"; const char BOB_COMMAND_QUIET[] = "quiet"; - const char BOB_COMMAND_LOOKUP[] = "lookup"; + const char BOB_COMMAND_LOOKUP[] = "lookup"; const char BOB_COMMAND_CLEAR[] = "clear"; const char BOB_COMMAND_LIST[] = "list"; const char BOB_COMMAND_OPTION[] = "option"; - const char BOB_COMMAND_STATUS[] = "status"; - - const char BOB_VERSION[] = "BOB 00.00.10\nOK\n"; + const char BOB_COMMAND_STATUS[] = "status"; + + const char BOB_VERSION[] = "BOB 00.00.10\nOK\n"; const char BOB_REPLY_OK[] = "OK %s\n"; const char BOB_REPLY_ERROR[] = "ERROR %s\n"; const char BOB_DATA[] = "NICKNAME %s\n"; @@ -47,13 +47,13 @@ namespace client { public: - BOBI2PTunnel (std::shared_ptr localDestination): + BOBI2PTunnel (std::shared_ptr localDestination): I2PService (localDestination) {}; virtual void Start () {}; - virtual void Stop () {}; - }; - + virtual void Stop () {}; + }; + class BOBI2PInboundTunnel: public BOBI2PTunnel { struct AddressReceiver @@ -61,11 +61,11 @@ namespace client std::shared_ptr socket; char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address uint8_t * data; // pointer to buffer - size_t dataLen, bufferOffset; + size_t dataLen, bufferOffset; AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {}; - }; - + }; + public: BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr localDestination); @@ -89,14 +89,14 @@ namespace client private: - boost::asio::ip::tcp::acceptor m_Acceptor; + boost::asio::ip::tcp::acceptor m_Acceptor; }; class BOBI2POutboundTunnel: public BOBI2PTunnel { public: - BOBI2POutboundTunnel (const std::string& address, int port, std::shared_ptr localDestination, bool quiet); + BOBI2POutboundTunnel (const std::string& address, int port, std::shared_ptr localDestination, bool quiet); void Start (); void Stop (); @@ -110,8 +110,8 @@ namespace client private: - boost::asio::ip::tcp::endpoint m_Endpoint; - bool m_IsQuiet; + boost::asio::ip::tcp::endpoint m_Endpoint; + bool m_IsQuiet; }; @@ -129,21 +129,21 @@ namespace client void CreateOutboundTunnel (const std::string& address, int port, bool quiet); const i2p::data::PrivateKeys& GetKeys () const { return m_LocalDestination->GetPrivateKeys (); }; std::shared_ptr GetLocalDestination () const { return m_LocalDestination; }; - - private: + + private: std::shared_ptr m_LocalDestination; BOBI2POutboundTunnel * m_OutboundTunnel; BOBI2PInboundTunnel * m_InboundTunnel; - }; - + }; + class BOBCommandChannel; class BOBCommandSession: public std::enable_shared_from_this { public: BOBCommandSession (BOBCommandChannel& owner); - ~BOBCommandSession (); + ~BOBCommandSession (); void Terminate (); boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; @@ -163,14 +163,14 @@ namespace client void OuthostCommandHandler (const char * operand, size_t len); void OutportCommandHandler (const char * operand, size_t len); void InhostCommandHandler (const char * operand, size_t len); - void InportCommandHandler (const char * operand, size_t len); - void QuietCommandHandler (const char * operand, size_t len); + void InportCommandHandler (const char * operand, size_t len); + void QuietCommandHandler (const char * operand, size_t len); void LookupCommandHandler (const char * operand, size_t len); void ClearCommandHandler (const char * operand, size_t len); void ListCommandHandler (const char * operand, size_t len); void OptionCommandHandler (const char * operand, size_t len); void StatusCommandHandler (const char * operand, size_t len); - + private: void Receive (); @@ -192,7 +192,7 @@ namespace client std::string m_Nickname, m_Address; int m_InPort, m_OutPort; i2p::data::PrivateKeys m_Keys; - std::map m_Options; + std::map m_Options; BOBDestination * m_CurrentDestination; }; typedef void (BOBCommandSession::*BOBCommandHandler)(const char * operand, size_t len); @@ -211,7 +211,7 @@ namespace client void AddDestination (const std::string& name, BOBDestination * dest); void DeleteDestination (const std::string& name); BOBDestination * FindDestination (const std::string& name); - + private: void Run (); @@ -221,7 +221,7 @@ namespace client private: bool m_IsRunning; - std::thread * m_Thread; + std::thread * m_Thread; boost::asio::io_service m_Service; boost::asio::ip::tcp::acceptor m_Acceptor; std::map m_Destinations; @@ -231,7 +231,7 @@ namespace client const decltype(m_CommandHandlers)& GetCommandHandlers () const { return m_CommandHandlers; }; const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; }; - }; + }; } } diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index db3a129d..5ad49ac5 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -281,7 +281,7 @@ namespace client } } - bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, + bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType) { if (filename == "transient") @@ -448,7 +448,7 @@ namespace client if (i2p::config::GetOption(prefix + I2CP_PARAM_MIN_TUNNEL_LATENCY, value)) options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = value; if (i2p::config::GetOption(prefix + I2CP_PARAM_MAX_TUNNEL_LATENCY, value)) - options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; + options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; } void ClientContext::ReadTunnels () diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 9b65ef32..8f7143bb 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -73,8 +73,8 @@ namespace client std::shared_ptr CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map * params = nullptr); void DeleteLocalDestination (std::shared_ptr destination); std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; - bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, - i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, + bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, + i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); AddressBook& GetAddressBook () { return m_AddressBook; }; diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index f98b1af3..9c87cf0e 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -23,8 +23,8 @@ namespace i2p namespace client { - I2CPDestination::I2CPDestination (std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params): - LeaseSetDestination (isPublic, ¶ms), m_Owner (owner), m_Identity (identity) + I2CPDestination::I2CPDestination (std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params): + LeaseSetDestination (isPublic, ¶ms), m_Owner (owner), m_Identity (identity) { } @@ -39,7 +39,7 @@ namespace client if (m_Decryptor) return m_Decryptor->Decrypt (encrypted, data, ctx); else - LogPrint (eLogError, "I2CP: decryptor is not set"); + LogPrint (eLogError, "I2CP: decryptor is not set"); return false; } @@ -50,7 +50,7 @@ namespace client m_Owner->SendMessagePayloadMessage (buf + 4, length); } - void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) + void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) { i2p::data::LocalLeaseSet ls (m_Identity, m_EncryptionPrivateKey, tunnels); // we don't care about encryption key m_LeaseSetExpirationTime = ls.GetExpirationTime (); @@ -58,23 +58,23 @@ namespace client leases[-1] = tunnels.size (); htobe16buf (leases - 3, m_Owner->GetSessionID ()); size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size (); - m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); + m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); } - + void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len) { auto ls = new i2p::data::LocalLeaseSet (m_Identity, buf, len); ls->SetExpirationTime (m_LeaseSetExpirationTime); SetLeaseSet (ls); } - + void I2CPDestination::SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce) { auto msg = NewI2NPMessage (); uint8_t * buf = msg->GetPayload (); htobe32buf (buf, len); memcpy (buf + 4, payload, len); - msg->len += len + 4; + msg->len += len + 4; msg->FillI2NPMessageHeader (eI2NPData); auto s = GetSharedFromThis (); auto remote = FindLeaseSet (ident); @@ -85,7 +85,7 @@ namespace client { bool sent = s->SendMsg (msg, remote); s->m_Owner->SendMessageStatusMessage (nonce, sent ? eI2CPMessageStatusGuaranteedSuccess : eI2CPMessageStatusGuaranteedFailure); - }); + }); } else { @@ -93,7 +93,7 @@ namespace client [s, msg, nonce](std::shared_ptr ls) { if (ls) - { + { bool sent = s->SendMsg (msg, ls); s->m_Owner->SendMessageStatusMessage (nonce, sent ? eI2CPMessageStatusGuaranteedSuccess : eI2CPMessageStatusGuaranteedFailure); } @@ -104,8 +104,8 @@ namespace client } bool I2CPDestination::SendMsg (std::shared_ptr msg, std::shared_ptr remote) - { - auto remoteSession = GetRoutingSession (remote, true); + { + auto remoteSession = GetRoutingSession (remote, true); if (!remoteSession) { LogPrint (eLogError, "I2CP: Failed to create remote session"); @@ -113,7 +113,7 @@ namespace client } auto path = remoteSession->GetSharedRoutingPath (); std::shared_ptr outboundTunnel; - std::shared_ptr remoteLease; + std::shared_ptr remoteLease; if (path) { if (!remoteSession->CleanupUnconfirmedTags ()) // no stuck tags @@ -128,27 +128,27 @@ namespace client { outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel (); auto leases = remote->GetNonExpiredLeases (); - if (!leases.empty ()) + if (!leases.empty ()) remoteLease = leases[rand () % leases.size ()]; if (remoteLease && outboundTunnel) remoteSession->SetSharedRoutingPath (std::make_shared ( i2p::garlic::GarlicRoutingPath{outboundTunnel, remoteLease, 10000, 0, 0})); // 10 secs RTT else remoteSession->SetSharedRoutingPath (nullptr); - } + } if (remoteLease && outboundTunnel) { - std::vector msgs; + std::vector msgs; auto garlic = remoteSession->WrapSingleMessage (msg); - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeTunnel, remoteLease->tunnelGateway, remoteLease->tunnelID, garlic }); outboundTunnel->SendTunnelDataMsg (msgs); return true; - } + } else { if (outboundTunnel) @@ -156,7 +156,7 @@ namespace client else LogPrint (eLogWarning, "I2CP: Failed to send message. No outbound tunnels"); return false; - } + } } I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): @@ -164,7 +164,7 @@ namespace client m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true) { } - + I2CPSession::~I2CPSession () { delete[] m_Payload; @@ -184,8 +184,8 @@ namespace client { if (m_Socket) { - auto s = shared_from_this (); - m_Socket->async_read_some (boost::asio::buffer (m_Header, 1), + auto s = shared_from_this (); + m_Socket->async_read_some (boost::asio::buffer (m_Header, 1), [s](const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (!ecode && bytes_transferred > 0 && s->m_Header[0] == I2CP_PROTOCOL_BYTE) @@ -239,7 +239,7 @@ namespace client HandleMessage (); delete[] m_Payload; m_Payload = nullptr; - m_PayloadLen = 0; + m_PayloadLen = 0; ReceiveHeader (); // next message } } @@ -273,16 +273,16 @@ namespace client { auto socket = m_Socket; if (socket) - { + { auto l = len + I2CP_HEADER_SIZE; uint8_t * buf = new uint8_t[l]; htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len); buf[I2CP_HEADER_TYPE_OFFSET] = type; memcpy (buf + I2CP_HEADER_SIZE, payload, len); boost::asio::async_write (*socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), - std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, buf)); - } + std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), + std::placeholders::_1, std::placeholders::_2, buf)); + } else LogPrint (eLogError, "I2CP: Can't write to the socket"); } @@ -307,7 +307,7 @@ namespace client if (l + 1 >= len) l = len - 1; if (l > 255) l = 255; // 1 byte max buf[0] = l; - memcpy (buf + 1, str.c_str (), l); + memcpy (buf + 1, str.c_str (), l); return l + 1; } @@ -319,20 +319,20 @@ namespace client { std::string param = ExtractString (buf + offset, len - offset); offset += param.length () + 1; - if (buf[offset] != '=') + if (buf[offset] != '=') { LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead '=' after ", param); - break; - } + break; + } offset++; std::string value = ExtractString (buf + offset, len - offset); offset += value.length () + 1; - if (buf[offset] != ';') + if (buf[offset] != ';') { LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead ';' after ", value); - break; - } + break; + } offset++; mapping.insert (std::make_pair (param, value)); } @@ -349,7 +349,7 @@ namespace client htobe64buf (payload, ts); // echo vesrion back PutString (payload + 8, l - 8, version); - SendI2CPMessage (I2CP_SET_DATE_MESSAGE, payload, l); + SendI2CPMessage (I2CP_SET_DATE_MESSAGE, payload, l); delete[] payload; } @@ -361,26 +361,26 @@ namespace client size_t offset = identity->FromBuffer (buf, len); if (!offset) { - LogPrint (eLogError, "I2CP: create session maformed identity"); + LogPrint (eLogError, "I2CP: create session maformed identity"); SendSessionStatusMessage (3); // invalid return; - } + } uint16_t optionsSize = bufbe16toh (buf + offset); offset += 2; if (optionsSize > len - offset) { - LogPrint (eLogError, "I2CP: options size ", optionsSize, "exceeds message size"); + LogPrint (eLogError, "I2CP: options size ", optionsSize, "exceeds message size"); SendSessionStatusMessage (3); // invalid return; } std::map params; - ExtractMapping (buf + offset, optionsSize, params); + ExtractMapping (buf + offset, optionsSize, params); offset += optionsSize; // options if (params[I2CP_PARAM_MESSAGE_RELIABILITY] == "none") m_IsSendAccepted = false; offset += 8; // date if (identity->Verify (buf, offset, buf + offset)) // signature - { + { bool isPublic = true; if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "true") isPublic = false; if (!m_Destination) @@ -388,17 +388,17 @@ namespace client m_Destination = std::make_shared(shared_from_this (), identity, isPublic, params); SendSessionStatusMessage (1); // created LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created"); - m_Destination->Start (); + m_Destination->Start (); } else { - LogPrint (eLogError, "I2CP: session already exists"); + LogPrint (eLogError, "I2CP: session already exists"); SendSessionStatusMessage (4); // refused } } else { - LogPrint (eLogError, "I2CP: create session signature verification falied"); + LogPrint (eLogError, "I2CP: create session signature verification falied"); SendSessionStatusMessage (3); // invalid } } @@ -418,14 +418,14 @@ namespace client { // TODO: implement actual reconfiguration SendSessionStatusMessage (2); // updated - } + } void I2CPSession::SendSessionStatusMessage (uint8_t status) { uint8_t buf[3]; htobe16buf (buf, m_SessionID); buf[2] = status; - SendI2CPMessage (I2CP_SESSION_STATUS_MESSAGE, buf, 3); + SendI2CPMessage (I2CP_SESSION_STATUS_MESSAGE, buf, 3); } void I2CPSession::SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status) @@ -436,8 +436,8 @@ namespace client htobe32buf (buf + 2, m_MessageID++); buf[6] = (uint8_t)status; memset (buf + 7, 0, 4); // size - htobe32buf (buf + 11, nonce); - SendI2CPMessage (I2CP_MESSAGE_STATUS_MESSAGE, buf, 15); + htobe32buf (buf + 11, nonce); + SendI2CPMessage (I2CP_MESSAGE_STATUS_MESSAGE, buf, 15); } void I2CPSession::CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len) @@ -450,13 +450,13 @@ namespace client { offset += i2p::crypto::DSA_PRIVATE_KEY_LENGTH; // skip signing private key // we always assume this field as 20 bytes (DSA) regardless actual size - // instead of - //offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen (); + // instead of + //offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen (); m_Destination->SetEncryptionPrivateKey (buf + offset); offset += 256; m_Destination->LeaseSetCreated (buf + offset, len - offset); } - } + } else LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } @@ -476,10 +476,10 @@ namespace client offset += identsize; uint32_t payloadLen = bufbe32toh (buf + offset); if (payloadLen + offset <= len) - { + { offset += 4; uint32_t nonce = bufbe32toh (buf + offset + payloadLen); - if (m_IsSendAccepted) + if (m_IsSendAccepted) SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce); } @@ -488,16 +488,16 @@ namespace client } else LogPrint(eLogError, "I2CP: invalid identity"); - } - } + } + } else LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } void I2CPSession::SendMessageExpiresMessageHandler (const uint8_t * buf, size_t len) { - SendMessageMessageHandler (buf, len - 8); // ignore flags(2) and expiration(6) - } + SendMessageMessageHandler (buf, len - 8); // ignore flags(2) and expiration(6) + } void I2CPSession::HostLookupMessageHandler (const uint8_t * buf, size_t len) { @@ -507,7 +507,7 @@ namespace client uint32_t requestID = bufbe32toh (buf + 2); //uint32_t timeout = bufbe32toh (buf + 6); i2p::data::IdentHash ident; - switch (buf[10]) + switch (buf[10]) { case 0: // hash ident = i2p::data::IdentHash (buf + 11); @@ -521,7 +521,7 @@ namespace client SendHostReplyMessage (requestID, nullptr); return; } - break; + break; } default: LogPrint (eLogError, "I2CP: request type ", (int)buf[10], " is not supported"); @@ -530,7 +530,7 @@ namespace client } std::shared_ptr destination = m_Destination; - if(!destination) destination = i2p::client::context.GetSharedLocalDestination (); + if(!destination) destination = i2p::client::context.GetSharedLocalDestination (); if (destination) { auto ls = destination->FindLeaseSet (ident); @@ -544,11 +544,11 @@ namespace client { s->SendHostReplyMessage (requestID, leaseSet ? leaseSet->GetIdentity () : nullptr); }); - } + } } else SendHostReplyMessage (requestID, nullptr); - } + } else LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } @@ -563,7 +563,7 @@ namespace client htobe32buf (buf + 2, requestID); buf[6] = 0; // result code identity->ToBuffer (buf + 7, l - 7); - SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, l); + SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, l); delete[] buf; } else @@ -572,8 +572,8 @@ namespace client htobe16buf (buf, m_SessionID); htobe32buf (buf + 2, requestID); buf[6] = 1; // result code - SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, 7); - } + SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, 7); + } } void I2CPSession::DestLookupMessageHandler (const uint8_t * buf, size_t len) @@ -582,7 +582,7 @@ namespace client { auto ls = m_Destination->FindLeaseSet (buf); if (ls) - { + { auto l = ls->GetIdentity ()->GetFullLen (); uint8_t * identBuf = new uint8_t[l]; ls->GetIdentity ()->ToBuffer (identBuf, l); @@ -610,8 +610,8 @@ namespace client } } else - SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, buf, 32); - } + SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, buf, 32); + } void I2CPSession::GetBandwidthLimitsMessageHandler (const uint8_t * buf, size_t len) { @@ -631,16 +631,16 @@ namespace client buf[I2CP_HEADER_TYPE_OFFSET] = I2CP_MESSAGE_PAYLOAD_MESSAGE; htobe16buf (buf + I2CP_HEADER_SIZE, m_SessionID); htobe32buf (buf + I2CP_HEADER_SIZE + 2, m_MessageID++); - htobe32buf (buf + I2CP_HEADER_SIZE + 6, len); + htobe32buf (buf + I2CP_HEADER_SIZE + 6, len); memcpy (buf + I2CP_HEADER_SIZE + 10, payload, len); boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), - std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, buf)); + std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), + std::placeholders::_1, std::placeholders::_2, buf)); } I2CPServer::I2CPServer (const std::string& interface, int port): m_IsRunning (false), m_Thread (nullptr), - m_Acceptor (m_Service, + m_Acceptor (m_Service, #ifdef ANDROID I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address #else @@ -654,10 +654,10 @@ namespace client m_MessagesHandlers[I2CP_RECONFIGURE_SESSION_MESSAGE] = &I2CPSession::ReconfigureSessionMessageHandler; m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; - m_MessagesHandlers[I2CP_SEND_MESSAGE_EXPIRES_MESSAGE] = &I2CPSession::SendMessageExpiresMessageHandler; + m_MessagesHandlers[I2CP_SEND_MESSAGE_EXPIRES_MESSAGE] = &I2CPSession::SendMessageExpiresMessageHandler; m_MessagesHandlers[I2CP_HOST_LOOKUP_MESSAGE] = &I2CPSession::HostLookupMessageHandler; - m_MessagesHandlers[I2CP_DEST_LOOKUP_MESSAGE] = &I2CPSession::DestLookupMessageHandler; - m_MessagesHandlers[I2CP_GET_BANDWIDTH_LIMITS_MESSAGE] = &I2CPSession::GetBandwidthLimitsMessageHandler; + m_MessagesHandlers[I2CP_DEST_LOOKUP_MESSAGE] = &I2CPSession::DestLookupMessageHandler; + m_MessagesHandlers[I2CP_GET_BANDWIDTH_LIMITS_MESSAGE] = &I2CPSession::GetBandwidthLimitsMessageHandler; } I2CPServer::~I2CPServer () @@ -682,26 +682,26 @@ namespace client m_Sessions.clear (); m_Service.stop (); if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = nullptr; - } + } } - void I2CPServer::Run () - { + void I2CPServer::Run () + { while (m_IsRunning) { try - { + { m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "I2CP: runtime exception: ", ex.what ()); - } - } + } + } } void I2CPServer::Accept () @@ -719,7 +719,7 @@ namespace client boost::system::error_code ec; auto ep = socket->remote_endpoint (ec); if (!ec) - { + { LogPrint (eLogDebug, "I2CP: new connection from ", ep); auto session = std::make_shared(*this, socket); session->Start (); @@ -738,17 +738,17 @@ namespace client { if (!session) return false; if (!m_Sessions.insert({session->GetSessionID (), session}).second) - { + { LogPrint (eLogError, "I2CP: duplicate session id ", session->GetSessionID ()); return false; - } + } return true; } void I2CPServer::RemoveSession (uint16_t sessionID) { m_Sessions.erase (sessionID); - } + } } } diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 8c4f8ff0..657c72c1 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -26,25 +26,25 @@ namespace client const size_t I2CP_HEADER_LENGTH_OFFSET = 0; const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4; - const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; + const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; const uint8_t I2CP_GET_DATE_MESSAGE = 32; const uint8_t I2CP_SET_DATE_MESSAGE = 33; const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1; - const uint8_t I2CP_RECONFIGURE_SESSION_MESSAGE = 2; - const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20; + const uint8_t I2CP_RECONFIGURE_SESSION_MESSAGE = 2; + const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20; const uint8_t I2CP_DESTROY_SESSION_MESSAGE = 3; const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; - const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; + const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; - const uint8_t I2CP_SEND_MESSAGE_EXPIRES_MESSAGE = 36; + const uint8_t I2CP_SEND_MESSAGE_EXPIRES_MESSAGE = 36; const uint8_t I2CP_MESSAGE_PAYLOAD_MESSAGE = 31; - const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22; + const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22; const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38; - const uint8_t I2CP_HOST_REPLY_MESSAGE = 39; + const uint8_t I2CP_HOST_REPLY_MESSAGE = 39; const uint8_t I2CP_DEST_LOOKUP_MESSAGE = 34; - const uint8_t I2CP_DEST_REPLY_MESSAGE = 35; - const uint8_t I2CP_GET_BANDWIDTH_LIMITS_MESSAGE = 8; + const uint8_t I2CP_DEST_REPLY_MESSAGE = 35; + const uint8_t I2CP_GET_BANDWIDTH_LIMITS_MESSAGE = 8; const uint8_t I2CP_BANDWIDTH_LIMITS_MESSAGE = 23; enum I2CPMessageStatus @@ -56,8 +56,8 @@ namespace client }; // params - const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet"; - const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability"; + const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet"; + const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability"; class I2CPSession; class I2CPDestination: public LeaseSetDestination @@ -83,7 +83,7 @@ namespace client private: std::shared_ptr GetSharedFromThis () - { return std::static_pointer_cast(shared_from_this ()); } + { return std::static_pointer_cast(shared_from_this ()); } bool SendMsg (std::shared_ptr msg, std::shared_ptr remote); private: @@ -100,11 +100,11 @@ namespace client { public: -#ifdef ANDROID +#ifdef ANDROID typedef boost::asio::local::stream_protocol proto; #else typedef boost::asio::ip::tcp proto; -#endif +#endif I2CPSession (I2CPServer& owner, std::shared_ptr socket); @@ -115,9 +115,9 @@ namespace client uint16_t GetSessionID () const { return m_SessionID; }; std::shared_ptr GetDestination () const { return m_Destination; }; - // called from I2CPDestination + // called from I2CPDestination void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); - void SendMessagePayloadMessage (const uint8_t * payload, size_t len); + void SendMessagePayloadMessage (const uint8_t * payload, size_t len); void SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status); // message handlers @@ -133,7 +133,7 @@ namespace client void GetBandwidthLimitsMessageHandler (const uint8_t * buf, size_t len); private: - + void ReadProtocolByte (); void ReceiveHeader (); void HandleReceivedHeader (const boost::system::error_code& ecode, std::size_t bytes_transferred); @@ -141,7 +141,7 @@ namespace client void HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleMessage (); void Terminate (); - + void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf); std::string ExtractString (const uint8_t * buf, size_t len); size_t PutString (uint8_t * buf, size_t len, const std::string& str); @@ -163,14 +163,14 @@ namespace client bool m_IsSendAccepted; }; typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len); - + class I2CPServer { public: I2CPServer (const std::string& interface, int port); ~I2CPServer (); - + void Start (); void Stop (); boost::asio::io_service& GetService () { return m_Service; }; @@ -187,12 +187,12 @@ namespace client void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket); private: - + I2CPMessageHandler m_MessagesHandlers[256]; std::map > m_Sessions; bool m_IsRunning; - std::thread * m_Thread; + std::thread * m_Thread; boost::asio::io_service m_Service; I2CPSession::proto::acceptor m_Acceptor; @@ -202,7 +202,7 @@ namespace client // for HTTP const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; - }; + }; } } diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index fd5e8999..1054a63c 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -42,11 +42,11 @@ 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) - { + inline void SetLocalDestination (std::shared_ptr dest) + { if (m_LocalDestination) m_LocalDestination->Release (); if (dest) dest->Acquire (); - m_LocalDestination = dest; + m_LocalDestination = dest; } void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0); void CreateStream(StreamRequestComplete complete, const i2p::data::IdentHash & ident, int port); diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 140140fc..13728eba 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -25,7 +25,7 @@ namespace client SAMSocket::~SAMSocket () { Terminate ("~SAMSocket()"); - } + } void SAMSocket::CloseStream (const char* reason) { @@ -34,13 +34,13 @@ namespace client { m_Stream->Close (); m_Stream.reset (); - } - } - + } + } + void SAMSocket::Terminate (const char* reason) { CloseStream (reason); - + switch (m_SocketType) { case eSAMSocketTypeSession: @@ -217,7 +217,7 @@ namespace client if (!strcmp (m_Buffer, SAM_SESSION_CREATE)) ProcessSessionCreate (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_CONNECT)) - ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1, bytes_transferred - (eol - m_Buffer) - 1); + ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1, bytes_transferred - (eol - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_ACCEPT)) ProcessStreamAccept (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_DEST_GENERATE)) @@ -375,11 +375,11 @@ namespace client if (m_Session) { if (rem > 0) // handle follow on data - { + { memmove (m_Buffer, buf + len + 1, rem); // buf is a pointer to m_Buffer's content - m_BufferOffset = rem; + m_BufferOffset = rem; } - else + else m_BufferOffset = 0; auto dest = std::make_shared (); @@ -442,7 +442,7 @@ namespace client m_Session->AddSocket (shared_from_this ()); if (!m_Session->localDestination->IsAcceptingStreams ()) { - m_IsAccepting = true; + m_IsAccepting = true; m_Session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); @@ -638,7 +638,7 @@ namespace client { if (!ecode) s->Receive (); - else + else s->m_Owner.GetService ().post ([s] { s->Terminate ("AsyncSend failed"); }); }); } @@ -668,7 +668,7 @@ namespace client } else // no more data Terminate ("no more data"); - } + } } } @@ -692,7 +692,7 @@ namespace client { auto s = shared_from_this (); m_Owner.GetService ().post ([s] { s->Terminate ("stream read error (op aborted)"); }); - } + } } else { @@ -915,7 +915,7 @@ namespace client { // extract signature type i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; - i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; + i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; if (params) { auto it = params->find (SAM_PARAM_SIGNATURE_TYPE); diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index f2c84e3c..3cbe0447 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -80,7 +80,7 @@ namespace client public: SAMSocket (SAMBridge& owner); - ~SAMSocket (); + ~SAMSocket (); void CloseStream (const char* reason); // TODO: implement it better boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; @@ -133,7 +133,7 @@ namespace client SAMSocketType m_SocketType; std::string m_ID; // nickname bool m_IsSilent; - bool m_IsAccepting; // for eSAMSocketTypeAcceptor only + bool m_IsAccepting; // for eSAMSocketTypeAcceptor only std::shared_ptr m_Stream; std::shared_ptr m_Session; }; diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 631d3e5c..ddf4bbe9 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -22,8 +22,8 @@ namespace proxy static const size_t SOCKS_FORWARDER_BUFFER_SIZE = 8192; static const size_t SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE = 8; - - struct SOCKSDnsAddress + + struct SOCKSDnsAddress { uint8_t size; char value[max_socks_hostname_size]; @@ -38,10 +38,10 @@ namespace proxy }; class SOCKSServer; - class SOCKSHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this + class SOCKSHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this { private: - enum state + enum state { GET_SOCKSV, GET_COMMAND, @@ -62,20 +62,20 @@ namespace proxy UPSTREAM_CONNECT, UPSTREAM_HANDSHAKE }; - enum authMethods + enum authMethods { AUTH_NONE = 0, //No authentication, skip to next step AUTH_GSSAPI = 1, //GSSAPI authentication AUTH_USERPASSWD = 2, //Username and password AUTH_UNACCEPTABLE = 0xff //No acceptable method found }; - enum addrTypes + enum addrTypes { ADDR_IPV4 = 1, //IPv4 address (4 octets) ADDR_DNS = 3, // DNS name (up to 255 octets) ADDR_IPV6 = 4 //IPV6 address (16 octets) }; - enum errTypes + enum errTypes { SOCKS5_OK = 0, // No error for SOCKS5 SOCKS5_GEN_FAIL = 1, // General server failure @@ -91,18 +91,18 @@ namespace proxy SOCKS4_IDENTD_MISSING = 92, // Couldn't connect to the identd server SOCKS4_IDENTD_DIFFER = 93 // The ID reported by the application and by identd differ }; - enum cmdTypes + enum cmdTypes { CMD_CONNECT = 1, // TCP Connect CMD_BIND = 2, // TCP Bind CMD_UDP = 3 // UDP associate }; - enum socksVersions + enum socksVersions { SOCKS4 = 4, // SOCKS4 SOCKS5 = 5 // SOCKS5 }; - union address + union address { uint32_t ip; SOCKSDnsAddress dns; @@ -138,7 +138,7 @@ namespace proxy boost::asio::ip::tcp::resolver::iterator itr); void HandleUpstreamResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr); - + boost::asio::ip::tcp::resolver m_proxy_resolver; uint8_t m_sock_buff[socks_buffer_size]; std::shared_ptr m_sock, m_upstreamSock; @@ -163,7 +163,7 @@ namespace proxy const bool m_UseUpstreamProxy; // do we want to use the upstream proxy for non i2p addresses? const std::string m_UpstreamProxyAddress; const uint16_t m_UpstreamProxyPort; - + public: SOCKSHandler(SOCKSServer * parent, std::shared_ptr sock, const std::string & upstreamAddr, const uint16_t upstreamPort, const bool useUpstream) : I2PServiceHandler(parent), @@ -172,13 +172,13 @@ namespace proxy m_authchosen(AUTH_UNACCEPTABLE), m_addrtype(ADDR_IPV4), m_UseUpstreamProxy(useUpstream), m_UpstreamProxyAddress(upstreamAddr), - m_UpstreamProxyPort(upstreamPort) + m_UpstreamProxyPort(upstreamPort) { m_address.ip = 0; EnterState(GET_SOCKSV); } - + ~SOCKSHandler() { Terminate(); } void Handle() { AsyncSockRead(); } }; - + void SOCKSHandler::AsyncSockRead() { LogPrint(eLogDebug, "SOCKS: async sock read"); @@ -191,10 +191,10 @@ namespace proxy } } - void SOCKSHandler::Terminate() + void SOCKSHandler::Terminate() { if (Kill()) return; - if (m_sock) + if (m_sock) { LogPrint(eLogDebug, "SOCKS: closing socket"); m_sock->close(); @@ -206,7 +206,7 @@ namespace proxy m_upstreamSock->close(); m_upstreamSock = nullptr; } - if (m_stream) + if (m_stream) { LogPrint(eLogDebug, "SOCKS: closing stream"); m_stream.reset (); @@ -232,7 +232,7 @@ namespace proxy m_response[1] = error; //Response code m_response[2] = '\x00'; //RSV m_response[3] = type; //Address type - switch (type) + switch (type) { case ADDR_IPV4: size = 10; @@ -288,14 +288,14 @@ namespace proxy m_response[0] = '\x05'; //Version m_response[1] = m_authchosen; //Response code boost::asio::const_buffers_1 response(m_response,2); - if (m_authchosen == AUTH_UNACCEPTABLE) + if (m_authchosen == AUTH_UNACCEPTABLE) { LogPrint(eLogWarning, "SOCKS: v5 authentication negotiation failed"); boost::asio::async_write(*m_sock, response, std::bind(&SOCKSHandler::SentSocksFailed, shared_from_this(), std::placeholders::_1)); return false; - } - else + } + else { LogPrint(eLogDebug, "SOCKS: v5 choosing authentication method: ", m_authchosen); boost::asio::async_write(*m_sock, response, std::bind(&SOCKSHandler::SentSocksResponse, @@ -309,7 +309,7 @@ namespace proxy { boost::asio::const_buffers_1 response(nullptr,0); assert(error != SOCKS4_OK && error != SOCKS5_OK); - switch (m_socksv) + switch (m_socksv) { case SOCKS4: LogPrint(eLogWarning, "SOCKS: v4 request failed: ", error); @@ -329,7 +329,7 @@ namespace proxy { boost::asio::const_buffers_1 response(nullptr,0); //TODO: this should depend on things like the command type and callbacks may change - switch (m_socksv) + switch (m_socksv) { case SOCKS4: LogPrint(eLogInfo, "SOCKS: v4 connection success"); @@ -348,7 +348,7 @@ namespace proxy } void SOCKSHandler::EnterState(SOCKSHandler::state nstate, uint8_t parseleft) { - switch (nstate) + switch (nstate) { case GET_PORT: parseleft = 2; break; case GET_IPV4: m_addrtype = ADDR_IPV4; m_address.ip = 0; parseleft = 4; break; @@ -362,9 +362,9 @@ namespace proxy m_state = nstate; } - bool SOCKSHandler::ValidateSOCKSRequest() + bool SOCKSHandler::ValidateSOCKSRequest() { - if ( m_cmd != CMD_CONNECT ) + if ( m_cmd != CMD_CONNECT ) { //TODO: we need to support binds and other shit! LogPrint(eLogError, "SOCKS: unsupported command: ", m_cmd); @@ -372,9 +372,9 @@ namespace proxy return false; } //TODO: we may want to support other address types! - if ( m_addrtype != ADDR_DNS ) + if ( m_addrtype != ADDR_DNS ) { - switch (m_socksv) + switch (m_socksv) { case SOCKS5: LogPrint(eLogError, "SOCKS: v5 unsupported address type: ", m_addrtype); @@ -392,13 +392,13 @@ namespace proxy bool SOCKSHandler::HandleData(uint8_t *sock_buff, std::size_t len) { assert(len); // This should always be called with a least a byte left to parse - while (len > 0) + while (len > 0) { - switch (m_state) + switch (m_state) { case GET_SOCKSV: m_socksv = (SOCKSHandler::socksVersions) *sock_buff; - switch (*sock_buff) + switch (*sock_buff) { case SOCKS4: EnterState(GET_COMMAND); //Initialize the parser at the right position @@ -419,14 +419,14 @@ namespace proxy m_parseleft --; if (*sock_buff == AUTH_NONE) m_authchosen = AUTH_NONE; - if ( m_parseleft == 0 ) + if ( m_parseleft == 0 ) { if (!Socks5ChooseAuth()) return false; EnterState(GET5_REQUESTV); } break; case GET_COMMAND: - switch (*sock_buff) + switch (*sock_buff) { case CMD_CONNECT: case CMD_BIND: @@ -439,7 +439,7 @@ namespace proxy return false; } m_cmd = (SOCKSHandler::cmdTypes)*sock_buff; - switch (m_socksv) + switch (m_socksv) { case SOCKS5: EnterState(GET5_GETRSV); break; case SOCKS4: EnterState(GET_PORT); break; @@ -448,9 +448,9 @@ namespace proxy case GET_PORT: m_port = (m_port << 8)|((uint16_t)*sock_buff); m_parseleft--; - if (m_parseleft == 0) + if (m_parseleft == 0) { - switch (m_socksv) + switch (m_socksv) { case SOCKS5: EnterState(READY); break; case SOCKS4: EnterState(GET_IPV4); break; @@ -460,9 +460,9 @@ namespace proxy case GET_IPV4: m_address.ip = (m_address.ip << 8)|((uint32_t)*sock_buff); m_parseleft--; - if (m_parseleft == 0) + if (m_parseleft == 0) { - switch (m_socksv) + switch (m_socksv) { case SOCKS5: EnterState(GET_PORT); break; case SOCKS4: EnterState(GET4_IDENT); m_4aip = m_address.ip; break; @@ -470,7 +470,7 @@ namespace proxy } break; case GET4_IDENT: - if (!*sock_buff) + if (!*sock_buff) { if( m_4aip == 0 || m_4aip > 255 ) EnterState(READY); @@ -479,12 +479,12 @@ namespace proxy } break; case GET4A_HOST: - if (!*sock_buff) + if (!*sock_buff) { EnterState(READY); break; } - if (m_address.dns.size >= max_socks_hostname_size) + if (m_address.dns.size >= max_socks_hostname_size) { LogPrint(eLogError, "SOCKS: v4a req failed: destination is too large"); SocksRequestFailed(SOCKS4_FAIL); @@ -493,7 +493,7 @@ namespace proxy m_address.dns.push_back(*sock_buff); break; case GET5_REQUESTV: - if (*sock_buff != SOCKS5) + if (*sock_buff != SOCKS5) { LogPrint(eLogError,"SOCKS: v5 rejected unknown request version: ", ((int)*sock_buff)); SocksRequestFailed(SOCKS5_GEN_FAIL); @@ -502,7 +502,7 @@ namespace proxy EnterState(GET_COMMAND); break; case GET5_GETRSV: - if ( *sock_buff != 0 ) + if ( *sock_buff != 0 ) { LogPrint(eLogError, "SOCKS: v5 unknown reserved field: ", ((int)*sock_buff)); SocksRequestFailed(SOCKS5_GEN_FAIL); @@ -511,7 +511,7 @@ namespace proxy EnterState(GET5_GETADDRTYPE); break; case GET5_GETADDRTYPE: - switch (*sock_buff) + switch (*sock_buff) { case ADDR_IPV4: EnterState(GET_IPV4); break; case ADDR_IPV6: EnterState(GET5_IPV6); break; @@ -542,7 +542,7 @@ namespace proxy } sock_buff++; len--; - if (m_state == READY) + if (m_state == READY) { m_remaining_data_len = len; m_remaining_data = sock_buff; @@ -555,16 +555,16 @@ namespace proxy void SOCKSHandler::HandleSockRecv(const boost::system::error_code & ecode, std::size_t len) { LogPrint(eLogDebug, "SOCKS: received ", len, " bytes"); - if(ecode) + if(ecode) { LogPrint(eLogWarning, "SOCKS: recv got error: ", ecode); Terminate(); return; } - if (HandleData(m_sock_buff, len)) + if (HandleData(m_sock_buff, len)) { - if (m_state == READY) + if (m_state == READY) { const std::string addr = m_address.dns.ToString(); LogPrint(eLogInfo, "SOCKS: requested ", addr, ":" , m_port); @@ -578,10 +578,10 @@ namespace proxy // forward it to upstream proxy ForwardSOCKS(); } else { - // no upstream proxy + // no upstream proxy SocksRequestFailed(SOCKS5_ADDR_UNSUP); } - } + } else AsyncSockRead(); } @@ -596,7 +596,7 @@ namespace proxy void SOCKSHandler::SentSocksDone(const boost::system::error_code & ecode) { - if (!ecode) + if (!ecode) { if (Kill()) return; LogPrint (eLogInfo, "SOCKS: new I2PTunnel connection"); @@ -614,7 +614,7 @@ namespace proxy void SOCKSHandler::SentSocksResponse(const boost::system::error_code & ecode) { - if (ecode) + if (ecode) { LogPrint (eLogError, "SOCKS: closing socket after sending reply because: ", ecode.message ()); Terminate(); @@ -623,18 +623,18 @@ namespace proxy void SOCKSHandler::HandleStreamRequestComplete (std::shared_ptr stream) { - if (stream) + if (stream) { m_stream = stream; SocksRequestSuccess(); - } - else + } + else { LogPrint (eLogError, "SOCKS: error when creating the stream, check the previous warnings for more info"); SocksRequestFailed(SOCKS5_HOST_UNREACH); } } - + void SOCKSHandler::ForwardSOCKS() { LogPrint(eLogInfo, "SOCKS: forwarding to upstream"); @@ -656,7 +656,7 @@ namespace proxy SocksRequestFailed(SOCKS5_GEN_FAIL); } } - + void SOCKSHandler::HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered) { if (ecode) { @@ -675,7 +675,7 @@ namespace proxy { LogPrint(eLogInfo, "SOCKS: upstream success"); boost::asio::const_buffers_1 response(nullptr, 0); - switch (m_socksv) + switch (m_socksv) { case SOCKS4: LogPrint(eLogInfo, "SOCKS: v4 connection success"); @@ -694,9 +694,9 @@ namespace proxy GetOwner()->AddHandler(forwarder); forwarder->Start(); Terminate(); - + } - + void SOCKSHandler::HandleUpstreamData(uint8_t * dataptr, std::size_t len) { if (m_state == UPSTREAM_HANDSHAKE) { @@ -726,7 +726,7 @@ namespace proxy LogPrint(eLogError, "SOCKS: invalid state reading from upstream: ", (int) m_state); } } - + void SOCKSHandler::SendUpstreamRequest() { LogPrint(eLogInfo, "SOCKS: negotiating with upstream proxy"); @@ -739,7 +739,7 @@ namespace proxy LogPrint(eLogError, "SOCKS: no upstream socket to send handshake to"); } } - + void SOCKSHandler::HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) { if (ecode) { @@ -750,7 +750,7 @@ namespace proxy LogPrint(eLogInfo, "SOCKS: connected to upstream proxy"); SendUpstreamRequest(); } - + void SOCKSHandler::HandleUpstreamResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) { if (ecode) { @@ -768,9 +768,9 @@ namespace proxy shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } - SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port, - bool outEnable, const std::string& outAddress, uint16_t outPort, - std::shared_ptr localDestination) : + SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port, + bool outEnable, const std::string& outAddress, uint16_t outPort, + std::shared_ptr localDestination) : TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name) { m_UseUpstreamProxy = false; diff --git a/libi2pd_client/WebSocks.cpp b/libi2pd_client/WebSocks.cpp index b6faa711..0b8062d3 100644 --- a/libi2pd_client/WebSocks.cpp +++ b/libi2pd_client/WebSocks.cpp @@ -285,7 +285,7 @@ namespace client } else { // forward data LogPrint(eLogDebug, "websocks recv ", n); - + std::string str((char*)m_RecvBuf, n); auto conn = m_Parent->GetConn(m_Conn); if(!conn) { @@ -295,7 +295,7 @@ namespace client } conn->send(str); AsyncRecv(); - + } } @@ -339,7 +339,7 @@ namespace client EnterState(eWSCFailConnect); } } - + virtual void GotMessage(const websocketpp::connection_hdl & conn, WebSocksServerImpl::message_ptr msg) { (void) conn; diff --git a/libi2pd_client/Websocket.h b/libi2pd_client/Websocket.h index 2ddca38f..3a754e49 100644 --- a/libi2pd_client/Websocket.h +++ b/libi2pd_client/Websocket.h @@ -7,7 +7,7 @@ namespace i2p { class WebsocketServerImpl; - + class WebsocketServer { public: @@ -18,7 +18,7 @@ namespace i2p void Stop(); EventListener * ToListener(); - + private: WebsocketServerImpl * m_impl; }; diff --git a/qt/i2pd_qt/DaemonQT.cpp b/qt/i2pd_qt/DaemonQT.cpp index 582ad0f3..dd7c892d 100644 --- a/qt/i2pd_qt/DaemonQT.cpp +++ b/qt/i2pd_qt/DaemonQT.cpp @@ -15,7 +15,7 @@ namespace qt { } - void Worker::startDaemon() + void Worker::startDaemon() { qDebug("Performing daemon start..."); //try{ @@ -28,7 +28,7 @@ namespace qt emit resultReady(true, QObject::tr("Error: unknown exception")); }*/ } - void Worker::restartDaemon() + void Worker::restartDaemon() { qDebug("Performing daemon restart..."); //try{ @@ -55,7 +55,7 @@ namespace qt } Controller::Controller(DaemonQTImpl& daemon): - m_Daemon (daemon) + m_Daemon (daemon) { Worker *worker = new Worker (m_Daemon); worker->moveToThread(&workerThread); @@ -66,7 +66,7 @@ namespace qt connect(worker, &Worker::resultReady, this, &Controller::handleResults); workerThread.start(); } - Controller::~Controller() + Controller::~Controller() { qDebug("Closing and waiting for daemon worker thread..."); workerThread.quit(); @@ -79,7 +79,7 @@ namespace qt qDebug("Stopped the daemon."); } } - + DaemonQTImpl::DaemonQTImpl (): mutex(nullptr), m_IsRunning(nullptr), m_RunningChangedCallback(nullptr) { @@ -119,7 +119,7 @@ namespace qt start(); } - void DaemonQTImpl::setRunningCallback(runningChangedCallback cb) + void DaemonQTImpl::setRunningCallback(runningChangedCallback cb) { m_RunningChangedCallback = cb; } @@ -132,7 +132,7 @@ namespace qt void DaemonQTImpl::setRunning(bool newValue) { bool oldValue = m_IsRunning; - if(oldValue!=newValue) + if(oldValue!=newValue) { m_IsRunning = newValue; if(m_RunningChangedCallback) diff --git a/qt/i2pd_qt/DaemonQT.h b/qt/i2pd_qt/DaemonQT.h index fc874f34..d0add0e3 100644 --- a/qt/i2pd_qt/DaemonQT.h +++ b/qt/i2pd_qt/DaemonQT.h @@ -15,7 +15,7 @@ namespace qt public: DaemonQTImpl (); - ~DaemonQTImpl (); + ~DaemonQTImpl (); typedef void (*runningChangedCallback)(); @@ -45,11 +45,11 @@ namespace qt Q_OBJECT public: - Worker (DaemonQTImpl& daemon); + Worker (DaemonQTImpl& daemon); private: - DaemonQTImpl& m_Daemon; + DaemonQTImpl& m_Daemon; public slots: void startDaemon(); @@ -58,7 +58,7 @@ namespace qt signals: void resultReady(bool failed, QString failureMessage); - }; + }; class Controller : public QObject { @@ -68,7 +68,7 @@ namespace qt Controller(DaemonQTImpl& daemon); ~Controller(); private: - DaemonQTImpl& m_Daemon; + DaemonQTImpl& m_Daemon; public slots: void handleResults(bool failed, QString failureMessage){ diff --git a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java index 23b32312..aea50bf6 100644 --- a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java +++ b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java @@ -23,7 +23,7 @@ public class I2PDMainActivity extends QtActivity public void onCreate(Bundle savedInstanceState) { I2PDMainActivity.setInstance(this); super.onCreate(savedInstanceState); - + //set the app be foreground (do not unload when RAM needed) doBindService(); } @@ -45,8 +45,8 @@ public class I2PDMainActivity extends QtActivity private static void setInstance(I2PDMainActivity instance) { I2PDMainActivity.instance = instance; } - - + + // private LocalService mBoundService; @@ -82,7 +82,7 @@ public class I2PDMainActivity extends QtActivity // class name because we want a specific service implementation that // we know will be running in our own process (and thus won't be // supporting component replacement by other applications). - bindService(new Intent(this, + bindService(new Intent(this, LocalService.class), mConnection, Context.BIND_AUTO_CREATE); mIsBound = true; } diff --git a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java index 4c158c08..e2901504 100644 --- a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java +++ b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java @@ -35,8 +35,8 @@ public class LocalService extends Service { // Display a notification about us starting. We put an icon in the status bar. showNotification(); - - + + } @Override diff --git a/qt/i2pd_qt/docs/patch_openssl_so_libs.html b/qt/i2pd_qt/docs/patch_openssl_so_libs.html index 0fb7d540..bc886abc 100644 --- a/qt/i2pd_qt/docs/patch_openssl_so_libs.html +++ b/qt/i2pd_qt/docs/patch_openssl_so_libs.html @@ -4,7 +4,7 @@

OpenSSL под Android в Qt - +

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

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

Вначале действия полностью идентичны "расово-верному" руководству по компилянию OpenSSL для Android:
diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index e9e95ce1..fc1e5985 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -233,16 +233,16 @@ MainWindow::MainWindow(QWidget *parent) : initCheckBox( OPTION("upnp","enabled",[]{return "true";}), uiSettings->enableUPnPCheckBox); initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), uiSettings->upnpNameLineEdit); - + initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), uiSettings->useElGamalPrecomputedTablesCheckBox); - + initCheckBox( OPTION("reseed","verify",[]{return "";}), uiSettings->reseedVerifyCheckBox); initFileChooser( OPTION("reseed","file",[]{return "";}), uiSettings->reseedFileLineEdit, uiSettings->reseedFileBrowsePushButton); initStringBox( OPTION("reseed","urls",[]{return "";}), uiSettings->reseedURLsLineEdit); - + initStringBox( OPTION("addressbook","defaulturl",[]{return "";}), uiSettings->addressbookDefaultURLLineEdit); initStringBox( OPTION("addressbook","subscriptions",[]{return "";}), uiSettings->addressbookSubscriptionsURLslineEdit); - + initUInt16Box( OPTION("limits","transittunnels",[]{return "2500";}), uiSettings->maxNumOfTransitTunnelsLineEdit, tr("maxNumberOfTransitTunnels")); initUInt16Box( OPTION("limits","openfiles",[]{return "0";}), uiSettings->maxNumOfOpenFilesLineEdit, tr("maxNumberOfOpenFiles")); initUInt32Box( OPTION("limits","coresize",[]{return "0";}), uiSettings->coreFileMaxSizeNumberLineEdit, tr("coreFileMaxSize"));