diff --git a/.travis.yml b/.travis.yml index d83cdbc0..819c75f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ cache: apt: true os: - linux - - osx sudo: required dist: trusty addons: diff --git a/AddressBook.cpp b/AddressBook.cpp index cd15d68d..b3f0f1ce 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -173,7 +173,7 @@ namespace client return 0; } - for (auto it: addresses) { + for (const auto& it: addresses) { f << it.first << "," << it.second.ToBase32 () << std::endl; num++; } @@ -252,7 +252,7 @@ namespace client } LogPrint (eLogError, "Addressbook: subscription download timeout"); m_IsDownloading = false; - } + } if (m_Storage) { m_Storage->Save (m_Addresses); @@ -260,8 +260,6 @@ namespace client m_Storage = nullptr; } m_DefaultSubscription = nullptr; - for (auto it: m_Subscriptions) - delete it; m_Subscriptions.clear (); } @@ -403,7 +401,7 @@ namespace client { getline(f, s); if (!s.length()) continue; // skip empty line - m_Subscriptions.push_back (new AddressBookSubscription (*this, s)); + m_Subscriptions.push_back (std::make_shared (*this, s)); } LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded"); } @@ -418,7 +416,7 @@ namespace client { std::map localAddresses; m_Storage->LoadLocal (localAddresses); - for (auto it: localAddresses) + for (const auto& it: localAddresses) { auto dot = it.first.find ('.'); if (dot != std::string::npos) @@ -462,7 +460,7 @@ namespace client int nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT; if (success) { - if (m_DefaultSubscription) m_DefaultSubscription.reset (nullptr); + if (m_DefaultSubscription) m_DefaultSubscription = nullptr; if (m_IsLoaded) nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT; else @@ -516,16 +514,17 @@ namespace client // download it from http://i2p-projekt.i2p/hosts.txt LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription."); if (!m_DefaultSubscription) - m_DefaultSubscription.reset (new AddressBookSubscription (*this, DEFAULT_SUBSCRIPTION_ADDRESS)); + m_DefaultSubscription = std::make_shared(*this, DEFAULT_SUBSCRIPTION_ADDRESS); m_IsDownloading = true; - m_DefaultSubscription->CheckUpdates (); + std::thread load_hosts(std::bind (&AddressBookSubscription::CheckUpdates, m_DefaultSubscription)); + load_hosts.detach(); // TODO: use join } else if (!m_Subscriptions.empty ()) { // pick random subscription auto ind = rand () % m_Subscriptions.size(); m_IsDownloading = true; - std::thread load_hosts(&AddressBookSubscription::CheckUpdates, m_Subscriptions[ind]); + std::thread load_hosts(std::bind (&AddressBookSubscription::CheckUpdates, m_Subscriptions[ind])); load_hosts.detach(); // TODO: use join } } @@ -659,15 +658,16 @@ namespace client { std::unique_lock l(newDataReceivedMutex); i2p::client::context.GetSharedLocalDestination ()->RequestDestination (m_Ident, - [&newDataReceived, &leaseSet](std::shared_ptr ls) + [&newDataReceived, &leaseSet, &newDataReceivedMutex](std::shared_ptr ls) { leaseSet = ls; + std::unique_lock l1(newDataReceivedMutex); newDataReceived.notify_all (); }); if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout) { LogPrint (eLogError, "Addressbook: Subscription LeaseSet request timeout expired"); - i2p::client::context.GetSharedLocalDestination ()->CancelDestinationRequest (m_Ident); + i2p::client::context.GetSharedLocalDestination ()->CancelDestinationRequest (m_Ident, false); // don't notify, because we know it already return false; } } diff --git a/AddressBook.h b/AddressBook.h index fd852907..7f559cd0 100644 --- a/AddressBook.h +++ b/AddressBook.h @@ -102,8 +102,8 @@ namespace client std::map m_Lookups; // nonce -> address AddressBookStorage * m_Storage; volatile bool m_IsLoaded, m_IsDownloading; - std::vector m_Subscriptions; - std::unique_ptr m_DefaultSubscription; // in case if we don't know any addresses yet + std::vector > m_Subscriptions; + std::shared_ptr m_DefaultSubscription; // in case if we don't know any addresses yet boost::asio::deadline_timer * m_SubscriptionsUpdateTimer; }; diff --git a/BOB.cpp b/BOB.cpp index caf766af..8ffffba6 100644 --- a/BOB.cpp +++ b/BOB.cpp @@ -536,8 +536,8 @@ namespace client void BOBCommandSession::ListCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: list"); - auto& destinations = m_Owner.GetDestinations (); - for (auto it: destinations) + const auto& destinations = m_Owner.GetDestinations (); + for (const auto& it: destinations) SendData (it.first.c_str ()); SendReplyOK ("Listing done"); } @@ -619,7 +619,7 @@ namespace client BOBCommandChannel::~BOBCommandChannel () { Stop (); - for (auto it: m_Destinations) + for (const auto& it: m_Destinations) delete it.second; } @@ -633,7 +633,7 @@ namespace client void BOBCommandChannel::Stop () { m_IsRunning = false; - for (auto it: m_Destinations) + for (auto& it: m_Destinations) it.second->Stop (); m_Acceptor.cancel (); m_Service.stop (); diff --git a/ClientContext.cpp b/ClientContext.cpp index 2bc13969..aa18ecdf 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -194,7 +194,7 @@ namespace client LogPrint(eLogInfo, "Clients: stopping AddressBook"); m_AddressBook.Stop (); - for (auto it: m_Destinations) + for (auto& it: m_Destinations) it.second->Stop (); m_Destinations.clear (); m_SharedLocalDestination = nullptr; diff --git a/Config.cpp b/Config.cpp index 2a35ce7e..a629f2d4 100644 --- a/Config.cpp +++ b/Config.cpp @@ -147,12 +147,17 @@ namespace config { #endif "Enable or disable elgamal precomputation table") ; - - options_description trust("Trust options"); - trust.add_options() - ("trust.enabled", value()->default_value(false), "enable explicit trust options") - ("trust.family", value()->default_value(""), "Router Familiy to trust for first hops") - ("trust.hidden", value()->default_value(false), "should we hide our router from other routers?"); + + options_description reseed("Reseed options"); + reseed.add_options() + ("reseed.file", value()->default_value(""), "Path to .su3 file") + ; + + options_description trust("Trust options"); + trust.add_options() + ("trust.enabled", value()->default_value(false), "enable explicit trust options") + ("trust.family", value()->default_value(""), "Router Familiy to trust for first hops") + ("trust.hidden", value()->default_value(false), "should we hide our router from other routers?"); m_OptionsDesc .add(general) @@ -166,7 +171,8 @@ namespace config { .add(i2pcontrol) .add(upnp) .add(precomputation) - .add(trust) + .add(reseed) + .add(trust) ; } diff --git a/Destination.cpp b/Destination.cpp index 2df14a9f..42351787 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -103,7 +103,7 @@ namespace client { if (m_IsRunning) Stop (); - for (auto it: m_LeaseSetRequests) + for (auto& it: m_LeaseSetRequests) if (it.second->requestComplete) it.second->requestComplete (nullptr); m_LeaseSetRequests.clear (); if (m_Pool) @@ -479,24 +479,25 @@ namespace client { if (!m_Pool || !IsReady ()) { - if (requestComplete) requestComplete (nullptr); + if (requestComplete) + m_Service.post ([requestComplete](void){requestComplete (nullptr);}); return false; } m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete)); return true; } - void LeaseSetDestination::CancelDestinationRequest (const i2p::data::IdentHash& dest) + void LeaseSetDestination::CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify) { auto s = shared_from_this (); - m_Service.post ([dest, s](void) + m_Service.post ([dest, notify, s](void) { auto it = s->m_LeaseSetRequests.find (dest); if (it != s->m_LeaseSetRequests.end ()) { auto requestComplete = it->second->requestComplete; s->m_LeaseSetRequests.erase (it); - if (requestComplete) requestComplete (nullptr); + if (notify && requestComplete) requestComplete (nullptr); } }); } @@ -635,7 +636,7 @@ namespace client it = m_RemoteLeaseSets.erase (it); } else - it++; + ++it; } } @@ -663,7 +664,7 @@ namespace client { m_StreamingDestination = std::make_shared (GetSharedFromThis ()); // TODO: m_StreamingDestination->Start (); - for (auto it: m_StreamingDestinationsByPorts) + for (auto& it: m_StreamingDestinationsByPorts) it.second->Start (); return true; } @@ -677,7 +678,7 @@ namespace client { m_StreamingDestination->Stop (); m_StreamingDestination = nullptr; - for (auto it: m_StreamingDestinationsByPorts) + for (auto& it: m_StreamingDestinationsByPorts) it.second->Stop (); if (m_DatagramDestination) { diff --git a/Destination.h b/Destination.h index e64508c9..ac7ef7c9 100644 --- a/Destination.h +++ b/Destination.h @@ -79,7 +79,7 @@ namespace client bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; }; std::shared_ptr FindLeaseSet (const i2p::data::IdentHash& ident); bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr); - void CancelDestinationRequest (const i2p::data::IdentHash& dest); + void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true); // implements GarlicDestination std::shared_ptr GetLeaseSet (); diff --git a/Garlic.cpp b/Garlic.cpp index d48e9d94..c3c0e045 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -111,7 +111,7 @@ namespace garlic it = m_UnconfirmedTagsMsgs.erase (it); } else - it++; + ++it; } } @@ -123,7 +123,7 @@ namespace garlic if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) it = m_SessionTags.erase (it); else - it++; + ++it; } CleanupUnconfirmedTags (); return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty (); @@ -144,7 +144,7 @@ namespace garlic ret = true; } else - it++; + ++it; } return ret; } @@ -615,7 +615,7 @@ namespace garlic it = m_Tags.erase (it); } else - it++; + ++it; } if (numExpiredTags > 0) LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " tags expired for ", GetIdentHash().ToBase64 ()); @@ -631,7 +631,7 @@ namespace garlic it = m_Sessions.erase (it); } else - it++; + ++it; } } @@ -643,26 +643,26 @@ namespace garlic void GarlicDestination::DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID) { m_DeliveryStatusSessions[msgID] = session; - } + } void GarlicDestination::HandleDeliveryStatusMessage (std::shared_ptr msg) { uint32_t msgID = bufbe32toh (msg->GetPayload ()); { auto it = m_DeliveryStatusSessions.find (msgID); - if (it != m_DeliveryStatusSessions.end ()) + if (it != m_DeliveryStatusSessions.end ()) { it->second->MessageConfirmed (msgID); m_DeliveryStatusSessions.erase (it); LogPrint (eLogDebug, "Garlic: message ", msgID, " acknowledged"); - } + } } } void GarlicDestination::SetLeaseSetUpdated () { - std::unique_lock l(m_SessionsMutex); - for (auto it: m_Sessions) + std::unique_lock l(m_SessionsMutex); + for (auto& it: m_Sessions) it.second->SetLeaseSetUpdated (); } diff --git a/HTTP.cpp b/HTTP.cpp index 4a0286a7..08615e5b 100644 --- a/HTTP.cpp +++ b/HTTP.cpp @@ -160,7 +160,7 @@ namespace http { strsplit(query, tokens, '&'); params.clear(); - for (auto it : tokens) { + for (const auto& it : tokens) { std::size_t eq = it.find ('='); if (eq != std::string::npos) { auto e = std::pair(it.substr(0, eq), it.substr(eq + 1)); diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index b35c3b4a..60b6bc33 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -105,7 +105,7 @@ namespace proxy { ss << "

" << description << "

\r\n"; std::string content = ss.str(); SendProxyError(content); - } + } void HTTPReqHandler::HostNotFound(std::string & host) { std::stringstream ss; @@ -113,13 +113,13 @@ namespace proxy { << "

Remote host not found in router's addressbook

\r\n" << "

You may try to find this host on jumpservices below:

\r\n" << "
    \r\n"; - for (auto & js : jumpservices) { + for (const auto& js : jumpservices) { ss << "
  • " << js.first << "
  • \r\n"; } ss << "
\r\n"; std::string content = ss.str(); SendProxyError(content); - } + } void HTTPReqHandler::SendProxyError(std::string & content) { @@ -164,7 +164,7 @@ namespace proxy { req.del_header("Forwarded"); /* drop proxy-disclosing headers */ std::vector toErase; - for (auto it : req.headers) { + for (const auto& it : req.headers) { if (it.first.compare(0, 12, "X-Forwarded-") == 0) { toErase.push_back(it.first); } else if (it.first.compare(0, 6, "Proxy-") == 0) { @@ -173,7 +173,7 @@ namespace proxy { /* allow */ } } - for (auto header : toErase) { + for (const auto& header : toErase) { req.headers.erase(header); } /* replace headers */ diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 566ad53e..f10289ef 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -22,6 +22,9 @@ #include "HTTPServer.h" #include "Daemon.h" #include "util.h" +#ifdef WIN32_APP +#include "Win32/Win32App.h" +#endif // For image and info #include "version.h" @@ -65,7 +68,7 @@ namespace http { const char HTTP_PAGE_TUNNELS[] = "tunnels"; const char HTTP_PAGE_TRANSIT_TUNNELS[] = "transit_tunnels"; - const char HTTP_PAGE_TRANSPORTS[] = "transports"; + const char HTTP_PAGE_TRANSPORTS[] = "transports"; const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations"; const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination"; const char HTTP_PAGE_SAM_SESSIONS[] = "sam_sessions"; @@ -79,7 +82,7 @@ namespace http { const char HTTP_COMMAND_SHUTDOWN_CANCEL[] = "shutdown_cancel"; const char HTTP_COMMAND_SHUTDOWN_NOW[] = "terminate"; const char HTTP_COMMAND_RUN_PEER_TEST[] = "run_peer_test"; - const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config"; + const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config"; const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; const char HTTP_PARAM_ADDRESS[] = "address"; @@ -141,12 +144,14 @@ namespace http { " Main page
\r\n
\r\n" " Router commands
\r\n" " Local destinations
\r\n" - " Lease Sets
\r\n" + " LeaseSets
\r\n" " Tunnels
\r\n" " Transit tunnels
\r\n" " Transports
\r\n" - " I2P tunnels
\r\n" - " SAM sessions
\r\n" + " I2P tunnels
\r\n"; + if (i2p::client::context.GetSAMBridge ()) + s << " SAM sessions
\r\n"; + s << "\r\n" "
"; } @@ -207,7 +212,7 @@ namespace http { s << "Router Family: " << i2p::context.GetRouterInfo().GetProperty("family") << "
\r\n"; s << "Router Caps: " << i2p::context.GetRouterInfo().GetProperty("caps") << "
\r\n"; s << "Our external address:" << "
\r\n" ; - for (auto address : i2p::context.GetRouterInfo().GetAddresses()) + for (const auto& address : i2p::context.GetRouterInfo().GetAddresses()) { switch (address->transportStyle) { @@ -236,9 +241,9 @@ namespace http { size_t clientTunnelCount = i2p::tunnel::tunnels.CountOutboundTunnels(); clientTunnelCount += i2p::tunnel::tunnels.CountInboundTunnels(); size_t transitTunnelCount = i2p::tunnel::tunnels.CountTransitTunnels(); - - s << "Client Tunnels: " << std::to_string(clientTunnelCount) << " "; - s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n"; + + s << "Client Tunnels: " << std::to_string(clientTunnelCount) << " "; + s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n"; } void ShowLocalDestinations (std::stringstream& s) @@ -277,18 +282,18 @@ namespace http { it->Print(s); ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ()); } - } + } s << "
\r\n"; s << "Tags
Incoming: " << dest->GetNumIncomingTags () << "
Outgoing:
" << std::endl; - for (auto it: dest->GetSessions ()) + for (const auto& it: dest->GetSessions ()) { s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " "; s << it.second->GetNumOutgoingTags () << "
" << std::endl; - } + } s << "
" << std::endl; // s << "
\r\nStreams:
\r\n"; // for (auto it: dest->GetStreamingDestination ()->GetStreams ()) - // { + // { // s << it.first << "->" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetRemoteIdentity ()) << " "; // s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; // s << " [out:" << it.second->GetSendQueueSize () << "][in:" << it.second->GetReceiveQueueSize () << "]"; @@ -297,7 +302,7 @@ namespace http { // s << "[Window:" << it.second->GetWindowSize () << "]"; // s << "[Status:" << (int)it.second->GetStatus () << "]"; // s << "
\r\n"<< std::endl; - // } + // } s << "
\r\n"; s << ""; s << ""; @@ -311,8 +316,8 @@ namespace http { s << ""; s << ""; - for (auto it: dest->GetAllStreams ()) - { + for (const auto& it: dest->GetAllStreams ()) + { s << ""; s << ""; s << ""; @@ -326,12 +331,12 @@ namespace http { s << ""; s << "
\r\n" << std::endl; } - } + } } void ShowLeasesSets(std::stringstream& s) { - s << "
LeaseSets

"; + s << "
LeaseSets:

"; // for each lease set i2p::data::netdb.VisitLeaseSets( [&s](const i2p::data::IdentHash dest, std::shared_ptr leaseSet) @@ -379,7 +384,7 @@ namespace http { ); // end for each lease set } - + void ShowTunnels (std::stringstream& s) { s << "Queue size: " << i2p::tunnel::tunnels.GetQueueSize () << "
\r\n"; @@ -396,7 +401,7 @@ namespace http { ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ()); } s << "
\r\n"; - } + } void ShowCommands (std::stringstream& s) { @@ -406,31 +411,37 @@ namespace http { //s << " Reload config
\r\n"; if (i2p::context.AcceptsTunnels ()) s << " Decline transit tunnels
\r\n"; - else + else s << " Accept transit tunnels
\r\n"; #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) - if (Daemon.gracefullShutdownInterval) { + if (Daemon.gracefullShutdownInterval) + { s << " Cancel gracefull shutdown ("; s << Daemon.gracefullShutdownInterval; s << " seconds remains)
\r\n"; - } else { + } + else + { s << " Start gracefull shutdown
\r\n"; } - s << " Force shutdown
\r\n"; #endif +#ifdef WIN32_APP + s << " Gracefull shutdown
\r\n"; +#endif + s << " Force shutdown
\r\n"; } void ShowTransitTunnels (std::stringstream& s) { s << "Transit tunnels:
\r\n
\r\n"; - for (auto it: i2p::tunnel::tunnels.GetTransitTunnels ()) + for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) { if (std::dynamic_pointer_cast(it)) - s << it->GetTunnelID () << " ⇒ "; + s << it->GetTunnelID () << " ⇒ "; else if (std::dynamic_pointer_cast(it)) - s << " ⇒ " << it->GetTunnelID (); + s << " ⇒ " << it->GetTunnelID (); else - s << " ⇒ " << it->GetTunnelID () << " ⇒ "; + s << " ⇒ " << it->GetTunnelID () << " ⇒ "; s << " " << it->GetNumTransmittedBytes () << "
\r\n"; } } @@ -440,50 +451,50 @@ namespace http { s << "Transports:
\r\n
\r\n"; auto ntcpServer = i2p::transport::transports.GetNTCPServer (); if (ntcpServer) - { + { s << "NTCP
\r\n"; - for (auto it: ntcpServer->GetNTCPSessions ()) + for (const auto& it: ntcpServer->GetNTCPSessions ()) { if (it.second && it.second->IsEstablished ()) { // incoming connection doesn't have remote RI - if (it.second->IsOutgoing ()) s << " ⇒ "; + if (it.second->IsOutgoing ()) s << " ⇒ "; s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": " << it.second->GetSocket ().remote_endpoint().address ().to_string (); - if (!it.second->IsOutgoing ()) s << " ⇒ "; + if (!it.second->IsOutgoing ()) s << " ⇒ "; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; s << "
\r\n" << std::endl; } } - } + } auto ssuServer = i2p::transport::transports.GetSSUServer (); if (ssuServer) { s << "
\r\nSSU
\r\n"; - for (auto it: ssuServer->GetSessions ()) + for (const auto& it: ssuServer->GetSessions ()) { auto endpoint = it.second->GetRemoteEndpoint (); - if (it.second->IsOutgoing ()) s << " ⇒ "; + if (it.second->IsOutgoing ()) s << " ⇒ "; s << endpoint.address ().to_string () << ":" << endpoint.port (); - if (!it.second->IsOutgoing ()) s << " ⇒ "; + if (!it.second->IsOutgoing ()) s << " ⇒ "; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; if (it.second->GetRelayTag ()) s << " [itag:" << it.second->GetRelayTag () << "]"; s << "
\r\n" << std::endl; } s << "
\r\nSSU6
\r\n"; - for (auto it: ssuServer->GetSessionsV6 ()) + for (const auto& it: ssuServer->GetSessionsV6 ()) { auto endpoint = it.second->GetRemoteEndpoint (); - if (it.second->IsOutgoing ()) s << " ⇒ "; + if (it.second->IsOutgoing ()) s << " ⇒ "; s << endpoint.address ().to_string () << ":" << endpoint.port (); - if (!it.second->IsOutgoing ()) s << " ⇒ "; + if (!it.second->IsOutgoing ()) s << " ⇒ "; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; s << "
\r\n" << std::endl; } } } - + void ShowSAMSessions (std::stringstream& s) { auto sam = i2p::client::context.GetSAMBridge (); @@ -496,8 +507,8 @@ namespace http { { s << ""; s << it.first << "
\r\n" << std::endl; - } - } + } + } void ShowSAMSession (std::stringstream& s, const std::string& id) { @@ -517,7 +528,7 @@ namespace http { s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n"; s << "
\r\n"; s << "Streams:
\r\n"; - for (auto it: session->ListSockets()) + for (const auto& it: session->ListSockets()) { switch (it->GetSocketType ()) { @@ -528,8 +539,8 @@ namespace http { } s << " [" << it->GetSocket ().remote_endpoint() << "]"; s << "
\r\n"; - } - } + } + } void ShowI2PTunnels (std::stringstream& s) { @@ -538,21 +549,21 @@ namespace http { { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); s << ""; - s << it.second->GetName () << " ⇐ "; + s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; - } + } s << "
\r\nServer Tunnels:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetServerTunnels ()) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); s << ""; - s << it.second->GetName () << " ⇒ "; + s << it.second->GetName () << " ⇒ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << ":" << it.second->GetLocalPort (); s << "
\r\n"<< std::endl; - } - } + } + } HTTPConnection::HTTPConnection (std::shared_ptr socket): m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0) @@ -723,6 +734,9 @@ namespace http { i2p::context.SetAcceptsTunnels (false); #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) Daemon.gracefullShutdownInterval = 10*60; +#endif +#ifdef WIN32_APP + i2p::win32::GracefulShutdown (); #endif } else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) { i2p::context.SetAcceptsTunnels (true); @@ -740,7 +754,7 @@ namespace http { s << "Back to commands list
\r\n"; s << "

You will be redirected in 5 seconds"; res.add_header("Refresh", "5; url=/?page=commands"); - } + } void HTTPConnection::SendReply (HTTPRes& reply, std::string& content) { @@ -770,12 +784,14 @@ namespace http { std::string pass; i2p::config::GetOption("http.pass", pass); /* generate pass if needed */ if (needAuth && pass == "") { + uint8_t random[16]; char alnum[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; - pass.resize(16); - for (size_t i = 0; i < pass.size(); i++) { - pass[i] = alnum[rand() % (sizeof(alnum) - 1)]; + pass.resize(sizeof(random)); + RAND_bytes(random, sizeof(random)); + for (size_t i = 0; i < sizeof(random); i++) { + pass[i] = alnum[random[i] % (sizeof(alnum) - 1)]; } i2p::config::SetOption("http.pass", pass); LogPrint(eLogInfo, "HTTPServer: password set to ", pass); diff --git a/I2CP.cpp b/I2CP.cpp index 0867d719..0352cd15 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -659,7 +659,7 @@ namespace client { m_IsRunning = false; m_Acceptor.cancel (); - for (auto it: m_Sessions) + for (auto& it: m_Sessions) it.second->Stop (); m_Sessions.clear (); m_Service.stop (); diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index 92ab8281..cbd4c3fc 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -202,7 +202,7 @@ namespace i2p len += 32; buf[len] = routers.size (); len++; - for (auto it: routers) + for (const auto& it: routers) { memcpy (buf + len, it, 32); len += 32; diff --git a/I2PControl.cpp b/I2PControl.cpp index a55871a3..3e2e3997 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -358,7 +358,7 @@ namespace client void I2PControlService::RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { - for (auto it = params.begin (); it != params.end (); it++) + for (auto it = params.begin (); it != params.end (); ++it) { LogPrint (eLogDebug, "I2PControl: RouterInfo request: ", it->first); auto it1 = m_RouterInfoHandlers.find (it->first); @@ -434,7 +434,7 @@ namespace client void I2PControlService::RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { - for (auto it = params.begin (); it != params.end (); it++) + for (auto it = params.begin (); it != params.end (); ++it) { if (it != params.begin ()) results << ","; LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first); @@ -483,7 +483,7 @@ namespace client // network setting void I2PControlService::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { - for (auto it = params.begin (); it != params.end (); it++) + for (auto it = params.begin (); it != params.end (); ++it) { if (it != params.begin ()) results << ","; LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first); diff --git a/LeaseSet.cpp b/LeaseSet.cpp index fafe14b7..89cad0df 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -64,10 +64,10 @@ namespace data return; } - // reset existing leases + // reset existing leases if (m_StoreLeases) - for (auto it: m_Leases) - it->isUpdated = false; + for (auto& it: m_Leases) + it->isUpdated = false; else m_Leases.clear (); @@ -123,7 +123,7 @@ namespace data m_Leases.erase (it++); } else - it++; + ++it; } } @@ -167,7 +167,7 @@ namespace data { auto ts = i2p::util::GetMillisecondsSinceEpoch (); std::vector > leases; - for (auto it: m_Leases) + for (const auto& it: m_Leases) { auto endDate = it->endDate; if (withThreshold) @@ -183,7 +183,7 @@ namespace data bool LeaseSet::HasExpiredLeases () const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); - for (auto it: m_Leases) + for (const auto& it: m_Leases) if (ts >= it->endDate) return true; return false; } diff --git a/Makefile.mingw b/Makefile.mingw index 5cf16bf5..85b6b455 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -9,7 +9,7 @@ LDFLAGS = -Wl,-rpath,/usr/local/lib \ -L/usr/local/lib # UPNP Support -ifeq ($(USE_UPNP),yes) +ifeq ($(USE_UPNP),yes) CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB LDLIBS = -Wl,-Bstatic -lminiupnpc endif @@ -37,7 +37,7 @@ ifeq ($(USE_WIN32_APP), yes) DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) endif -ifeq ($(USE_AESNI),yes) +ifeq ($(USE_AESNI),1) CPU_FLAGS = -maes -DAESNI else CPU_FLAGS = -msse diff --git a/NTCPSession.cpp b/NTCPSession.cpp index d2c03857..b22b0f3c 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -19,7 +19,8 @@ namespace i2p namespace transport { NTCPSession::NTCPSession (NTCPServer& server, std::shared_ptr in_RemoteRouter): - TransportSession (in_RemoteRouter), m_Server (server), m_Socket (m_Server.GetService ()), + TransportSession (in_RemoteRouter, NTCP_TERMINATION_TIMEOUT), + m_Server (server), m_Socket (m_Server.GetService ()), m_TerminationTimer (m_Server.GetService ()), m_IsEstablished (false), m_IsTerminated (false), m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_IsSending (false) { @@ -665,7 +666,7 @@ namespace transport { m_IsSending = true; std::vector bufs; - for (auto it: msgs) + for (const auto& it: msgs) bufs.push_back (CreateMsgBuffer (it)); boost::asio::async_write (m_Socket, bufs, boost::asio::transfer_all (), std::bind(&NTCPSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, msgs)); @@ -715,7 +716,7 @@ namespace transport { if (m_SendQueue.size () < NTCP_MAX_OUTGOING_QUEUE_SIZE) { - for (auto it: msgs) + for (const auto& it: msgs) m_SendQueue.push_back (it); } else @@ -731,7 +732,7 @@ namespace transport void NTCPSession::ScheduleTermination () { m_TerminationTimer.cancel (); - m_TerminationTimer.expires_from_now (boost::posix_time::seconds(NTCP_TERMINATION_TIMEOUT)); + m_TerminationTimer.expires_from_now (boost::posix_time::seconds(GetTerminationTimeout ())); m_TerminationTimer.async_wait (std::bind (&NTCPSession::HandleTerminationTimer, shared_from_this (), std::placeholders::_1)); } @@ -740,7 +741,7 @@ namespace transport { if (ecode != boost::asio::error::operation_aborted) { - LogPrint (eLogDebug, "NTCP: No activity for ", NTCP_TERMINATION_TIMEOUT, " seconds"); + LogPrint (eLogDebug, "NTCP: No activity for ", GetTerminationTimeout (), " seconds"); //Terminate (); m_Socket.close ();// invoke Terminate () from HandleReceive } @@ -766,7 +767,7 @@ namespace transport m_Thread = new std::thread (std::bind (&NTCPServer::Run, this)); // create acceptors auto& addresses = context.GetRouterInfo ().GetAddresses (); - for (auto address: addresses) + for (const auto& address: addresses) { if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP) { diff --git a/NetDb.cpp b/NetDb.cpp index f5b51064..dc018326 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -14,7 +14,6 @@ #include "RouterContext.h" #include "Garlic.h" #include "NetDb.h" -#include "util.h" using namespace i2p::transport; @@ -52,7 +51,7 @@ namespace data { if (m_IsRunning) { - for (auto it: m_RouterInfos) + for (auto& it: m_RouterInfos) it.second->SaveProfile (); DeleteObsoleteProfiles (); m_RouterInfos.clear (); @@ -72,7 +71,7 @@ namespace data void NetDb::Run () { - uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0; + uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; while (m_IsRunning) { try @@ -122,7 +121,11 @@ namespace data } lastSave = ts; } - + if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT) + { + i2p::context.CleanupDestination (); + lastDestinationCleanup = ts; + } // if we're in hidden mode don't publish or explore // if (m_HiddenMode) continue; @@ -336,7 +339,7 @@ namespace data m_LastLoad = i2p::util::GetSecondsSinceEpoch(); std::vector files; m_Storage.Traverse(files); - for (auto path : files) + for (const auto& path : files) LoadRouterInfo(path); LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.size (), " floodfils)"); @@ -354,7 +357,7 @@ namespace data 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; - for (auto it: m_RouterInfos) + for (auto& it: m_RouterInfos) { std::string ident = it.second->GetIdentHashBase64(); std::string path = m_Storage.Path(ident); @@ -402,7 +405,7 @@ namespace data it = m_RouterInfos.erase (it); continue; } - it++; + ++it; } } // clean up expired floodfiils @@ -412,7 +415,7 @@ namespace data if ((*it)->IsUnreachable ()) it = m_Floodfills.erase (it); else - it++; + ++it; } } } @@ -898,7 +901,7 @@ namespace data { uint32_t i = 0; std::unique_lock l(m_RouterInfosMutex); - for (auto it: m_RouterInfos) + for (const auto& it: m_RouterInfos) { if (i >= ind) { @@ -930,7 +933,7 @@ namespace data else minMetric.SetMax (); std::unique_lock l(m_FloodfillsMutex); - for (auto it: m_Floodfills) + for (const auto& it: m_Floodfills) { if (!it->IsUnreachable ()) { @@ -961,7 +964,7 @@ namespace data if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash (); { std::unique_lock l(m_FloodfillsMutex); - for (auto it: m_Floodfills) + for (const auto& it: m_Floodfills) { if (!it->IsUnreachable ()) { @@ -980,11 +983,11 @@ namespace data std::vector res; size_t i = 0; - for (auto it: sorted) + for (const auto& it: sorted) { if (i < num) { - auto& ident = it.r->GetIdentHash (); + const auto& ident = it.r->GetIdentHash (); if (!excluded.count (ident)) { res.push_back (ident); @@ -1013,7 +1016,7 @@ namespace data IdentHash destKey = CreateRoutingKey (destination); minMetric.SetMax (); // must be called from NetDb thread only - for (auto it: m_RouterInfos) + for (const auto& it: m_RouterInfos) { if (!it.second->IsFloodfill ()) { @@ -1039,7 +1042,7 @@ namespace data it = m_LeaseSets.erase (it); } else - it++; + ++it; } } @@ -1051,7 +1054,7 @@ namespace data if (ts > it->second.second + 180) // 3 minutes it = m_LookupResponses.erase (it); else - it++; + ++it; } } } diff --git a/NetDbRequests.cpp b/NetDbRequests.cpp index e1ea2872..c3966597 100644 --- a/NetDbRequests.cpp +++ b/NetDbRequests.cpp @@ -141,7 +141,7 @@ namespace data if (done) it = m_RequestedDestinations.erase (it); else - it++; + ++it; } } } diff --git a/Profiling.cpp b/Profiling.cpp index be675502..890a2620 100644 --- a/Profiling.cpp +++ b/Profiling.cpp @@ -167,7 +167,7 @@ namespace data std::vector files; m_ProfilesStorage.Traverse(files); - for (auto path: files) { + for (const auto& path: files) { if (stat(path.c_str(), &st) != 0) { LogPrint(eLogWarning, "Profiling: Can't stat(): ", path); continue; diff --git a/Queue.h b/Queue.h index b47a19c8..39d139b9 100644 --- a/Queue.h +++ b/Queue.h @@ -7,6 +7,7 @@ #include #include #include +#include namespace i2p { @@ -20,7 +21,7 @@ namespace util void Put (Element e) { std::unique_lock l(m_QueueMutex); - m_Queue.push (e); + m_Queue.push (std::move(e)); m_NonEmpty.notify_one (); } @@ -29,7 +30,7 @@ namespace util if (!vec.empty ()) { std::unique_lock l(m_QueueMutex); - for (auto it: vec) + for (const auto& it: vec) m_Queue.push (it); m_NonEmpty.notify_one (); } diff --git a/Reseed.cpp b/Reseed.cpp index 236531f9..bac381b1 100644 --- a/Reseed.cpp +++ b/Reseed.cpp @@ -16,6 +16,7 @@ #include "NetDb.h" #include "HTTP.h" #include "util.h" +#include "Config.h" namespace i2p { @@ -51,6 +52,13 @@ namespace data int Reseeder::ReseedNowSU3 () { + std::string filename; i2p::config::GetOption("reseed.file", filename); + if (filename.length() > 0) // reseed file is specified + { + auto num = ProcessSU3File (filename.c_str ()); + if (num > 0) return num; // success + LogPrint (eLogWarning, "Can't reseed from ", filename, " . Trying from hosts"); + } auto ind = rand () % httpsReseedHostList.size (); std::string& reseedHost = httpsReseedHostList[ind]; return ReseedFromSU3 (reseedHost); diff --git a/RouterContext.cpp b/RouterContext.cpp index f2c2bc48..c92b575b 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -112,7 +112,7 @@ namespace i2p void RouterContext::UpdatePort (int port) { bool updated = false; - for (auto address : m_RouterInfo.GetAddresses ()) + for (auto& address : m_RouterInfo.GetAddresses ()) { if (address->port != port) { @@ -127,7 +127,7 @@ namespace i2p void RouterContext::UpdateAddress (const boost::asio::ip::address& host) { bool updated = false; - for (auto address : m_RouterInfo.GetAddresses ()) + for (auto& address : m_RouterInfo.GetAddresses ()) { if (address->host != host && address->IsCompatible (host)) { @@ -244,7 +244,7 @@ namespace i2p m_RouterInfo.SetCaps (i2p::data::RouterInfo::eUnreachable | i2p::data::RouterInfo::eSSUTesting); // LU, B // remove NTCP address auto& addresses = m_RouterInfo.GetAddresses (); - for (auto it = addresses.begin (); it != addresses.end (); it++) + for (auto it = addresses.begin (); it != addresses.end (); ++it) { if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportNTCP && (*it)->host.is_v4 ()) @@ -254,7 +254,7 @@ namespace i2p } } // delete previous introducers - for (auto addr : addresses) + for (auto& addr : addresses) addr->introducers.clear (); // update @@ -274,7 +274,7 @@ namespace i2p // insert NTCP back auto& addresses = m_RouterInfo.GetAddresses (); - for (auto addr : addresses) + for (const auto& addr : addresses) { if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU && addr->host.is_v4 ()) @@ -285,7 +285,7 @@ namespace i2p } } // delete previous introducers - for (auto addr : addresses) + for (auto& addr : addresses) addr->introducers.clear (); // update @@ -316,7 +316,7 @@ namespace i2p bool updated = false, found = false; int port = 0; auto& addresses = m_RouterInfo.GetAddresses (); - for (auto addr: addresses) + for (auto& addr: addresses) { if (addr->host.is_v6 () && addr->transportStyle == i2p::data::RouterInfo::eTransportNTCP) { @@ -439,6 +439,12 @@ namespace i2p std::unique_lock l(m_GarlicMutex); i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg); } + + void RouterContext::CleanupDestination () + { + std::unique_lock l(m_GarlicMutex); + i2p::garlic::GarlicDestination::CleanupExpiredTags (); + } uint32_t RouterContext::GetUptime () const { diff --git a/RouterContext.h b/RouterContext.h index 05339847..27e0947d 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -71,7 +71,8 @@ namespace i2p void SetSupportsV4 (bool supportsV4); void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session - void UpdateStats (); + void UpdateStats (); + void CleanupDestination (); // garlic destination // implements LocalDestination std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; diff --git a/RouterInfo.cpp b/RouterInfo.cpp index f497c30e..90cf5e44 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -369,19 +369,19 @@ namespace data SetProperty ("caps", caps); } - void RouterInfo::WriteToStream (std::ostream& s) + void RouterInfo::WriteToStream (std::ostream& s) const { uint64_t ts = htobe64 (m_Timestamp); - s.write ((char *)&ts, sizeof (ts)); + s.write ((const char *)&ts, sizeof (ts)); // addresses uint8_t numAddresses = m_Addresses->size (); s.write ((char *)&numAddresses, sizeof (numAddresses)); - for (auto addr : *m_Addresses) + for (const auto& addr_ptr : *m_Addresses) { - Address& address = *addr; - s.write ((char *)&address.cost, sizeof (address.cost)); - s.write ((char *)&address.date, sizeof (address.date)); + const Address& address = *addr_ptr; + s.write ((const char *)&address.cost, sizeof (address.cost)); + s.write ((const char *)&address.date, sizeof (address.date)); std::stringstream properties; if (address.transportStyle == eTransportNTCP) WriteString ("NTCP", s); @@ -410,7 +410,7 @@ namespace data if (address.introducers.size () > 0) { int i = 0; - for (auto introducer: address.introducers) + for (const auto& introducer: address.introducers) { WriteString ("ihost" + boost::lexical_cast(i), properties); properties << '='; @@ -419,7 +419,7 @@ namespace data i++; } i = 0; - for (auto introducer: address.introducers) + for (const auto& introducer: address.introducers) { WriteString ("ikey" + boost::lexical_cast(i), properties); properties << '='; @@ -431,7 +431,7 @@ namespace data i++; } i = 0; - for (auto introducer: address.introducers) + for (const auto& introducer: address.introducers) { WriteString ("iport" + boost::lexical_cast(i), properties); properties << '='; @@ -440,7 +440,7 @@ namespace data i++; } i = 0; - for (auto introducer: address.introducers) + for (const auto& introducer: address.introducers) { WriteString ("itag" + boost::lexical_cast(i), properties); properties << '='; @@ -482,7 +482,7 @@ namespace data // properties std::stringstream properties; - for (auto& p : m_Properties) + for (const auto& p : m_Properties) { WriteString (p.first, properties); properties << '='; @@ -570,10 +570,10 @@ namespace data addr->cost = 2; addr->date = 0; addr->mtu = 0; - for (auto it: *m_Addresses) // don't insert same address twice + for (const auto& it: *m_Addresses) // don't insert same address twice if (*it == *addr) return; - m_Addresses->push_back(addr); 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) @@ -586,21 +586,22 @@ namespace data addr->date = 0; addr->mtu = mtu; memcpy (addr->key, key, 32); - for (auto it: *m_Addresses) // don't insert same address twice + for (const auto& it: *m_Addresses) // don't insert same address twice if (*it == *addr) return; - m_Addresses->push_back(addr); m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4; - m_Caps |= eSSUTesting; - m_Caps |= eSSUIntroducer; + m_Addresses->push_back(std::move(addr)); + + m_Caps |= eSSUTesting; + m_Caps |= eSSUIntroducer; } bool RouterInfo::AddIntroducer (const Introducer& introducer) { - for (auto addr : *m_Addresses) + for (auto& addr : *m_Addresses) { if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ()) { - for (auto intro: addr->introducers) + for (auto& intro: addr->introducers) if (intro.iTag == introducer.iTag) return false; // already presented addr->introducers.push_back (introducer); return true; @@ -611,16 +612,16 @@ namespace data bool RouterInfo::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e) { - for (auto addr: *m_Addresses) + for (auto& addr: *m_Addresses) { if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ()) { - for (std::vector::iterator it = addr->introducers.begin (); it != addr->introducers.end (); it++) + for (auto it = addr->introducers.begin (); it != addr->introducers.end (); ++it) if ( boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e) { addr->introducers.erase (it); return true; - } + } } } return false; @@ -707,7 +708,7 @@ namespace data if (addr->host.is_v6 ()) it = m_Addresses->erase (it); else - it++; + ++it; } } } @@ -723,7 +724,7 @@ namespace data if (addr->host.is_v4 ()) it = m_Addresses->erase (it); else - it++; + ++it; } } } @@ -752,7 +753,7 @@ namespace data std::shared_ptr RouterInfo::GetAddress (TransportStyle s, bool v4only, bool v6only) const { auto addresses = m_Addresses; - for (auto address : *addresses) + for (const auto& address : *addresses) { if (address->transportStyle == s) { diff --git a/RouterInfo.h b/RouterInfo.h index 8c99d245..16937b5b 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -187,9 +187,9 @@ namespace data void ReadFromFile (); void ReadFromStream (std::istream& s); void ReadFromBuffer (bool verifySignature); - void WriteToStream (std::ostream& s); - size_t ReadString (char * str, std::istream& s); - void WriteString (const std::string& str, std::ostream& s); + void WriteToStream (std::ostream& s) const; + static size_t ReadString (char* str, std::istream& s); + static void WriteString (const std::string& str, std::ostream& s); void ExtractCaps (const char * value); std::shared_ptr GetAddress (TransportStyle s, bool v4only, bool v6only = false) const; void UpdateCapsProperty (); diff --git a/SAM.cpp b/SAM.cpp index 55eae222..2864cd6f 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -686,7 +686,7 @@ namespace client { { std::lock_guard lock(m_SocketsMutex); - for (auto sock : m_Sockets) { + for (auto& sock : m_Sockets) { sock->CloseStream(); } } @@ -719,7 +719,7 @@ namespace client { m_IsRunning = false; m_Acceptor.cancel (); - for (auto it: m_Sessions) + for (auto& it: m_Sessions) it.second->CloseStreams (); m_Sessions.clear (); m_Service.stop (); diff --git a/SAM.h b/SAM.h index ef36f285..db08c5a0 100644 --- a/SAM.h +++ b/SAM.h @@ -154,7 +154,7 @@ namespace client std::list > l; { std::lock_guard lock(m_SocketsMutex); - for( auto & sock : m_Sockets ) l.push_back(sock); + for(const auto& sock : m_Sockets ) l.push_back(sock); } return l; } diff --git a/SOCKS.cpp b/SOCKS.cpp index 73833191..9d85963b 100644 --- a/SOCKS.cpp +++ b/SOCKS.cpp @@ -26,7 +26,7 @@ namespace proxy { uint8_t size; char value[max_socks_hostname_size]; - void FromString (std::string str) + void FromString (const std::string& str) { size = str.length(); if (str.length() > max_socks_hostname_size) size = max_socks_hostname_size; diff --git a/SSU.cpp b/SSU.cpp index f4277a5a..0c3662d3 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -237,9 +237,8 @@ namespace transport std::map > * sessions) { std::shared_ptr session; - for (auto it1: packets) + for (auto& packet: packets) { - auto packet = it1; try { if (!session || session->GetRemoteEndpoint () != packet->from) // we received packet for other session than previous @@ -431,11 +430,11 @@ namespace transport void SSUServer::DeleteAllSessions () { - for (auto it: m_Sessions) + for (auto& it: m_Sessions) it.second->Close (); m_Sessions.clear (); - for (auto it: m_SessionsV6) + for (auto& it: m_SessionsV6) it.second->Close (); m_SessionsV6.clear (); } @@ -444,7 +443,7 @@ namespace transport std::shared_ptr SSUServer::GetRandomV4Session (Filter filter) // v4 only { std::vector > filteredSessions; - for (auto s :m_Sessions) + for (const auto& s :m_Sessions) if (filter (s.second)) filteredSessions.push_back (s.second); if (filteredSessions.size () > 0) { @@ -468,7 +467,7 @@ namespace transport std::shared_ptr SSUServer::GetRandomV6Session (Filter filter) // v6 only { std::vector > filteredSessions; - for (auto s :m_SessionsV6) + for (const auto& s :m_SessionsV6) if (filter (s.second)) filteredSessions.push_back (s.second); if (filteredSessions.size () > 0) { @@ -535,7 +534,7 @@ namespace transport std::list newList; size_t numIntroducers = 0; uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - for (auto it :m_Introducers) + for (const auto& it : m_Introducers) { auto session = FindSession (it); if (session && ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION) @@ -552,23 +551,20 @@ namespace transport { // create new auto introducers = FindIntroducers (SSU_MAX_NUM_INTRODUCERS); - if (introducers.size () > 0) + for (const auto& it1: introducers) { - for (auto it1: introducers) + const auto& ep = it1->GetRemoteEndpoint (); + i2p::data::RouterInfo::Introducer introducer; + introducer.iHost = ep.address (); + introducer.iPort = ep.port (); + introducer.iTag = it1->GetRelayTag (); + introducer.iKey = it1->GetIntroKey (); + if (i2p::context.AddIntroducer (introducer)) { - auto& ep = it1->GetRemoteEndpoint (); - i2p::data::RouterInfo::Introducer introducer; - introducer.iHost = ep.address (); - introducer.iPort = ep.port (); - introducer.iTag = it1->GetRelayTag (); - introducer.iKey = it1->GetIntroKey (); - if (i2p::context.AddIntroducer (introducer)) - { - newList.push_back (ep); - if (newList.size () >= SSU_MAX_NUM_INTRODUCERS) break; - } - } - } + newList.push_back (ep); + if (newList.size () >= SSU_MAX_NUM_INTRODUCERS) break; + } + } } m_Introducers = newList; if (m_Introducers.size () < SSU_MAX_NUM_INTRODUCERS) @@ -637,7 +633,7 @@ namespace transport it = m_PeerTests.erase (it); } else - it++; + ++it; } if (numDeleted > 0) LogPrint (eLogDebug, "SSU: ", numDeleted, " peer tests have been expired"); diff --git a/SSUData.cpp b/SSUData.cpp index 2bd65682..e5abfd54 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -25,10 +25,10 @@ namespace transport } SSUData::SSUData (SSUSession& session): - m_Session (session), m_ResendTimer (session.GetService ()), m_DecayTimer (session.GetService ()), + 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_PacketSize (m_MaxPacketSize), m_LastMessageReceivedTime (0) { } @@ -44,7 +44,6 @@ namespace transport void SSUData::Stop () { m_ResendTimer.cancel (); - m_DecayTimer.cancel (); m_IncompleteMessagesCleanupTimer.cancel (); } @@ -233,11 +232,8 @@ namespace transport { if (!m_ReceivedMessages.count (msgID)) { - if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES) - m_ReceivedMessages.clear (); - else - ScheduleDecay (); m_ReceivedMessages.insert (msgID); + m_LastMessageReceivedTime = i2p::util::GetSecondsSinceEpoch (); if (!msg->IsExpired ()) m_Handler.PutNextMessage (msg); else @@ -431,12 +427,12 @@ namespace transport if (ts >= it->second->nextResendTime) { if (it->second->numResends < MAX_NUM_RESENDS) - { + { for (auto& f: it->second->fragments) - if (f) + if (f) { try - { + { m_Session.Send (f->buf, f->len); // resend numResent++; } @@ -444,11 +440,11 @@ namespace transport { LogPrint (eLogWarning, "SSU: Can't resend data fragment ", ec.what ()); } - } + } it->second->numResends++; it->second->nextResendTime += it->second->numResends*RESEND_INTERVAL; - it++; + ++it; } else { @@ -457,7 +453,7 @@ namespace transport } } else - it++; + ++it; } if (numResent < MAX_OUTGOING_WINDOW_SIZE) ScheduleResend (); @@ -469,21 +465,6 @@ namespace transport } } - void SSUData::ScheduleDecay () - { - m_DecayTimer.cancel (); - m_DecayTimer.expires_from_now (boost::posix_time::seconds(DECAY_INTERVAL)); - auto s = m_Session.shared_from_this(); - m_ResendTimer.async_wait ([s](const boost::system::error_code& ecode) - { s->m_Data.HandleDecayTimer (ecode); }); - } - - void SSUData::HandleDecayTimer (const boost::system::error_code& ecode) - { - if (ecode != boost::asio::error::operation_aborted) - m_ReceivedMessages.clear (); - } - void SSUData::ScheduleIncompleteMessagesCleanup () { m_IncompleteMessagesCleanupTimer.cancel (); @@ -506,8 +487,13 @@ namespace transport it = m_IncompleteMessages.erase (it); } else - it++; + ++it; } + // decay + if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES || + i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL) + m_ReceivedMessages.clear (); + ScheduleIncompleteMessagesCleanup (); } } diff --git a/SSUData.h b/SSUData.h index bfc75128..f3ad9ea8 100644 --- a/SSUData.h +++ b/SSUData.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include "I2NPProtocol.h" @@ -109,9 +109,6 @@ namespace transport void ScheduleResend (); void HandleResendTimer (const boost::system::error_code& ecode); - void ScheduleDecay (); - void HandleDecayTimer (const boost::system::error_code& ecode); - void ScheduleIncompleteMessagesCleanup (); void HandleIncompleteMessagesCleanupTimer (const boost::system::error_code& ecode); @@ -121,10 +118,11 @@ namespace transport SSUSession& m_Session; std::map > m_IncompleteMessages; std::map > m_SentMessages; - std::set m_ReceivedMessages; - boost::asio::deadline_timer m_ResendTimer, m_DecayTimer, m_IncompleteMessagesCleanupTimer; + std::unordered_set m_ReceivedMessages; + boost::asio::deadline_timer m_ResendTimer, m_IncompleteMessagesCleanupTimer; int m_MaxPacketSize, m_PacketSize; i2p::I2NPMessagesHandler m_Handler; + uint32_t m_LastMessageReceivedTime; // in second }; } } diff --git a/SSUSession.cpp b/SSUSession.cpp index 3aae06ba..bf4058a5 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -12,7 +12,8 @@ namespace i2p namespace transport { SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, - std::shared_ptr router, bool peerTest ): TransportSession (router), + std::shared_ptr router, bool peerTest ): + TransportSession (router, SSU_TERMINATION_TIMEOUT), m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_Timer (GetService ()), m_IsPeerTest (peerTest),m_State (eSessionStateUnknown), m_IsSessionKey (false), m_RelayTag (0),m_Data (*this), m_IsDataReceived (false) @@ -882,7 +883,7 @@ namespace transport void SSUSession::ScheduleTermination () { m_Timer.cancel (); - m_Timer.expires_from_now (boost::posix_time::seconds(SSU_TERMINATION_TIMEOUT)); + m_Timer.expires_from_now (boost::posix_time::seconds(GetTerminationTimeout ())); m_Timer.async_wait (std::bind (&SSUSession::HandleTerminationTimer, shared_from_this (), std::placeholders::_1)); } @@ -891,7 +892,7 @@ namespace transport { if (ecode != boost::asio::error::operation_aborted) { - LogPrint (eLogWarning, "SSU: no activity with ", m_RemoteEndpoint, " for ", SSU_TERMINATION_TIMEOUT, " seconds"); + LogPrint (eLogWarning, "SSU: no activity with ", m_RemoteEndpoint, " for ", GetTerminationTimeout (), " seconds"); Failed (); } } @@ -906,7 +907,7 @@ namespace transport { if (m_State == eSessionStateEstablished) { - for (auto it: msgs) + for (const auto& it: msgs) if (it) m_Data.Send (it); } } diff --git a/Streaming.cpp b/Streaming.cpp index 3806d97d..90c363ea 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -247,7 +247,7 @@ namespace stream } int nackCount = packet->GetNACKCount (); for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();) - { + { auto seqn = (*it)->GetSeqn (); if (seqn <= ackThrough) { @@ -263,7 +263,7 @@ namespace stream if (nacked) { LogPrint (eLogDebug, "Streaming: Packet ", seqn, " NACK"); - it++; + ++it; continue; } } @@ -412,7 +412,7 @@ namespace stream } bool isEmpty = m_SentPackets.empty (); auto ts = i2p::util::GetMillisecondsSinceEpoch (); - for (auto it: packets) + for (auto& it: packets) { it->sendTime = ts; m_SentPackets.insert (it); @@ -762,7 +762,7 @@ namespace stream bool updated = false; if (expired && m_CurrentRemoteLease) { - for (auto it: leases) + for (const auto& it: leases) if ((it->tunnelGateway == m_CurrentRemoteLease->tunnelGateway) && (it->tunnelID != m_CurrentRemoteLease->tunnelID)) { m_CurrentRemoteLease = it; @@ -798,7 +798,7 @@ namespace stream StreamingDestination::~StreamingDestination () { - for (auto it: m_SavedPackets) + for (auto& it: m_SavedPackets) { for (auto it1: it.second) delete it1; it.second.clear (); @@ -877,7 +877,7 @@ namespace stream else // follow on packet without SYN { uint32_t receiveStreamID = packet->GetReceiveStreamID (); - for (auto it: m_Streams) + for (auto& it: m_Streams) if (it.second->GetSendStreamID () == receiveStreamID) { // found @@ -944,7 +944,7 @@ namespace stream m_Owner->GetService ().post([acceptor, this](void) { m_Acceptor = acceptor; - for (auto it: m_PendingIncomingStreams) + for (auto& it: m_PendingIncomingStreams) if (it->GetStatus () == eStreamStatusOpen) // still open? m_Acceptor (it); m_PendingIncomingStreams.clear (); @@ -963,7 +963,7 @@ namespace stream if (ecode != boost::asio::error::operation_aborted) { LogPrint (eLogWarning, "Streaming: Pending incoming timeout expired"); - for (auto it: m_PendingIncomingStreams) + for (auto& it: m_PendingIncomingStreams) it->Close (); m_PendingIncomingStreams.clear (); } diff --git a/TransportSession.h b/TransportSession.h index 608e72d1..1b057bc7 100644 --- a/TransportSession.h +++ b/TransportSession.h @@ -53,8 +53,8 @@ namespace transport { public: - TransportSession (std::shared_ptr router): - m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router) + TransportSession (std::shared_ptr router, int terminationTimeout): + m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout) { if (router) m_RemoteIdentity = router->GetRouterIdentity (); @@ -70,6 +70,9 @@ namespace transport 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; }; + virtual void SendI2NPMessages (const std::vector >& msgs) = 0; protected: @@ -78,6 +81,7 @@ namespace transport std::shared_ptr m_DHKeysPair; // X - for client and Y - for server size_t m_NumSentBytes, m_NumReceivedBytes; bool m_IsOutgoing; + int m_TerminationTimeout; }; } } diff --git a/Transports.cpp b/Transports.cpp index a54455cc..b1c174f6 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -112,7 +112,7 @@ namespace transport m_Thread = new std::thread (std::bind (&Transports::Run, this)); // create acceptors auto& addresses = context.GetRouterInfo ().GetAddresses (); - for (auto address : addresses) + for (const auto& address : addresses) { if (m_NTCPServer == nullptr && enableNTCP) { @@ -236,7 +236,7 @@ namespace transport if (ident == i2p::context.GetRouterInfo ().GetIdentHash ()) { // we send it to ourself - for (auto it: msgs) + for (auto& it: msgs) i2p::HandleI2NPMessage (it); return; } @@ -266,7 +266,7 @@ namespace transport { if (it->second.delayedMessages.size () < MAX_NUM_DELAYED_MESSAGES) { - for (auto it1: msgs) + for (auto& it1: msgs) it->second.delayedMessages.push_back (it1); } else @@ -569,6 +569,8 @@ namespace transport } if (sendDatabaseStore) session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); + else + session->SetTerminationTimeout (10); // most likely it's publishing, no follow-up messages expected, set timeout to 10 seconds it->second.sessions.push_back (session); session->SendI2NPMessages (it->second.delayedMessages); it->second.delayedMessages.clear (); @@ -634,7 +636,7 @@ namespace transport it = m_Peers.erase (it); } else - it++; + ++it; } UpdateBandwidth (); // TODO: use separate timer(s) for it if (i2p::context.GetStatus () == eRouterStatusTesting) // if still testing, repeat peer test @@ -656,7 +658,7 @@ namespace transport { std::lock_guard lock(m_FamilyMutex); m_TrustedFamilies.clear(); - for ( auto fam : families ) + for ( const auto& fam : families ) m_TrustedFamilies.push_back(fam); } diff --git a/Transports.h b/Transports.h index 708c55e2..81063916 100644 --- a/Transports.h +++ b/Transports.h @@ -60,7 +60,7 @@ namespace transport void Done () { - for (auto it: sessions) + for (auto& it: sessions) it->Done (); } }; diff --git a/Tunnel.cpp b/Tunnel.cpp index fd971628..7d2e6735 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -13,19 +13,19 @@ #include "Tunnel.h" namespace i2p -{ +{ namespace tunnel -{ - +{ + 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) { - } + } Tunnel::~Tunnel () { - } + } void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr outboundTunnel) { @@ -33,7 +33,7 @@ namespace tunnel int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops; auto msg = NewI2NPShortMessage (); *msg->GetPayload () = numRecords; - msg->len += numRecords*TUNNEL_BUILD_RECORD_SIZE + 1; + msg->len += numRecords*TUNNEL_BUILD_RECORD_SIZE + 1; // shuffle records std::vector recordIndicies; @@ -56,13 +56,13 @@ namespace tunnel hop->recordIndex = idx; i++; hop = hop->next; - } - // fill up fake records with random data + } + // fill up fake records with random data for (int i = numHops; i < numRecords; i++) { int idx = recordIndicies[i]; RAND_bytes (records + idx*TUNNEL_BUILD_RECORD_SIZE, TUNNEL_BUILD_RECORD_SIZE); - } + } // decrypt real records i2p::crypto::CBCDecryption decryption; @@ -73,31 +73,31 @@ namespace tunnel // decrypt records after current hop TunnelHopConfig * hop1 = hop->next; while (hop1) - { + { decryption.SetIV (hop->replyIV); uint8_t * record = records + hop1->recordIndex*TUNNEL_BUILD_RECORD_SIZE; decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record); hop1 = hop1->next; - } + } hop = hop->prev; - } + } msg->FillI2NPMessageHeader (eI2NPVariableTunnelBuild); // send message if (outboundTunnel) - outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg); + outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg); else i2p::transport::transports.SendMessage (GetNextIdentHash (), msg); - } - + } + bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len) { LogPrint (eLogDebug, "Tunnel: TunnelBuildResponse ", (int)msg[0], " records."); - + i2p::crypto::CBCDecryption decryption; TunnelHopConfig * hop = m_Config->GetLastHop (); while (hop) - { + { decryption.SetKey (hop->replyKey); // decrypt records before and including current hop TunnelHopConfig * hop1 = hop; @@ -105,22 +105,22 @@ namespace tunnel { auto idx = hop1->recordIndex; if (idx >= 0 && idx < msg[0]) - { + { uint8_t * record = msg + 1 + idx*TUNNEL_BUILD_RECORD_SIZE; decryption.SetIV (hop->replyIV); decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record); - } + } else LogPrint (eLogWarning, "Tunnel: hop index ", idx, " is out of range"); hop1 = hop1->prev; - } + } hop = hop->prev; } bool established = true; hop = m_Config->GetFirstHop (); while (hop) - { + { const uint8_t * record = msg + 1 + hop->recordIndex*TUNNEL_BUILD_RECORD_SIZE; uint8_t ret = record[BUILD_RESPONSE_RECORD_RET_OFFSET]; LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret); @@ -143,12 +143,12 @@ namespace tunnel tunnelHop->decryption.SetKeys (hop->layerKey, hop->ivKey); m_Hops.push_back (std::unique_ptr(tunnelHop)); hop = hop->prev; - } + } m_Config = nullptr; - } + } if (established) m_State = eTunnelStateEstablished; return established; - } + } void Tunnel::EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out) { @@ -158,20 +158,20 @@ namespace tunnel { it->decryption.Decrypt (inPayload, outPayload); inPayload = outPayload; - } - } + } + } void Tunnel::SendTunnelDataMsg (std::shared_ptr msg) { LogPrint (eLogWarning, "Tunnel: Can't send I2NP messages without delivery instructions"); - } + } std::vector > Tunnel::GetPeers () const { auto peers = GetInvertedPeers (); - std::reverse (peers.begin (), peers.end ()); + std::reverse (peers.begin (), peers.end ()); return peers; - } + } std::vector > Tunnel::GetInvertedPeers () const { @@ -179,54 +179,54 @@ namespace tunnel std::vector > ret; for (auto& it: m_Hops) ret.push_back (it->ident); - return ret; - } + return ret; + } void Tunnel::PrintHops (std::stringstream& s) const { for (auto& it: m_Hops) - { - s << " ⇒ "; + { + s << " ⇒ "; s << i2p::data::GetIdentHashAbbreviation (it->ident->GetIdentHash ()); - } - } - + } + } + void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr msg) { - if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive + if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive auto newMsg = CreateEmptyTunnelDataMsg (); EncryptTunnelMsg (msg, newMsg); newMsg->from = shared_from_this (); - m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); - } + m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); + } void InboundTunnel::Print (std::stringstream& s) const { PrintHops (s); - s << " ⇒ " << GetTunnelID () << ":me"; - } + s << " ⇒ " << GetTunnelID () << ":me"; + } ZeroHopsInboundTunnel::ZeroHopsInboundTunnel (): InboundTunnel (std::make_shared ()), m_NumReceivedBytes (0) { - } - + } + void ZeroHopsInboundTunnel::SendTunnelDataMsg (std::shared_ptr msg) { if (msg) - { + { m_NumReceivedBytes += msg->GetLength (); msg->from = shared_from_this (); HandleI2NPMessage (msg); - } - } + } + } void ZeroHopsInboundTunnel::Print (std::stringstream& s) const { - s << " ⇒ " << GetTunnelID () << ":me"; - } - + s << " ⇒ " << GetTunnelID () << ":me"; + } + void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg) { TunnelMessageBlock block; @@ -234,28 +234,28 @@ namespace tunnel { block.hash = gwHash; if (gwTunnel) - { + { block.deliveryType = eDeliveryTypeTunnel; block.tunnelID = gwTunnel; - } + } else block.deliveryType = eDeliveryTypeRouter; - } - else + } + else block.deliveryType = eDeliveryTypeLocal; block.data = msg; - + SendTunnelDataMsg ({block}); } - + void OutboundTunnel::SendTunnelDataMsg (const std::vector& msgs) { std::unique_lock l(m_SendMutex); for (auto& it : msgs) m_Gateway.PutTunnelDataMsg (it); m_Gateway.SendBuffer (); - } - + } + void OutboundTunnel::HandleTunnelDataMsg (std::shared_ptr tunnelMsg) { LogPrint (eLogError, "Tunnel: incoming message for outbound tunnel ", GetTunnelID ()); @@ -265,9 +265,9 @@ namespace tunnel { s << GetTunnelID () << ":me"; PrintHops (s); - s << " ⇒ "; - } - + s << " ⇒ "; + } + ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel (): OutboundTunnel (std::make_shared ()), m_NumSentBytes (0) @@ -286,30 +286,30 @@ namespace tunnel case eDeliveryTypeTunnel: i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data)); break; - case eDeliveryTypeRouter: + case eDeliveryTypeRouter: i2p::transport::transports.SendMessage (msg.hash, msg.data); break; default: LogPrint (eLogError, "Tunnel: Unknown delivery type ", (int)msg.deliveryType); - } + } } } void ZeroHopsOutboundTunnel::Print (std::stringstream& s) const { - s << GetTunnelID () << ":me ⇒ "; + s << GetTunnelID () << ":me ⇒ "; } Tunnels tunnels; - + Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), m_NumSuccesiveTunnelCreations (0), m_NumFailedTunnelCreations (0) { } - - Tunnels::~Tunnels () + + Tunnels::~Tunnels () { - } + } std::shared_ptr Tunnels::GetTunnel (uint32_t tunnelID) { @@ -317,35 +317,35 @@ namespace tunnel if (it != m_Tunnels.end ()) return it->second; return nullptr; - } - + } + std::shared_ptr Tunnels::GetPendingInboundTunnel (uint32_t replyMsgID) { - return GetPendingTunnel (replyMsgID, m_PendingInboundTunnels); + return GetPendingTunnel (replyMsgID, m_PendingInboundTunnels); } std::shared_ptr Tunnels::GetPendingOutboundTunnel (uint32_t replyMsgID) { - return GetPendingTunnel (replyMsgID, m_PendingOutboundTunnels); - } + return GetPendingTunnel (replyMsgID, m_PendingOutboundTunnels); + } - template + template std::shared_ptr Tunnels::GetPendingTunnel (uint32_t replyMsgID, const std::map >& pendingTunnels) { auto it = pendingTunnels.find(replyMsgID); if (it != pendingTunnels.end () && it->second->GetState () == eTunnelStatePending) - { - it->second->SetState (eTunnelStateBuildReplyReceived); + { + it->second->SetState (eTunnelStateBuildReplyReceived); return it->second; } return nullptr; - } + } std::shared_ptr Tunnels::GetNextInboundTunnel () { std::shared_ptr tunnel; size_t minReceived = 0; - for (auto it : m_InboundTunnels) + for (const auto& it : m_InboundTunnels) { if (!it->IsEstablished ()) continue; if (!tunnel || it->GetNumReceivedBytes () < minReceived) @@ -353,26 +353,26 @@ namespace tunnel tunnel = it; minReceived = it->GetNumReceivedBytes (); } - } + } return tunnel; } - + std::shared_ptr Tunnels::GetNextOutboundTunnel () { if (m_OutboundTunnels.empty ()) return nullptr; uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0; std::shared_ptr tunnel; - for (auto it: m_OutboundTunnels) - { + for (const auto& it: m_OutboundTunnels) + { if (it->IsEstablished ()) { tunnel = it; i++; } if (i > ind && tunnel) break; - } + } return tunnel; - } + } std::shared_ptr Tunnels::CreateTunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels) @@ -381,19 +381,19 @@ namespace tunnel std::unique_lock l(m_PoolsMutex); m_Pools.push_back (pool); return pool; - } + } void Tunnels::DeleteTunnelPool (std::shared_ptr pool) { if (pool) - { + { StopTunnelPool (pool); { std::unique_lock l(m_PoolsMutex); m_Pools.remove (pool); - } - } - } + } + } + } void Tunnels::StopTunnelPool (std::shared_ptr pool) { @@ -401,47 +401,47 @@ namespace tunnel { pool->SetActive (false); pool->DetachTunnels (); - } - } - + } + } + void Tunnels::AddTransitTunnel (std::shared_ptr tunnel) { if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second) m_TransitTunnels.push_back (tunnel); else LogPrint (eLogError, "Tunnel: tunnel with id ", tunnel->GetTunnelID (), " already exists"); - } + } void Tunnels::Start () { m_IsRunning = true; m_Thread = new std::thread (std::bind (&Tunnels::Run, this)); } - + void Tunnels::Stop () { m_IsRunning = false; m_Queue.WakeUp (); if (m_Thread) - { + { m_Thread->join (); delete m_Thread; m_Thread = 0; - } - } + } + } void Tunnels::Run () { std::this_thread::sleep_for (std::chrono::seconds(1)); // wait for other parts are ready - + uint64_t lastTs = 0; while (m_IsRunning) { try - { + { auto msg = m_Queue.GetNextWithTimeout (1000); // 1 sec if (msg) - { + { uint32_t prevTunnelID = 0, tunnelID = 0; std::shared_ptr prevTunnel; do @@ -449,16 +449,16 @@ namespace tunnel std::shared_ptr tunnel; uint8_t typeID = msg->GetTypeID (); switch (typeID) - { + { case eI2NPTunnelData: case eI2NPTunnelGateway: - { + { tunnelID = bufbe32toh (msg->GetPayload ()); if (tunnelID == prevTunnelID) tunnel = prevTunnel; else if (prevTunnel) prevTunnel->FlushTunnelDataMsgs (); - + if (!tunnel) tunnel = GetTunnel (tunnelID); if (tunnel) @@ -472,17 +472,17 @@ namespace tunnel LogPrint (eLogWarning, "Tunnel: tunnel not found, tunnelID=", tunnelID, " previousTunnelID=", prevTunnelID, " type=", (int)typeID); break; - } - case eI2NPVariableTunnelBuild: + } + case eI2NPVariableTunnelBuild: case eI2NPVariableTunnelBuildReply: case eI2NPTunnelBuild: - case eI2NPTunnelBuildReply: + case eI2NPTunnelBuildReply: HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ()); - break; + break; default: LogPrint (eLogWarning, "Tunnel: unexpected messsage type ", (int) typeID); } - + msg = m_Queue.Get (); if (msg) { @@ -493,8 +493,8 @@ namespace tunnel tunnel->FlushTunnelDataMsgs (); } while (msg); - } - + } + uint64_t ts = i2p::util::GetSecondsSinceEpoch (); if (ts - lastTs >= 15) // manage tunnels every 15 seconds { @@ -505,9 +505,9 @@ namespace tunnel catch (std::exception& ex) { LogPrint (eLogError, "Tunnel: runtime exception: ", ex.what ()); - } - } - } + } + } + } void Tunnels::HandleTunnelGatewayMsg (std::shared_ptr tunnel, std::shared_ptr msg) { @@ -528,7 +528,7 @@ namespace tunnel msg->len = msg->offset + len; auto typeID = msg->GetTypeID (); 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 // or DatabaseSearchReply with new routers @@ -543,7 +543,7 @@ namespace tunnel ManageOutboundTunnels (); ManageTransitTunnels (); ManageTunnelPools (); - } + } void Tunnels::ManagePendingTunnels () { @@ -557,7 +557,7 @@ namespace tunnel // check pending tunnel. delete failed or timeout uint64_t ts = i2p::util::GetSecondsSinceEpoch (); for (auto it = pendingTunnels.begin (); it != pendingTunnels.end ();) - { + { auto tunnel = it->second; switch (tunnel->GetState ()) { @@ -579,14 +579,14 @@ namespace tunnel profile->TunnelNonReplied (); } hop = hop->next; - } - } + } + } // delete it = pendingTunnels.erase (it); m_NumFailedTunnelCreations++; } else - it++; + ++it; break; case eTunnelStateBuildFailed: LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " failed, deleted"); @@ -595,14 +595,14 @@ namespace tunnel break; case eTunnelStateBuildReplyReceived: // intermediate state, will be either established of build failed - it++; - break; + ++it; + break; default: // success it = pendingTunnels.erase (it); m_NumSuccesiveTunnelCreations++; - } - } + } + } } void Tunnels::ManageOutboundTunnels () @@ -620,26 +620,26 @@ namespace tunnel pool->TunnelExpired (tunnel); // we don't have outbound tunnels in m_Tunnels it = m_OutboundTunnels.erase (it); - } + } else { if (tunnel->IsEstablished ()) - { + { if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { - tunnel->SetIsRecreated (); + tunnel->SetIsRecreated (); auto pool = tunnel->GetTunnelPool (); if (pool) pool->RecreateOutboundTunnel (tunnel); } if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) tunnel->SetState (eTunnelStateExpiring); - } - it++; + } + ++it; } } - } - + } + if (m_OutboundTunnels.size () < 5) { // trying to create one more oubound tunnel @@ -648,12 +648,12 @@ namespace tunnel if (!inboundTunnel || !router) return; LogPrint (eLogDebug, "Tunnel: creating one hop outbound tunnel"); CreateTunnel ( - std::make_shared (std::vector > { router->GetRouterIdentity () }, - inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()) - ); + std::make_shared (std::vector > { router->GetRouterIdentity () }, + inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()) + ); } } - + void Tunnels::ManageInboundTunnels () { uint64_t ts = i2p::util::GetSecondsSinceEpoch (); @@ -669,26 +669,26 @@ namespace tunnel pool->TunnelExpired (tunnel); m_Tunnels.erase (tunnel->GetTunnelID ()); it = m_InboundTunnels.erase (it); - } + } else { if (tunnel->IsEstablished ()) - { + { if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { - tunnel->SetIsRecreated (); + tunnel->SetIsRecreated (); auto pool = tunnel->GetTunnelPool (); if (pool) pool->RecreateInboundTunnel (tunnel); } - + if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) tunnel->SetState (eTunnelStateExpiring); - } + } it++; } } - } + } if (m_InboundTunnels.empty ()) { @@ -702,10 +702,10 @@ namespace tunnel } return; } - + if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 5) { - // trying to create one more inbound tunnel + // trying to create one more inbound tunnel auto router = i2p::data::netdb.GetRandomRouter (); if (!router) { LogPrint (eLogWarning, "Tunnel: can't find any router, skip creating tunnel"); @@ -714,9 +714,9 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: creating one hop inbound tunnel"); CreateTunnel ( std::make_shared (std::vector > { router->GetRouterIdentity () }) - ); + ); } - } + } void Tunnels::ManageTransitTunnels () { @@ -729,36 +729,35 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: Transit tunnel with id ", tunnel->GetTunnelID (), " expired"); m_Tunnels.erase (tunnel->GetTunnelID ()); it = m_TransitTunnels.erase (it); - } + } else it++; } - } + } void Tunnels::ManageTunnelPools () { std::unique_lock l(m_PoolsMutex); - for (auto it: m_Pools) - { - auto pool = it; + for (auto& pool : m_Pools) + { if (pool && pool->IsActive ()) - { + { pool->CreateTunnels (); pool->TestTunnels (); - } + } } - } - + } + void Tunnels::PostTunnelData (std::shared_ptr msg) { - if (msg) m_Queue.Put (msg); - } + if (msg) m_Queue.Put (msg); + } void Tunnels::PostTunnelData (const std::vector >& msgs) { m_Queue.Put (msgs); - } - + } + template std::shared_ptr Tunnels::CreateTunnel (std::shared_ptr config, std::shared_ptr outboundTunnel) { @@ -768,7 +767,7 @@ namespace tunnel AddPendingTunnel (replyMsgID, newTunnel); newTunnel->Build (replyMsgID, outboundTunnel); return newTunnel; - } + } std::shared_ptr Tunnels::CreateInboundTunnel (std::shared_ptr config, std::shared_ptr outboundTunnel) { @@ -805,20 +804,20 @@ namespace tunnel pool->TunnelCreated (newTunnel); else newTunnel->SetTunnelPool (nullptr); - } + } void Tunnels::AddInboundTunnel (std::shared_ptr newTunnel) { if (m_Tunnels.emplace (newTunnel->GetTunnelID (), newTunnel).second) - { + { m_InboundTunnels.push_back (newTunnel); auto pool = newTunnel->GetTunnelPool (); if (!pool) - { + { // build symmetric outbound tunnel CreateTunnel (std::make_shared(newTunnel->GetInvertedPeers (), newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash ()), - GetNextOutboundTunnel ()); + GetNextOutboundTunnel ()); } else { @@ -830,9 +829,9 @@ namespace tunnel } else LogPrint (eLogError, "Tunnel: tunnel with id ", newTunnel->GetTunnelID (), " already exists"); - } + } + - std::shared_ptr Tunnels::CreateZeroHopsInboundTunnel () { auto inboundTunnel = std::make_shared (); @@ -840,7 +839,7 @@ namespace tunnel m_InboundTunnels.push_back (inboundTunnel); m_Tunnels[inboundTunnel->GetTunnelID ()] = inboundTunnel; return inboundTunnel; - } + } std::shared_ptr Tunnels::CreateZeroHopsOutboundTunnel () { @@ -856,11 +855,11 @@ namespace tunnel int timeout = 0; uint32_t ts = i2p::util::GetSecondsSinceEpoch (); // TODO: possible race condition with I2PControl - for (auto it: m_TransitTunnels) + for (const auto& it : m_TransitTunnels) { int t = it->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT - ts; if (t > timeout) timeout = t; - } + } return timeout; } @@ -883,4 +882,3 @@ namespace tunnel } } } - diff --git a/Tunnel.h b/Tunnel.h index 0d35b682..5bc8b195 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -224,7 +224,7 @@ namespace tunnel std::list> m_Pools; std::shared_ptr m_ExploratoryPool; i2p::util::Queue > m_Queue; - + // some stats int m_NumSuccesiveTunnelCreations, m_NumFailedTunnelCreations; diff --git a/TunnelConfig.h b/TunnelConfig.h index 7546c9b2..23417ed9 100644 --- a/TunnelConfig.h +++ b/TunnelConfig.h @@ -213,7 +213,7 @@ namespace tunnel void CreatePeers (const Peers& peers) { TunnelHopConfig * prev = nullptr; - for (auto it: peers) + for (const auto& it: peers) { auto hop = new TunnelHopConfig (it); if (prev) diff --git a/TunnelGateway.cpp b/TunnelGateway.cpp index d701e24b..ad423fc0 100644 --- a/TunnelGateway.cpp +++ b/TunnelGateway.cpp @@ -197,7 +197,7 @@ namespace tunnel { m_Buffer.CompleteCurrentTunnelDataMessage (); auto tunnelMsgs = m_Buffer.GetTunnelDataMsgs (); - for (auto tunnelMsg : tunnelMsgs) + for (auto& tunnelMsg : tunnelMsgs) { m_Tunnel->EncryptTunnelMsg (tunnelMsg, tunnelMsg); tunnelMsg->FillI2NPMessageHeader (eI2NPTunnelData); diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 4bd116cb..119556aa 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -49,13 +49,13 @@ namespace tunnel { { std::unique_lock l(m_InboundTunnelsMutex); - for (auto it: m_InboundTunnels) + for (auto& it: m_InboundTunnels) it->SetTunnelPool (nullptr); m_InboundTunnels.clear (); } { std::unique_lock l(m_OutboundTunnelsMutex); - for (auto it: m_OutboundTunnels) + for (auto& it: m_OutboundTunnels) it->SetTunnelPool (nullptr); m_OutboundTunnels.clear (); } @@ -78,7 +78,7 @@ namespace tunnel if (expiredTunnel) { expiredTunnel->SetTunnelPool (nullptr); - for (auto it: m_Tests) + for (auto& it: m_Tests) if (it.second.second == expiredTunnel) it.second.second = nullptr; std::unique_lock l(m_InboundTunnelsMutex); @@ -101,7 +101,7 @@ namespace tunnel if (expiredTunnel) { expiredTunnel->SetTunnelPool (nullptr); - for (auto it: m_Tests) + for (auto& it: m_Tests) if (it.second.first == expiredTunnel) it.second.first = nullptr; std::unique_lock l(m_OutboundTunnelsMutex); @@ -114,7 +114,7 @@ namespace tunnel std::vector > v; int i = 0; std::unique_lock l(m_InboundTunnelsMutex); - for (auto it : m_InboundTunnels) + for (const auto& it : m_InboundTunnels) { if (i >= num) break; if (it->IsEstablished ()) @@ -144,7 +144,7 @@ namespace tunnel if (tunnels.empty ()) return nullptr; uint32_t ind = rand () % (tunnels.size ()/2 + 1), i = 0; typename TTunnels::value_type tunnel = nullptr; - for (auto it: tunnels) + for (const auto& it: tunnels) { if (it->IsEstablished () && it != excluded) { @@ -164,7 +164,7 @@ namespace tunnel if (old) { std::unique_lock l(m_OutboundTunnelsMutex); - for (auto it: m_OutboundTunnels) + for (const auto& it: m_OutboundTunnels) if (it->IsEstablished () && old->GetEndpointIdentHash () == it->GetEndpointIdentHash ()) { tunnel = it; @@ -182,7 +182,7 @@ namespace tunnel int num = 0; { std::unique_lock l(m_InboundTunnelsMutex); - for (auto it : m_InboundTunnels) + for (const auto& it : m_InboundTunnels) if (it->IsEstablished ()) num++; } for (int i = num; i < m_NumInboundTunnels; i++) @@ -191,7 +191,7 @@ namespace tunnel num = 0; { std::unique_lock l(m_OutboundTunnelsMutex); - for (auto it : m_OutboundTunnels) + for (const auto& it : m_OutboundTunnels) if (it->IsEstablished ()) num++; } for (int i = num; i < m_NumOutboundTunnels; i++) @@ -203,11 +203,10 @@ namespace tunnel decltype(m_Tests) tests; { std::unique_lock l(m_TestsMutex); - tests = m_Tests; - m_Tests.clear (); + tests.swap(m_Tests); } - for (auto it: tests) + for (auto& it: tests) { LogPrint (eLogWarning, "Tunnels: test of tunnel ", it.first, " failed"); // if test failed again with another tunnel we consider it failed @@ -248,12 +247,12 @@ namespace tunnel if ((*it1)->IsFailed ()) { failed = true; - it1++; + ++it1; } if ((*it2)->IsFailed ()) { failed = true; - it2++; + ++it2; } if (!failed) { @@ -265,7 +264,7 @@ namespace tunnel } (*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), CreateDeliveryStatusMsg (msgID)); - it1++; it2++; + ++it1; ++it2; } } } diff --git a/UPnP.cpp b/UPnP.cpp index 41b49e00..612b1441 100644 --- a/UPnP.cpp +++ b/UPnP.cpp @@ -49,7 +49,9 @@ namespace transport m_IsRunning = true; LogPrint(eLogInfo, "UPnP: starting"); m_Service.post (std::bind (&UPnP::Discover, this)); + std::unique_lock l(m_StartedMutex); m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this))); + m_Started.wait_for (l, std::chrono::seconds (5)); // 5 seconds maximum } UPnP::~UPnP () @@ -80,7 +82,12 @@ namespace transport #else m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror); #endif - + { + // notify satrting thread + std::unique_lock l(m_StartedMutex); + m_Started.notify_all (); + } + int r; r = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr)); if (r == 1) @@ -115,8 +122,8 @@ namespace transport void UPnP::PortMapping () { - auto a = context.GetRouterInfo().GetAddresses(); - for (auto address : a) + const auto& a = context.GetRouterInfo().GetAddresses(); + for (const auto& address : a) { if (!address->host.is_v6 ()) TryPortMapping (address); @@ -132,8 +139,8 @@ namespace transport void UPnP::CloseMapping () { - auto a = context.GetRouterInfo().GetAddresses(); - for (auto address : a) + const auto& a = context.GetRouterInfo().GetAddresses(); + for (const auto& address : a) { if (!address->host.is_v6 ()) CloseMapping (address); diff --git a/UPnP.h b/UPnP.h index 4013b3df..7d67fdbf 100644 --- a/UPnP.h +++ b/UPnP.h @@ -4,6 +4,8 @@ #ifdef USE_UPNP #include #include +#include +#include #include #include @@ -13,8 +15,6 @@ #include -#include "util.h" - namespace i2p { namespace transport @@ -45,8 +45,10 @@ namespace transport bool m_IsRunning; std::unique_ptr m_Thread; + 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/Win32/Win32App.cpp b/Win32/Win32App.cpp index 01432381..7da8f882 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -2,6 +2,7 @@ #include #include #include "../Config.h" +#include "../RouterContext.h" #include "../version.h" #include "resource.h" #include "Win32App.h" @@ -15,10 +16,13 @@ #define ID_EXIT 2001 #define ID_CONSOLE 2002 #define ID_APP 2003 +#define ID_GRACEFUL_SHUTDOWN 2004 #define ID_TRAY_ICON 2050 #define WM_TRAYICON (WM_USER + 1) +#define IDT_GRACEFUL_SHUTDOWN_TIMER 2100 + namespace i2p { namespace win32 @@ -30,6 +34,7 @@ namespace win32 InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app"); InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About..."); InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, NULL, NULL); + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown"); InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit"); SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE); SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0); @@ -82,6 +87,7 @@ namespace win32 case WM_CLOSE: { RemoveTrayIcon (hWnd); + KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER); PostQuitMessage (0); break; } @@ -101,6 +107,12 @@ namespace win32 PostMessage (hWnd, WM_CLOSE, 0, 0); return 0; } + case ID_GRACEFUL_SHUTDOWN: + { + i2p::context.SetAcceptsTunnels (false); + SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes + return 0; + } case ID_CONSOLE: { char buf[30]; @@ -167,6 +179,15 @@ namespace win32 } break; } + case WM_TIMER: + { + if (wParam == IDT_GRACEFUL_SHUTDOWN_TIMER) + { + PostMessage (hWnd, WM_CLOSE, 0, 0); // exit + return 0; + } + break; + } } return DefWindowProc( hWnd, uMsg, wParam, lParam); } @@ -218,5 +239,13 @@ namespace win32 { UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL)); } + + bool GracefulShutdown () + { + HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); + if (hWnd) + PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0); + return hWnd; + } } } diff --git a/Win32/Win32App.h b/Win32/Win32App.h index 7d35ec1e..3babffa9 100644 --- a/Win32/Win32App.h +++ b/Win32/Win32App.h @@ -10,6 +10,7 @@ namespace win32 bool StartWin32App (); void StopWin32App (); int RunWin32App (); + bool GracefulShutdown (); } } #endif // WIN32APP_H__ diff --git a/debian/patches/01-tune-build-opts.patch b/debian/patches/01-tune-build-opts.patch index e0e24408..2a09b07b 100644 --- a/debian/patches/01-tune-build-opts.patch +++ b/debian/patches/01-tune-build-opts.patch @@ -1,14 +1,15 @@ diff --git a/Makefile b/Makefile -index fe8ae7e..fc8abda 100644 +index 7d04ba0..33ee184 100644 --- a/Makefile +++ b/Makefile -@@ -9,9 +9,9 @@ DEPS := obj/make.dep +@@ -9,10 +9,10 @@ DEPS := obj/make.dep include filelist.mk -USE_AESNI := yes +USE_AESNI := no USE_STATIC := no + USE_MESHNET := no -USE_UPNP := no +USE_UPNP := yes diff --git a/docs/build_notes_android.md b/docs/build_notes_android.md index 71f0b2bc..93b8b77e 100644 --- a/docs/build_notes_android.md +++ b/docs/build_notes_android.md @@ -1,6 +1,8 @@ Building on Android =================== +There are two versions: with QT and without QT. + Pre-requesties -------------- @@ -8,12 +10,12 @@ You need to install Android SDK, NDK and QT with android support. - [SDK](https://developer.android.com/studio/index.html) (choose command line tools only) - [NDK](https://developer.android.com/ndk/downloads/index.html) -- [QT](https://www.qt.io/download-open-source/). Choose one for your platform for android. For example QT 5.6 under Linux would be [this file](http://download.qt.io/official_releases/qt/5.6/5.6.1-1/qt-opensource-linux-x64-android-5.6.1-1.run ) +- [QT](https://www.qt.io/download-open-source/)(for QT only). Choose one for your platform for android. For example QT 5.6 under Linux would be [this file](http://download.qt.io/official_releases/qt/5.6/5.6.1-1/qt-opensource-linux-x64-android-5.6.1-1.run ) You also need Java JDK and Ant. -QT-Creator ----------- +QT-Creator (for QT only) +------------------------ Open QT-creator that should be installed with QT. Go to Settings/Anndroid and specify correct paths to SDK and NDK. If everything is correct you will see two set avaiable: @@ -30,11 +32,26 @@ git clone https://github.com/PurpleI2P/android-ifaddrs.git ``` -Building the app ----------------- -- Open qt/i2pd_qt/i2pd_qt.pro in the QT-creator. -- Change line MAIN_PATH = /path/to/libraries to actual path where did you put the dependancies to. -- Select appropriate project (usually armeabi-v7a) and build. -- You will find an .apk file in android-build/bin folder. - - +Building the app with QT +------------------------ +- Open qt/i2pd_qt/i2pd_qt.pro in the QT-creator +- Change line MAIN_PATH = /path/to/libraries to an actual path where you put the dependancies to +- Select appropriate project (usually armeabi-v7a) and build +- You will find an .apk file in android-build/bin folder + +Building the app without QT +--------------------------- +- Change line I2PD_LIBS_PATH in android/jni/Application.mk to an actual path where you put the dependancies to +- Run 'ndk-build -j4' from andorid folder +- Create or edit file 'local.properties'. Place 'sdk.dir=' and 'ndk.dir=' +- Run 'ant clean debug' + +Creating release .apk +---------------------- +In order to create release .apk you must obtain a Java keystore file(.jks). Either you have in already, or you can generate it yourself using keytool, or from one of you existing well-know ceritificates. For example, i2pd release are signed with this [certificate](https://github.com/PurpleI2P/i2pd/blob/openssl/contrib/certificates/router/orignal_at_mail.i2p.crt). +Create file 'ant.propeties' +key.store='path to keystore file' +key.alias='alias name' +key.store.password='keystore password' +key.alias.password='alias password' +Run 'ant clean release' diff --git a/docs/build_notes_unix.md b/docs/build_notes_unix.md index 795e408a..228333c8 100644 --- a/docs/build_notes_unix.md +++ b/docs/build_notes_unix.md @@ -23,7 +23,7 @@ After successfull build i2pd could be installed with: ```bash make install ``` -or you can just use 'make' once you have all dependacies (boost and openssl) installed +or you can just use 'make' once you have all dependencies (boost and openssl) installed ```bash git clone https://github.com/PurpleI2P/i2pd.git diff --git a/docs/build_notes_windows.md b/docs/build_notes_windows.md index 8ba36131..827d0123 100644 --- a/docs/build_notes_windows.md +++ b/docs/build_notes_windows.md @@ -161,15 +161,17 @@ support for this. Unpack client source code in a sibling folder, e.g. C:\dev\miniupnpc . You may want to remove version number from folder name included in downloaded archive. -Note that you might need to build DLL yourself for 64-bit systems -using msys2 as 64-bit DLLs are not provided by the project. - You can also install it through the MSYS2 and build with USE_UPNP key. ```bash pacman -S mingw-w64-i686-miniupnpc -make USE_UPNP=1 +make USE_UPNP=yes +``` +or +```bash +pacman -S mingw-x86_64-miniupnpc +make USE_UPNP=yes ``` ### Creating Visual Studio project diff --git a/docs/configuration.md b/docs/configuration.md index e6ac74d2..32cd7f49 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -70,7 +70,9 @@ All options below still possible in cmdline, but better write it in config file: * --upnp.enabled= - Enable or disable UPnP, false by default for CLI and true for GUI (Windows, Android) * --upnp.name= - Name i2pd appears in UPnP forwardings list. I2Pd by default + * --precomputation.elgamal= - Use ElGamal precomputated tables. false for x64 and true for other platforms by default +* --reseed.file - Full path to SU3 file to reseed from * --limits.transittunnels= - Override maximum number of transit tunnels. 2500 by default @@ -109,7 +111,7 @@ tunnels.conf: # * keys -- our identity, if unset, will be generated on every startup, # if set and file missing, keys will be generated and placed to this file # * address -- local interface to bind - # * signaturetype -- signature type for new destination. 0,1 or 7 + # * signaturetype -- signature type for new destination. 0 (DSA/SHA1), 1 (EcDSA/SHA256) or 7 (EdDSA/SHA512) [IRC] type = client address = 127.0.0.1 diff --git a/filelist.mk b/filelist.mk index d8d74252..f2f4937e 100644 --- a/filelist.mk +++ b/filelist.mk @@ -5,7 +5,7 @@ LIB_SRC = \ SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \ Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \ Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.cpp \ - util.cpp api.cpp + Config.cpp util.cpp api.cpp LIB_CLIENT_SRC = \ AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \ @@ -13,5 +13,5 @@ LIB_CLIENT_SRC = \ # also: Daemon{Linux,Win32}.cpp will be added later DAEMON_SRC = \ - HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp Config.cpp i2pd.cpp + HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp diff --git a/util.cpp b/util.cpp index 08ee6672..ca2b61c2 100644 --- a/util.cpp +++ b/util.cpp @@ -1,12 +1,7 @@ #include #include -#include -#include -#include -#include -#include #include -#include + #include "util.h" #include "Log.h" @@ -60,158 +55,6 @@ namespace i2p { namespace util { -namespace http -{ - std::string GetHttpContent (std::istream& response) - { - std::string version, statusMessage; - response >> version; // HTTP version - int status; - response >> status; // status - std::getline (response, statusMessage); - if (status == 200) // OK - { - bool isChunked = false; - std::string header; - while (!response.eof () && header != "\r") - { - std::getline(response, header); - auto colon = header.find (':'); - if (colon != std::string::npos) - { - std::string field = header.substr (0, colon); - std::transform(field.begin(), field.end(), field.begin(), ::tolower); - if (field == i2p::util::http::TRANSFER_ENCODING) - isChunked = (header.find ("chunked", colon + 1) != std::string::npos); - } - } - - std::stringstream ss; - if (isChunked) - MergeChunkedResponse (response, ss); - else - ss << response.rdbuf(); - return ss.str(); - } - else - { - LogPrint (eLogError, "HTTPClient: error, server responds ", status); - return ""; - } - } - - void MergeChunkedResponse (std::istream& response, std::ostream& merged) - { - while (!response.eof ()) - { - std::string hexLen; - size_t len; - std::getline (response, hexLen); - std::istringstream iss (hexLen); - iss >> std::hex >> len; - if (!len || len > 10000000L) // 10M - { - LogPrint (eLogError, "Unexpected chunk length ", len); - break; - } - char * buf = new char[len]; - response.read (buf, len); - merged.write (buf, len); - delete[] buf; - std::getline (response, hexLen); // read \r\n after chunk - } - } - - url::url(const std::string& url_s) - { - portstr_ = "80"; - port_ = 80; - user_ = ""; - pass_ = ""; - - parse(url_s); - } - - - // code for parser tests - //{ - // i2p::util::http::url u_0("http://127.0.0.1:7070/asdasd?qqqqqqqqqqqq"); - // i2p::util::http::url u_1("http://user:password@site.com:8080/asdasd?qqqqqqqqqqqqq"); - // i2p::util::http::url u_2("http://user:password@site.com/asdasd?qqqqqqqqqqqqqq"); - // i2p::util::http::url u_3("http://user:@site.com/asdasd?qqqqqqqqqqqqq"); - // i2p::util::http::url u_4("http://user@site.com/asdasd?qqqqqqqqqqqq"); - // i2p::util::http::url u_5("http://@site.com:800/asdasd?qqqqqqqqqqqq"); - // i2p::util::http::url u_6("http://@site.com:err_port/asdasd?qqqqqqqqqqqq"); - // i2p::util::http::url u_7("http://user:password@site.com:err_port/asdasd?qqqqqqqqqqqq"); - //} - void url::parse(const std::string& url_s) - { - const std::string prot_end("://"); - std::string::const_iterator prot_i = search(url_s.begin(), url_s.end(), - prot_end.begin(), prot_end.end()); - protocol_.reserve(distance(url_s.begin(), prot_i)); - transform(url_s.begin(), prot_i, - back_inserter(protocol_), - std::ptr_fun(tolower)); // protocol is icase - if( prot_i == url_s.end() ) - return; - advance(prot_i, prot_end.length()); - std::string::const_iterator path_i = find(prot_i, url_s.end(), '/'); - host_.reserve(distance(prot_i, path_i)); - transform(prot_i, path_i, - back_inserter(host_), - std::ptr_fun(tolower)); // host is icase - - // parse user/password - auto user_pass_i = find(host_.begin(), host_.end(), '@'); - if (user_pass_i != host_.end()) - { - std::string user_pass = std::string(host_.begin(), user_pass_i); - auto pass_i = find(user_pass.begin(), user_pass.end(), ':'); - if (pass_i != user_pass.end()) - { - user_ = std::string(user_pass.begin(), pass_i); - pass_ = std::string(pass_i + 1, user_pass.end()); - } - else - user_ = user_pass; - - host_.assign(user_pass_i + 1, host_.end()); - } - - // parse port - auto port_i = find(host_.begin(), host_.end(), ':'); - if (port_i != host_.end()) - { - portstr_ = std::string(port_i + 1, host_.end()); - host_.assign(host_.begin(), port_i); - try{ - port_ = boost::lexical_cast(portstr_); - } - catch (std::exception e) { - port_ = 80; - } - } - - std::string::const_iterator query_i = find(path_i, url_s.end(), '?'); - path_.assign(path_i, query_i); - if( query_i != url_s.end() ) - ++query_i; - query_.assign(query_i, url_s.end()); - } - - std::string urlDecode(const std::string& data) - { - std::string res(data); - for (size_t pos = res.find('%'); pos != std::string::npos; pos = res.find('%',pos+1)) - { - char c = strtol(res.substr(pos+1,2).c_str(), NULL, 16); - res.replace(pos,3,1,c); - } - return res; - } -} - namespace net { #ifdef WIN32 diff --git a/util.h b/util.h index 642ecc9b..77b94995 100644 --- a/util.h +++ b/util.h @@ -22,7 +22,6 @@ namespace i2p { namespace util { - /** wrapper arround boost::lexical_cast that "never" fails */ @@ -34,34 +33,6 @@ namespace util return fallback; } } - - namespace http - { - // in (lower case) - const char ETAG[] = "etag"; // ETag - const char LAST_MODIFIED[] = "last-modified"; // Last-Modified - const char TRANSFER_ENCODING[] = "transfer-encoding"; // Transfer-Encoding - const char CONTENT_ENCODING[] = "content-encoding"; // Content-Encoding - // out - const char IF_NONE_MATCH[] = "If-None-Match"; - const char IF_MODIFIED_SINCE[] = "If-Modified-Since"; - - std::string GetHttpContent (std::istream& response); - void MergeChunkedResponse (std::istream& response, std::ostream& merged); - std::string urlDecode(const std::string& data); - - struct url { - url(const std::string& url_s); // omitted copy, ==, accessors, ... - private: - void parse(const std::string& url_s); - public: - std::string protocol_, host_, path_, query_; - std::string portstr_; - unsigned int port_; - std::string user_; - std::string pass_; - }; - } namespace net { diff --git a/version.h b/version.h index 54fc295f..00064c00 100644 --- a/version.h +++ b/version.h @@ -7,7 +7,7 @@ #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 8 +#define I2PD_VERSION_MINOR 9 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)

Streams
StreamIDDestinationStatus
" << it->GetSendStreamID () << "" << i2p::client::context.GetAddressBook ().ToAddress(it->GetRemoteIdentity ()) << "" << (int)it->GetStatus () << "