diff --git a/.gitignore b/.gitignore index b6cffd15..73297488 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ netDb autom4te.cache .deps stamp-h1 -Makefile +#Makefile config.h config.h.in~ config.log @@ -238,3 +238,11 @@ pip-log.txt # Sphinx docs/_build /androidIdea/ + + +# emacs files +*~ +*\#* + +# gdb files +.gdb_history \ No newline at end of file diff --git a/Datagram.cpp b/Datagram.cpp index b9188864..d0b0737a 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -12,8 +12,10 @@ namespace i2p namespace datagram { DatagramDestination::DatagramDestination (std::shared_ptr owner): - m_Owner (owner.get()), m_Receiver (nullptr) + m_Owner (owner.get()), + m_Receiver (nullptr) { + m_Identity.FromBase64 (owner->GetIdentity()->ToBase64()); } DatagramDestination::~DatagramDestination () @@ -24,16 +26,16 @@ namespace datagram void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) { auto owner = m_Owner; - auto i = owner->GetIdentity(); - uint8_t buf[MAX_DATAGRAM_SIZE]; - auto identityLen = i->ToBuffer (buf, MAX_DATAGRAM_SIZE); + std::vector v(MAX_DATAGRAM_SIZE); + uint8_t * buf = v.data(); + auto identityLen = m_Identity.ToBuffer (buf, MAX_DATAGRAM_SIZE); uint8_t * signature = buf + identityLen; - auto signatureLen = i->GetSignatureLen (); + auto signatureLen = m_Identity.GetSignatureLen (); uint8_t * buf1 = signature + signatureLen; size_t headerLen = identityLen + signatureLen; memcpy (buf1, payload, len); - if (i->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + if (m_Identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) { uint8_t hash[32]; SHA256(buf1, len, hash); @@ -48,7 +50,7 @@ namespace datagram } - void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len) { i2p::data::IdentityEx identity; size_t identityLen = identity.FromBuffer (buf, len); @@ -93,7 +95,7 @@ namespace datagram uint8_t uncompressed[MAX_DATAGRAM_SIZE]; size_t uncompressedLen = m_Inflator.Inflate (buf, len, uncompressed, MAX_DATAGRAM_SIZE); if (uncompressedLen) - HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen); + HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen); } std::shared_ptr DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort) @@ -121,7 +123,7 @@ namespace datagram if (m_Sessions.empty ()) return; auto now = i2p::util::GetMillisecondsSinceEpoch(); LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); - std::lock_guard lock(m_SessionsMutex); + std::unique_lock lock(m_SessionsMutex); // for each session ... for (auto it = m_Sessions.begin (); it != m_Sessions.end (); ) { @@ -270,13 +272,16 @@ namespace datagram bool DatagramSession::ShouldUpdateRoutingPath() const { + bool dead = m_RoutingSession == nullptr || m_RoutingSession->GetSharedRoutingPath () == nullptr; auto now = i2p::util::GetMillisecondsSinceEpoch (); // we need to rotate paths becuase the routing path is too old - if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_SWITCH_INTERVAL) return true; + // if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_SWITCH_INTERVAL) return true; + // too fast switching paths + if (now - m_LastPathChange < DATAGRAM_SESSION_PATH_MIN_LIFETIME ) return false; // our path looks dead so we need to rotate paths - if (now - m_LastSuccess >= DATAGRAM_SESSION_PATH_TIMEOUT) return true; + if (now - m_LastSuccess >= DATAGRAM_SESSION_PATH_TIMEOUT) return !dead; // if we have a routing session and routing path we don't need to switch paths - return m_RoutingSession != nullptr && m_RoutingSession->GetSharedRoutingPath () != nullptr; + return dead; } @@ -291,7 +296,7 @@ namespace datagram if(currentLease) // if we have a lease return true if it's about to expire otherwise return false return currentLease->ExpiresWithin( DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE ); // we have no current lease, we should switch - return true; + return currentLease == nullptr; } std::shared_ptr DatagramSession::GetNextRoutingPath() diff --git a/Datagram.h b/Datagram.h index f3aae6f9..dc63cccb 100644 --- a/Datagram.h +++ b/Datagram.h @@ -22,14 +22,15 @@ namespace datagram // milliseconds for max session idle time const uint64_t DATAGRAM_SESSION_MAX_IDLE = 10 * 60 * 1000; // milliseconds for how long we try sticking to a dead routing path before trying to switch - const uint64_t DATAGRAM_SESSION_PATH_TIMEOUT = 5000; + const uint64_t DATAGRAM_SESSION_PATH_TIMEOUT = 10 * 1000; // milliseconds interval a routing path is used before switching - const uint64_t DATAGRAM_SESSION_PATH_SWITCH_INTERVAL = 60 * 1000; + const uint64_t DATAGRAM_SESSION_PATH_SWITCH_INTERVAL = 20 * 60 * 1000; // milliseconds before lease expire should we try switching leases const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW = 10 * 1000; // milliseconds fudge factor for leases handover const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000; - + // milliseconds minimum time between path switches + const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000; class DatagramSession { @@ -133,13 +134,14 @@ namespace datagram std::shared_ptr CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); - void HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); /** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */ Receiver FindReceiver(uint16_t port); private: i2p::client::ClientDestination * m_Owner; + i2p::data::IdentityEx m_Identity; Receiver m_Receiver; // default std::mutex m_SessionsMutex; std::map > m_Sessions; diff --git a/Destination.cpp b/Destination.cpp index 48717f5f..ccf1e6e2 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -203,15 +203,12 @@ namespace client if (ls && !ls->IsExpired ()) { ls->PopulateLeases (); // since we don't store them in netdb - { - std::lock_guard lock(m_RemoteLeaseSetsMutex); - m_RemoteLeaseSets[ident] = ls; - } + m_RemoteLeaseSets[ident] = ls; return ls; } } return nullptr; - } + } std::shared_ptr LeaseSetDestination::GetLeaseSet () { diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 0c58ba9d..be48b83a 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -559,23 +559,23 @@ namespace client } /** create new udp session */ boost::asio::ip::udp::endpoint ep(m_LocalAddress, 0); - m_Sessions.push_back(new UDPSession(ep, m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort)); + m_Sessions.push_back(new UDPSession(ep, m_LocalDest, m_RemoteEndpoint, &ih, localPort, remotePort)); return m_Sessions.back(); } UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, - boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, + boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash * to, uint16_t ourPort, uint16_t theirPort) : m_Destination(localDestination->GetDatagramDestination()), m_Service(localDestination->GetService()), IPSocket(localDestination->GetService(), localEndpoint), - Identity(to), SendEndpoint(endpoint), LastActivity(i2p::util::GetMillisecondsSinceEpoch()), LocalPort(ourPort), RemotePort(theirPort) { + memcpy(Identity, to->data(), 32); Receive(); } @@ -592,13 +592,7 @@ namespace client { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - uint8_t * data = new uint8_t[len]; - memcpy(data, m_Buffer, len); - m_Service.post([&,len, data] () { - m_Destination->SendDatagramTo(data, len, Identity, 0, 0); - delete [] data; - }); - + m_Destination->SendDatagramTo(m_Buffer, len, Identity, 0, 0); Receive(); } else { LogPrint(eLogError, "UDPSession: ", ecode.message()); @@ -727,7 +721,7 @@ namespace client if(m_Session) delete m_Session; boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); - m_Session = new UDPSession(m_LocalEndpoint, m_LocalDest, ep, *m_RemoteIdent, LocalPort, RemotePort); + m_Session = new UDPSession(m_LocalEndpoint, m_LocalDest, ep, m_RemoteIdent, LocalPort, RemotePort); } void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) diff --git a/I2PTunnel.h b/I2PTunnel.h index dce9f812..e6f0e84f 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -155,7 +155,7 @@ namespace client UDPSession(boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, - boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, + boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident, uint16_t ourPort, uint16_t theirPort); void HandleReceived(const boost::system::error_code & ecode, std::size_t len); void Receive(); diff --git a/Makefile.mingw b/Makefile.mingw index 2ab918b4..e2dae747 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -44,5 +44,10 @@ else CPU_FLAGS = -msse endif +ifeq ($(USE_ASLR),yes) + LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va \ + -Wl,--dynamicbase,--export-all-symbols +endif + obj/%.o : %.rc $(WINDRES) -i $< -o $@ diff --git a/appveyor.yml b/appveyor.yml index bb81757b..be16e890 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -142,9 +142,9 @@ install: - if not defined msvc ( C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy bash pacman pacman-mirrors msys2-runtime msys2-runtime-devel cmake" && if "%x64%" == "1" ( - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-openssl mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc" + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-openssl mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc mingw-w64-x86_64-extra-cmake-modules" ) else ( - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-openssl mingw-w64-i686-boost mingw-w64-i686-miniupnpc" + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-openssl mingw-w64-i686-boost mingw-w64-i686-miniupnpc mingw-w64-i686-extra-cmake-modules" ) ) cache: