Browse Source

Merge pull request #604 from PurpleI2P/openssl

recent changes
pull/613/head
orignal 8 years ago committed by GitHub
parent
commit
c09212de81
  1. 1
      .travis.yml
  2. 22
      AddressBook.cpp
  3. 4
      AddressBook.h
  4. 8
      BOB.cpp
  5. 2
      ClientContext.cpp
  6. 6
      Config.cpp
  7. 17
      Destination.cpp
  8. 2
      Destination.h
  9. 12
      Garlic.cpp
  10. 2
      HTTP.cpp
  11. 6
      HTTPProxy.cpp
  12. 72
      HTTPServer.cpp
  13. 2
      I2CP.cpp
  14. 2
      I2NPProtocol.cpp
  15. 6
      I2PControl.cpp
  16. 8
      LeaseSet.cpp
  17. 2
      Makefile.mingw
  18. 13
      NTCPSession.cpp
  19. 35
      NetDb.cpp
  20. 2
      NetDbRequests.cpp
  21. 2
      Profiling.cpp
  22. 5
      Queue.h
  23. 8
      Reseed.cpp
  24. 20
      RouterContext.cpp
  25. 1
      RouterContext.h
  26. 45
      RouterInfo.cpp
  27. 6
      RouterInfo.h
  28. 4
      SAM.cpp
  29. 2
      SAM.h
  30. 2
      SOCKS.cpp
  31. 22
      SSU.cpp
  32. 36
      SSUData.cpp
  33. 10
      SSUData.h
  34. 9
      SSUSession.cpp
  35. 14
      Streaming.cpp
  36. 8
      TransportSession.h
  37. 12
      Transports.cpp
  38. 2
      Transports.h
  39. 26
      Tunnel.cpp
  40. 2
      TunnelConfig.h
  41. 2
      TunnelGateway.cpp
  42. 29
      TunnelPool.cpp
  43. 15
      UPnP.cpp
  44. 6
      UPnP.h
  45. 29
      Win32/Win32App.cpp
  46. 1
      Win32/Win32App.h
  47. 5
      debian/patches/01-tune-build-opts.patch
  48. 39
      docs/build_notes_android.md
  49. 2
      docs/build_notes_unix.md
  50. 10
      docs/build_notes_windows.md
  51. 4
      docs/configuration.md
  52. 4
      filelist.mk
  53. 159
      util.cpp
  54. 29
      util.h
  55. 2
      version.h

1
.travis.yml

@ -3,7 +3,6 @@ cache:
apt: true apt: true
os: os:
- linux - linux
- osx
sudo: required sudo: required
dist: trusty dist: trusty
addons: addons:

22
AddressBook.cpp

@ -173,7 +173,7 @@ namespace client
return 0; return 0;
} }
for (auto it: addresses) { for (const auto& it: addresses) {
f << it.first << "," << it.second.ToBase32 () << std::endl; f << it.first << "," << it.second.ToBase32 () << std::endl;
num++; num++;
} }
@ -260,8 +260,6 @@ namespace client
m_Storage = nullptr; m_Storage = nullptr;
} }
m_DefaultSubscription = nullptr; m_DefaultSubscription = nullptr;
for (auto it: m_Subscriptions)
delete it;
m_Subscriptions.clear (); m_Subscriptions.clear ();
} }
@ -403,7 +401,7 @@ namespace client
{ {
getline(f, s); getline(f, s);
if (!s.length()) continue; // skip empty line if (!s.length()) continue; // skip empty line
m_Subscriptions.push_back (new AddressBookSubscription (*this, s)); m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, s));
} }
LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded"); LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
} }
@ -418,7 +416,7 @@ namespace client
{ {
std::map<std::string, i2p::data::IdentHash> localAddresses; std::map<std::string, i2p::data::IdentHash> localAddresses;
m_Storage->LoadLocal (localAddresses); m_Storage->LoadLocal (localAddresses);
for (auto it: localAddresses) for (const auto& it: localAddresses)
{ {
auto dot = it.first.find ('.'); auto dot = it.first.find ('.');
if (dot != std::string::npos) if (dot != std::string::npos)
@ -462,7 +460,7 @@ namespace client
int nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT; int nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT;
if (success) if (success)
{ {
if (m_DefaultSubscription) m_DefaultSubscription.reset (nullptr); if (m_DefaultSubscription) m_DefaultSubscription = nullptr;
if (m_IsLoaded) if (m_IsLoaded)
nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT; nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT;
else else
@ -516,16 +514,17 @@ namespace client
// download it from http://i2p-projekt.i2p/hosts.txt // download it from http://i2p-projekt.i2p/hosts.txt
LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription."); LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription.");
if (!m_DefaultSubscription) if (!m_DefaultSubscription)
m_DefaultSubscription.reset (new AddressBookSubscription (*this, DEFAULT_SUBSCRIPTION_ADDRESS)); m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, DEFAULT_SUBSCRIPTION_ADDRESS);
m_IsDownloading = true; 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 ()) else if (!m_Subscriptions.empty ())
{ {
// pick random subscription // pick random subscription
auto ind = rand () % m_Subscriptions.size(); auto ind = rand () % m_Subscriptions.size();
m_IsDownloading = true; 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 load_hosts.detach(); // TODO: use join
} }
} }
@ -659,15 +658,16 @@ namespace client
{ {
std::unique_lock<std::mutex> l(newDataReceivedMutex); std::unique_lock<std::mutex> l(newDataReceivedMutex);
i2p::client::context.GetSharedLocalDestination ()->RequestDestination (m_Ident, i2p::client::context.GetSharedLocalDestination ()->RequestDestination (m_Ident,
[&newDataReceived, &leaseSet](std::shared_ptr<i2p::data::LeaseSet> ls) [&newDataReceived, &leaseSet, &newDataReceivedMutex](std::shared_ptr<i2p::data::LeaseSet> ls)
{ {
leaseSet = ls; leaseSet = ls;
std::unique_lock<std::mutex> l1(newDataReceivedMutex);
newDataReceived.notify_all (); newDataReceived.notify_all ();
}); });
if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout) if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout)
{ {
LogPrint (eLogError, "Addressbook: Subscription LeaseSet request timeout expired"); 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; return false;
} }
} }

4
AddressBook.h

@ -102,8 +102,8 @@ namespace client
std::map<uint32_t, std::string> m_Lookups; // nonce -> address std::map<uint32_t, std::string> m_Lookups; // nonce -> address
AddressBookStorage * m_Storage; AddressBookStorage * m_Storage;
volatile bool m_IsLoaded, m_IsDownloading; volatile bool m_IsLoaded, m_IsDownloading;
std::vector<AddressBookSubscription *> m_Subscriptions; std::vector<std::shared_ptr<AddressBookSubscription> > m_Subscriptions;
std::unique_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet std::shared_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet
boost::asio::deadline_timer * m_SubscriptionsUpdateTimer; boost::asio::deadline_timer * m_SubscriptionsUpdateTimer;
}; };

8
BOB.cpp

@ -536,8 +536,8 @@ namespace client
void BOBCommandSession::ListCommandHandler (const char * operand, size_t len) void BOBCommandSession::ListCommandHandler (const char * operand, size_t len)
{ {
LogPrint (eLogDebug, "BOB: list"); LogPrint (eLogDebug, "BOB: list");
auto& destinations = m_Owner.GetDestinations (); const auto& destinations = m_Owner.GetDestinations ();
for (auto it: destinations) for (const auto& it: destinations)
SendData (it.first.c_str ()); SendData (it.first.c_str ());
SendReplyOK ("Listing done"); SendReplyOK ("Listing done");
} }
@ -619,7 +619,7 @@ namespace client
BOBCommandChannel::~BOBCommandChannel () BOBCommandChannel::~BOBCommandChannel ()
{ {
Stop (); Stop ();
for (auto it: m_Destinations) for (const auto& it: m_Destinations)
delete it.second; delete it.second;
} }
@ -633,7 +633,7 @@ namespace client
void BOBCommandChannel::Stop () void BOBCommandChannel::Stop ()
{ {
m_IsRunning = false; m_IsRunning = false;
for (auto it: m_Destinations) for (auto& it: m_Destinations)
it.second->Stop (); it.second->Stop ();
m_Acceptor.cancel (); m_Acceptor.cancel ();
m_Service.stop (); m_Service.stop ();

2
ClientContext.cpp

@ -194,7 +194,7 @@ namespace client
LogPrint(eLogInfo, "Clients: stopping AddressBook"); LogPrint(eLogInfo, "Clients: stopping AddressBook");
m_AddressBook.Stop (); m_AddressBook.Stop ();
for (auto it: m_Destinations) for (auto& it: m_Destinations)
it.second->Stop (); it.second->Stop ();
m_Destinations.clear (); m_Destinations.clear ();
m_SharedLocalDestination = nullptr; m_SharedLocalDestination = nullptr;

6
Config.cpp

@ -148,6 +148,11 @@ namespace config {
"Enable or disable elgamal precomputation table") "Enable or disable elgamal precomputation table")
; ;
options_description reseed("Reseed options");
reseed.add_options()
("reseed.file", value<std::string>()->default_value(""), "Path to .su3 file")
;
options_description trust("Trust options"); options_description trust("Trust options");
trust.add_options() trust.add_options()
("trust.enabled", value<bool>()->default_value(false), "enable explicit trust options") ("trust.enabled", value<bool>()->default_value(false), "enable explicit trust options")
@ -166,6 +171,7 @@ namespace config {
.add(i2pcontrol) .add(i2pcontrol)
.add(upnp) .add(upnp)
.add(precomputation) .add(precomputation)
.add(reseed)
.add(trust) .add(trust)
; ;
} }

17
Destination.cpp

@ -103,7 +103,7 @@ namespace client
{ {
if (m_IsRunning) if (m_IsRunning)
Stop (); Stop ();
for (auto it: m_LeaseSetRequests) for (auto& it: m_LeaseSetRequests)
if (it.second->requestComplete) it.second->requestComplete (nullptr); if (it.second->requestComplete) it.second->requestComplete (nullptr);
m_LeaseSetRequests.clear (); m_LeaseSetRequests.clear ();
if (m_Pool) if (m_Pool)
@ -479,24 +479,25 @@ namespace client
{ {
if (!m_Pool || !IsReady ()) if (!m_Pool || !IsReady ())
{ {
if (requestComplete) requestComplete (nullptr); if (requestComplete)
m_Service.post ([requestComplete](void){requestComplete (nullptr);});
return false; return false;
} }
m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete)); m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete));
return true; 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 (); 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); auto it = s->m_LeaseSetRequests.find (dest);
if (it != s->m_LeaseSetRequests.end ()) if (it != s->m_LeaseSetRequests.end ())
{ {
auto requestComplete = it->second->requestComplete; auto requestComplete = it->second->requestComplete;
s->m_LeaseSetRequests.erase (it); 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); it = m_RemoteLeaseSets.erase (it);
} }
else else
it++; ++it;
} }
} }
@ -663,7 +664,7 @@ namespace client
{ {
m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis ()); // TODO: m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis ()); // TODO:
m_StreamingDestination->Start (); m_StreamingDestination->Start ();
for (auto it: m_StreamingDestinationsByPorts) for (auto& it: m_StreamingDestinationsByPorts)
it.second->Start (); it.second->Start ();
return true; return true;
} }
@ -677,7 +678,7 @@ namespace client
{ {
m_StreamingDestination->Stop (); m_StreamingDestination->Stop ();
m_StreamingDestination = nullptr; m_StreamingDestination = nullptr;
for (auto it: m_StreamingDestinationsByPorts) for (auto& it: m_StreamingDestinationsByPorts)
it.second->Stop (); it.second->Stop ();
if (m_DatagramDestination) if (m_DatagramDestination)
{ {

2
Destination.h

@ -79,7 +79,7 @@ namespace client
bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; }; bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
std::shared_ptr<const i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident); std::shared_ptr<const i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr); 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 // implements GarlicDestination
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet (); std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet ();

12
Garlic.cpp

@ -111,7 +111,7 @@ namespace garlic
it = m_UnconfirmedTagsMsgs.erase (it); it = m_UnconfirmedTagsMsgs.erase (it);
} }
else else
it++; ++it;
} }
} }
@ -123,7 +123,7 @@ namespace garlic
if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT)
it = m_SessionTags.erase (it); it = m_SessionTags.erase (it);
else else
it++; ++it;
} }
CleanupUnconfirmedTags (); CleanupUnconfirmedTags ();
return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty (); return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty ();
@ -144,7 +144,7 @@ namespace garlic
ret = true; ret = true;
} }
else else
it++; ++it;
} }
return ret; return ret;
} }
@ -615,7 +615,7 @@ namespace garlic
it = m_Tags.erase (it); it = m_Tags.erase (it);
} }
else else
it++; ++it;
} }
if (numExpiredTags > 0) if (numExpiredTags > 0)
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " tags expired for ", GetIdentHash().ToBase64 ()); LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " tags expired for ", GetIdentHash().ToBase64 ());
@ -631,7 +631,7 @@ namespace garlic
it = m_Sessions.erase (it); it = m_Sessions.erase (it);
} }
else else
it++; ++it;
} }
} }
@ -662,7 +662,7 @@ namespace garlic
void GarlicDestination::SetLeaseSetUpdated () void GarlicDestination::SetLeaseSetUpdated ()
{ {
std::unique_lock<std::mutex> l(m_SessionsMutex); std::unique_lock<std::mutex> l(m_SessionsMutex);
for (auto it: m_Sessions) for (auto& it: m_Sessions)
it.second->SetLeaseSetUpdated (); it.second->SetLeaseSetUpdated ();
} }

2
HTTP.cpp

@ -160,7 +160,7 @@ namespace http {
strsplit(query, tokens, '&'); strsplit(query, tokens, '&');
params.clear(); params.clear();
for (auto it : tokens) { for (const auto& it : tokens) {
std::size_t eq = it.find ('='); std::size_t eq = it.find ('=');
if (eq != std::string::npos) { if (eq != std::string::npos) {
auto e = std::pair<std::string, std::string>(it.substr(0, eq), it.substr(eq + 1)); auto e = std::pair<std::string, std::string>(it.substr(0, eq), it.substr(eq + 1));

6
HTTPProxy.cpp

@ -113,7 +113,7 @@ namespace proxy {
<< "<p>Remote host not found in router's addressbook</p>\r\n" << "<p>Remote host not found in router's addressbook</p>\r\n"
<< "<p>You may try to find this host on jumpservices below:</p>\r\n" << "<p>You may try to find this host on jumpservices below:</p>\r\n"
<< "<ul>\r\n"; << "<ul>\r\n";
for (auto & js : jumpservices) { for (const auto& js : jumpservices) {
ss << " <li><a href=\"" << js.second << host << "\">" << js.first << "</a></li>\r\n"; ss << " <li><a href=\"" << js.second << host << "\">" << js.first << "</a></li>\r\n";
} }
ss << "</ul>\r\n"; ss << "</ul>\r\n";
@ -164,7 +164,7 @@ namespace proxy {
req.del_header("Forwarded"); req.del_header("Forwarded");
/* drop proxy-disclosing headers */ /* drop proxy-disclosing headers */
std::vector<std::string> toErase; std::vector<std::string> toErase;
for (auto it : req.headers) { for (const auto& it : req.headers) {
if (it.first.compare(0, 12, "X-Forwarded-") == 0) { if (it.first.compare(0, 12, "X-Forwarded-") == 0) {
toErase.push_back(it.first); toErase.push_back(it.first);
} else if (it.first.compare(0, 6, "Proxy-") == 0) { } else if (it.first.compare(0, 6, "Proxy-") == 0) {
@ -173,7 +173,7 @@ namespace proxy {
/* allow */ /* allow */
} }
} }
for (auto header : toErase) { for (const auto& header : toErase) {
req.headers.erase(header); req.headers.erase(header);
} }
/* replace headers */ /* replace headers */

72
HTTPServer.cpp

@ -22,6 +22,9 @@
#include "HTTPServer.h" #include "HTTPServer.h"
#include "Daemon.h" #include "Daemon.h"
#include "util.h" #include "util.h"
#ifdef WIN32_APP
#include "Win32/Win32App.h"
#endif
// For image and info // For image and info
#include "version.h" #include "version.h"
@ -145,8 +148,10 @@ namespace http {
" <a href=\"/?page=" << HTTP_PAGE_TUNNELS << "\">Tunnels</a><br>\r\n" " <a href=\"/?page=" << HTTP_PAGE_TUNNELS << "\">Tunnels</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">Transit tunnels</a><br>\r\n" " <a href=\"/?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">Transit tunnels</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_TRANSPORTS << "\">Transports</a><br>\r\n" " <a href=\"/?page=" << HTTP_PAGE_TRANSPORTS << "\">Transports</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_I2P_TUNNELS << "\">I2P tunnels</a><br>\r\n" " <a href=\"/?page=" << HTTP_PAGE_I2P_TUNNELS << "\">I2P tunnels</a><br>\r\n";
" <a href=\"/?page=" << HTTP_PAGE_SAM_SESSIONS << "\">SAM sessions</a><br>\r\n" if (i2p::client::context.GetSAMBridge ())
s << " <a href=\"/?page=" << HTTP_PAGE_SAM_SESSIONS << "\">SAM sessions</a><br>\r\n";
s <<
"</div>\r\n" "</div>\r\n"
"<div class=right>"; "<div class=right>";
} }
@ -207,7 +212,7 @@ namespace http {
s << "<b>Router Family:</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n"; s << "<b>Router Family:</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
s << "<b>Router Caps:</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n"; s << "<b>Router Caps:</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n";
s << "<b>Our external address:</b>" << "<br>\r\n" ; s << "<b>Our external address:</b>" << "<br>\r\n" ;
for (auto address : i2p::context.GetRouterInfo().GetAddresses()) for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
{ {
switch (address->transportStyle) switch (address->transportStyle)
{ {
@ -280,7 +285,7 @@ namespace http {
} }
s << "<br>\r\n"; s << "<br>\r\n";
s << "<b>Tags</b><br>Incoming: " << dest->GetNumIncomingTags () << "<br>Outgoing:<br>" << std::endl; s << "<b>Tags</b><br>Incoming: " << dest->GetNumIncomingTags () << "<br>Outgoing:<br>" << std::endl;
for (auto it: dest->GetSessions ()) for (const auto& it: dest->GetSessions ())
{ {
s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " "; s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " ";
s << it.second->GetNumOutgoingTags () << "<br>" << std::endl; s << it.second->GetNumOutgoingTags () << "<br>" << std::endl;
@ -311,7 +316,7 @@ namespace http {
s << "<th>Status</th>"; s << "<th>Status</th>";
s << "</tr>"; s << "</tr>";
for (auto it: dest->GetAllStreams ()) for (const auto& it: dest->GetAllStreams ())
{ {
s << "<tr>"; s << "<tr>";
s << "<td>" << it->GetSendStreamID () << "</td>"; s << "<td>" << it->GetSendStreamID () << "</td>";
@ -331,7 +336,7 @@ namespace http {
void ShowLeasesSets(std::stringstream& s) void ShowLeasesSets(std::stringstream& s)
{ {
s << "<div id='leasesets'>LeaseSets</div><br>"; s << "<div id='leasesets'><b>LeaseSets:</b></div><br>";
// for each lease set // for each lease set
i2p::data::netdb.VisitLeaseSets( i2p::data::netdb.VisitLeaseSets(
[&s](const i2p::data::IdentHash dest, std::shared_ptr<i2p::data::LeaseSet> leaseSet) [&s](const i2p::data::IdentHash dest, std::shared_ptr<i2p::data::LeaseSet> leaseSet)
@ -409,28 +414,34 @@ namespace http {
else else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "\">Accept transit tunnels</a><br>\r\n"; s << " <a href=\"/?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "\">Accept transit tunnels</a><br>\r\n";
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
if (Daemon.gracefullShutdownInterval) { if (Daemon.gracefullShutdownInterval)
{
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "\">Cancel gracefull shutdown ("; s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "\">Cancel gracefull shutdown (";
s << Daemon.gracefullShutdownInterval; s << Daemon.gracefullShutdownInterval;
s << " seconds remains)</a><br>\r\n"; s << " seconds remains)</a><br>\r\n";
} else { }
else
{
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "\">Start gracefull shutdown</a><br>\r\n"; s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "\">Start gracefull shutdown</a><br>\r\n";
} }
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "\">Force shutdown</a><br>\r\n";
#endif #endif
#ifdef WIN32_APP
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "\">Gracefull shutdown</a><br>\r\n";
#endif
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "\">Force shutdown</a><br>\r\n";
} }
void ShowTransitTunnels (std::stringstream& s) void ShowTransitTunnels (std::stringstream& s)
{ {
s << "<b>Transit tunnels:</b><br>\r\n<br>\r\n"; s << "<b>Transit tunnels:</b><br>\r\n<br>\r\n";
for (auto it: i2p::tunnel::tunnels.GetTransitTunnels ()) for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
{ {
if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelGateway>(it)) if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelGateway>(it))
s << it->GetTunnelID () << " "; s << it->GetTunnelID () << " &#8658; ";
else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it)) else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
s << " " << it->GetTunnelID (); s << " &#8658; " << it->GetTunnelID ();
else else
s << " " << it->GetTunnelID () << " "; s << " &#8658; " << it->GetTunnelID () << " &#8658; ";
s << " " << it->GetNumTransmittedBytes () << "<br>\r\n"; s << " " << it->GetNumTransmittedBytes () << "<br>\r\n";
} }
} }
@ -442,15 +453,15 @@ namespace http {
if (ntcpServer) if (ntcpServer)
{ {
s << "<b>NTCP</b><br>\r\n"; s << "<b>NTCP</b><br>\r\n";
for (auto it: ntcpServer->GetNTCPSessions ()) for (const auto& it: ntcpServer->GetNTCPSessions ())
{ {
if (it.second && it.second->IsEstablished ()) if (it.second && it.second->IsEstablished ())
{ {
// incoming connection doesn't have remote RI // incoming connection doesn't have remote RI
if (it.second->IsOutgoing ()) s << " "; if (it.second->IsOutgoing ()) s << " &#8658; ";
s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": " s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
<< it.second->GetSocket ().remote_endpoint().address ().to_string (); << it.second->GetSocket ().remote_endpoint().address ().to_string ();
if (!it.second->IsOutgoing ()) s << " "; if (!it.second->IsOutgoing ()) s << " &#8658; ";
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
s << "<br>\r\n" << std::endl; s << "<br>\r\n" << std::endl;
} }
@ -460,24 +471,24 @@ namespace http {
if (ssuServer) if (ssuServer)
{ {
s << "<br>\r\n<b>SSU</b><br>\r\n"; s << "<br>\r\n<b>SSU</b><br>\r\n";
for (auto it: ssuServer->GetSessions ()) for (const auto& it: ssuServer->GetSessions ())
{ {
auto endpoint = it.second->GetRemoteEndpoint (); auto endpoint = it.second->GetRemoteEndpoint ();
if (it.second->IsOutgoing ()) s << " "; if (it.second->IsOutgoing ()) s << " &#8658; ";
s << endpoint.address ().to_string () << ":" << endpoint.port (); s << endpoint.address ().to_string () << ":" << endpoint.port ();
if (!it.second->IsOutgoing ()) s << " "; if (!it.second->IsOutgoing ()) s << " &#8658; ";
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it.second->GetRelayTag ()) if (it.second->GetRelayTag ())
s << " [itag:" << it.second->GetRelayTag () << "]"; s << " [itag:" << it.second->GetRelayTag () << "]";
s << "<br>\r\n" << std::endl; s << "<br>\r\n" << std::endl;
} }
s << "<br>\r\n<b>SSU6</b><br>\r\n"; s << "<br>\r\n<b>SSU6</b><br>\r\n";
for (auto it: ssuServer->GetSessionsV6 ()) for (const auto& it: ssuServer->GetSessionsV6 ())
{ {
auto endpoint = it.second->GetRemoteEndpoint (); auto endpoint = it.second->GetRemoteEndpoint ();
if (it.second->IsOutgoing ()) s << " "; if (it.second->IsOutgoing ()) s << " &#8658; ";
s << endpoint.address ().to_string () << ":" << endpoint.port (); s << endpoint.address ().to_string () << ":" << endpoint.port ();
if (!it.second->IsOutgoing ()) s << " "; if (!it.second->IsOutgoing ()) s << " &#8658; ";
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
s << "<br>\r\n" << std::endl; s << "<br>\r\n" << std::endl;
} }
@ -517,7 +528,7 @@ namespace http {
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n"; s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n";
s << "<br>\r\n"; s << "<br>\r\n";
s << "<b>Streams:</b><br>\r\n"; s << "<b>Streams:</b><br>\r\n";
for (auto it: session->ListSockets()) for (const auto& it: session->ListSockets())
{ {
switch (it->GetSocketType ()) switch (it->GetSocketType ())
{ {
@ -538,7 +549,7 @@ namespace http {
{ {
auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">"; s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> "; s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl; s << "<br>\r\n"<< std::endl;
} }
@ -547,7 +558,7 @@ namespace http {
{ {
auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">"; s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> "; s << it.second->GetName () << "</a> &#8658; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << ":" << it.second->GetLocalPort (); s << ":" << it.second->GetLocalPort ();
s << "</a><br>\r\n"<< std::endl; s << "</a><br>\r\n"<< std::endl;
@ -723,6 +734,9 @@ namespace http {
i2p::context.SetAcceptsTunnels (false); i2p::context.SetAcceptsTunnels (false);
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
Daemon.gracefullShutdownInterval = 10*60; Daemon.gracefullShutdownInterval = 10*60;
#endif
#ifdef WIN32_APP
i2p::win32::GracefulShutdown ();
#endif #endif
} else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) { } else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) {
i2p::context.SetAcceptsTunnels (true); i2p::context.SetAcceptsTunnels (true);
@ -770,12 +784,14 @@ namespace http {
std::string pass; i2p::config::GetOption("http.pass", pass); std::string pass; i2p::config::GetOption("http.pass", pass);
/* generate pass if needed */ /* generate pass if needed */
if (needAuth && pass == "") { if (needAuth && pass == "") {
uint8_t random[16];
char alnum[] = "0123456789" char alnum[] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"; "abcdefghijklmnopqrstuvwxyz";
pass.resize(16); pass.resize(sizeof(random));
for (size_t i = 0; i < pass.size(); i++) { RAND_bytes(random, sizeof(random));
pass[i] = alnum[rand() % (sizeof(alnum) - 1)]; for (size_t i = 0; i < sizeof(random); i++) {
pass[i] = alnum[random[i] % (sizeof(alnum) - 1)];
} }
i2p::config::SetOption("http.pass", pass); i2p::config::SetOption("http.pass", pass);
LogPrint(eLogInfo, "HTTPServer: password set to ", pass); LogPrint(eLogInfo, "HTTPServer: password set to ", pass);

2
I2CP.cpp

@ -659,7 +659,7 @@ namespace client
{ {
m_IsRunning = false; m_IsRunning = false;
m_Acceptor.cancel (); m_Acceptor.cancel ();
for (auto it: m_Sessions) for (auto& it: m_Sessions)
it.second->Stop (); it.second->Stop ();
m_Sessions.clear (); m_Sessions.clear ();
m_Service.stop (); m_Service.stop ();

2
I2NPProtocol.cpp

@ -202,7 +202,7 @@ namespace i2p
len += 32; len += 32;
buf[len] = routers.size (); buf[len] = routers.size ();
len++; len++;
for (auto it: routers) for (const auto& it: routers)
{ {
memcpy (buf + len, it, 32); memcpy (buf + len, it, 32);
len += 32; len += 32;

6
I2PControl.cpp

@ -358,7 +358,7 @@ namespace client
void I2PControlService::RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) 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); LogPrint (eLogDebug, "I2PControl: RouterInfo request: ", it->first);
auto it1 = m_RouterInfoHandlers.find (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) 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 << ","; if (it != params.begin ()) results << ",";
LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first); LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first);
@ -483,7 +483,7 @@ namespace client
// network setting // network setting
void I2PControlService::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results) 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 << ","; if (it != params.begin ()) results << ",";
LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first); LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first);

8
LeaseSet.cpp

@ -66,7 +66,7 @@ namespace data
// reset existing leases // reset existing leases
if (m_StoreLeases) if (m_StoreLeases)
for (auto it: m_Leases) for (auto& it: m_Leases)
it->isUpdated = false; it->isUpdated = false;
else else
m_Leases.clear (); m_Leases.clear ();
@ -123,7 +123,7 @@ namespace data
m_Leases.erase (it++); m_Leases.erase (it++);
} }
else else
it++; ++it;
} }
} }
@ -167,7 +167,7 @@ namespace data
{ {
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::GetMillisecondsSinceEpoch ();
std::vector<std::shared_ptr<const Lease> > leases; std::vector<std::shared_ptr<const Lease> > leases;
for (auto it: m_Leases) for (const auto& it: m_Leases)
{ {
auto endDate = it->endDate; auto endDate = it->endDate;
if (withThreshold) if (withThreshold)
@ -183,7 +183,7 @@ namespace data
bool LeaseSet::HasExpiredLeases () const bool LeaseSet::HasExpiredLeases () const
{ {
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto it: m_Leases) for (const auto& it: m_Leases)
if (ts >= it->endDate) return true; if (ts >= it->endDate) return true;
return false; return false;
} }

2
Makefile.mingw

@ -37,7 +37,7 @@ ifeq ($(USE_WIN32_APP), yes)
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
endif endif
ifeq ($(USE_AESNI),yes) ifeq ($(USE_AESNI),1)
CPU_FLAGS = -maes -DAESNI CPU_FLAGS = -maes -DAESNI
else else
CPU_FLAGS = -msse CPU_FLAGS = -msse

13
NTCPSession.cpp

@ -19,7 +19,8 @@ namespace i2p
namespace transport namespace transport
{ {
NTCPSession::NTCPSession (NTCPServer& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter): NTCPSession::NTCPSession (NTCPServer& server, std::shared_ptr<const i2p::data::RouterInfo> 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_TerminationTimer (m_Server.GetService ()), m_IsEstablished (false), m_IsTerminated (false),
m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_IsSending (false) m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_IsSending (false)
{ {
@ -665,7 +666,7 @@ namespace transport
{ {
m_IsSending = true; m_IsSending = true;
std::vector<boost::asio::const_buffer> bufs; std::vector<boost::asio::const_buffer> bufs;
for (auto it: msgs) for (const auto& it: msgs)
bufs.push_back (CreateMsgBuffer (it)); bufs.push_back (CreateMsgBuffer (it));
boost::asio::async_write (m_Socket, bufs, boost::asio::transfer_all (), 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)); 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) if (m_SendQueue.size () < NTCP_MAX_OUTGOING_QUEUE_SIZE)
{ {
for (auto it: msgs) for (const auto& it: msgs)
m_SendQueue.push_back (it); m_SendQueue.push_back (it);
} }
else else
@ -731,7 +732,7 @@ namespace transport
void NTCPSession::ScheduleTermination () void NTCPSession::ScheduleTermination ()
{ {
m_TerminationTimer.cancel (); 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, m_TerminationTimer.async_wait (std::bind (&NTCPSession::HandleTerminationTimer,
shared_from_this (), std::placeholders::_1)); shared_from_this (), std::placeholders::_1));
} }
@ -740,7 +741,7 @@ namespace transport
{ {
if (ecode != boost::asio::error::operation_aborted) 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 (); //Terminate ();
m_Socket.close ();// invoke Terminate () from HandleReceive m_Socket.close ();// invoke Terminate () from HandleReceive
} }
@ -766,7 +767,7 @@ namespace transport
m_Thread = new std::thread (std::bind (&NTCPServer::Run, this)); m_Thread = new std::thread (std::bind (&NTCPServer::Run, this));
// create acceptors // create acceptors
auto& addresses = context.GetRouterInfo ().GetAddresses (); auto& addresses = context.GetRouterInfo ().GetAddresses ();
for (auto address: addresses) for (const auto& address: addresses)
{ {
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP) if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
{ {

35
NetDb.cpp

@ -14,7 +14,6 @@
#include "RouterContext.h" #include "RouterContext.h"
#include "Garlic.h" #include "Garlic.h"
#include "NetDb.h" #include "NetDb.h"
#include "util.h"
using namespace i2p::transport; using namespace i2p::transport;
@ -52,7 +51,7 @@ namespace data
{ {
if (m_IsRunning) if (m_IsRunning)
{ {
for (auto it: m_RouterInfos) for (auto& it: m_RouterInfos)
it.second->SaveProfile (); it.second->SaveProfile ();
DeleteObsoleteProfiles (); DeleteObsoleteProfiles ();
m_RouterInfos.clear (); m_RouterInfos.clear ();
@ -72,7 +71,7 @@ namespace data
void NetDb::Run () 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) while (m_IsRunning)
{ {
try try
@ -122,7 +121,11 @@ namespace data
} }
lastSave = ts; 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 we're in hidden mode don't publish or explore
// if (m_HiddenMode) continue; // if (m_HiddenMode) continue;
@ -336,7 +339,7 @@ namespace data
m_LastLoad = i2p::util::GetSecondsSinceEpoch(); m_LastLoad = i2p::util::GetSecondsSinceEpoch();
std::vector<std::string> files; std::vector<std::string> files;
m_Storage.Traverse(files); m_Storage.Traverse(files);
for (auto path : files) for (const auto& path : files)
LoadRouterInfo(path); LoadRouterInfo(path);
LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.size (), " floodfils)"); 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 : expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL :
NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
for (auto it: m_RouterInfos) for (auto& it: m_RouterInfos)
{ {
std::string ident = it.second->GetIdentHashBase64(); std::string ident = it.second->GetIdentHashBase64();
std::string path = m_Storage.Path(ident); std::string path = m_Storage.Path(ident);
@ -402,7 +405,7 @@ namespace data
it = m_RouterInfos.erase (it); it = m_RouterInfos.erase (it);
continue; continue;
} }
it++; ++it;
} }
} }
// clean up expired floodfiils // clean up expired floodfiils
@ -412,7 +415,7 @@ namespace data
if ((*it)->IsUnreachable ()) if ((*it)->IsUnreachable ())
it = m_Floodfills.erase (it); it = m_Floodfills.erase (it);
else else
it++; ++it;
} }
} }
} }
@ -898,7 +901,7 @@ namespace data
{ {
uint32_t i = 0; uint32_t i = 0;
std::unique_lock<std::mutex> l(m_RouterInfosMutex); std::unique_lock<std::mutex> l(m_RouterInfosMutex);
for (auto it: m_RouterInfos) for (const auto& it: m_RouterInfos)
{ {
if (i >= ind) if (i >= ind)
{ {
@ -930,7 +933,7 @@ namespace data
else else
minMetric.SetMax (); minMetric.SetMax ();
std::unique_lock<std::mutex> l(m_FloodfillsMutex); std::unique_lock<std::mutex> l(m_FloodfillsMutex);
for (auto it: m_Floodfills) for (const auto& it: m_Floodfills)
{ {
if (!it->IsUnreachable ()) if (!it->IsUnreachable ())
{ {
@ -961,7 +964,7 @@ namespace data
if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash (); if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash ();
{ {
std::unique_lock<std::mutex> l(m_FloodfillsMutex); std::unique_lock<std::mutex> l(m_FloodfillsMutex);
for (auto it: m_Floodfills) for (const auto& it: m_Floodfills)
{ {
if (!it->IsUnreachable ()) if (!it->IsUnreachable ())
{ {
@ -980,11 +983,11 @@ namespace data
std::vector<IdentHash> res; std::vector<IdentHash> res;
size_t i = 0; size_t i = 0;
for (auto it: sorted) for (const auto& it: sorted)
{ {
if (i < num) if (i < num)
{ {
auto& ident = it.r->GetIdentHash (); const auto& ident = it.r->GetIdentHash ();
if (!excluded.count (ident)) if (!excluded.count (ident))
{ {
res.push_back (ident); res.push_back (ident);
@ -1013,7 +1016,7 @@ namespace data
IdentHash destKey = CreateRoutingKey (destination); IdentHash destKey = CreateRoutingKey (destination);
minMetric.SetMax (); minMetric.SetMax ();
// must be called from NetDb thread only // must be called from NetDb thread only
for (auto it: m_RouterInfos) for (const auto& it: m_RouterInfos)
{ {
if (!it.second->IsFloodfill ()) if (!it.second->IsFloodfill ())
{ {
@ -1039,7 +1042,7 @@ namespace data
it = m_LeaseSets.erase (it); it = m_LeaseSets.erase (it);
} }
else else
it++; ++it;
} }
} }
@ -1051,7 +1054,7 @@ namespace data
if (ts > it->second.second + 180) // 3 minutes if (ts > it->second.second + 180) // 3 minutes
it = m_LookupResponses.erase (it); it = m_LookupResponses.erase (it);
else else
it++; ++it;
} }
} }
} }

2
NetDbRequests.cpp

@ -141,7 +141,7 @@ namespace data
if (done) if (done)
it = m_RequestedDestinations.erase (it); it = m_RequestedDestinations.erase (it);
else else
it++; ++it;
} }
} }
} }

2
Profiling.cpp

@ -167,7 +167,7 @@ namespace data
std::vector<std::string> files; std::vector<std::string> files;
m_ProfilesStorage.Traverse(files); m_ProfilesStorage.Traverse(files);
for (auto path: files) { for (const auto& path: files) {
if (stat(path.c_str(), &st) != 0) { if (stat(path.c_str(), &st) != 0) {
LogPrint(eLogWarning, "Profiling: Can't stat(): ", path); LogPrint(eLogWarning, "Profiling: Can't stat(): ", path);
continue; continue;

5
Queue.h

@ -7,6 +7,7 @@
#include <thread> #include <thread>
#include <condition_variable> #include <condition_variable>
#include <functional> #include <functional>
#include <utility>
namespace i2p namespace i2p
{ {
@ -20,7 +21,7 @@ namespace util
void Put (Element e) void Put (Element e)
{ {
std::unique_lock<std::mutex> l(m_QueueMutex); std::unique_lock<std::mutex> l(m_QueueMutex);
m_Queue.push (e); m_Queue.push (std::move(e));
m_NonEmpty.notify_one (); m_NonEmpty.notify_one ();
} }
@ -29,7 +30,7 @@ namespace util
if (!vec.empty ()) if (!vec.empty ())
{ {
std::unique_lock<std::mutex> l(m_QueueMutex); std::unique_lock<std::mutex> l(m_QueueMutex);
for (auto it: vec) for (const auto& it: vec)
m_Queue.push (it); m_Queue.push (it);
m_NonEmpty.notify_one (); m_NonEmpty.notify_one ();
} }

8
Reseed.cpp

@ -16,6 +16,7 @@
#include "NetDb.h" #include "NetDb.h"
#include "HTTP.h" #include "HTTP.h"
#include "util.h" #include "util.h"
#include "Config.h"
namespace i2p namespace i2p
{ {
@ -51,6 +52,13 @@ namespace data
int Reseeder::ReseedNowSU3 () 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 (); auto ind = rand () % httpsReseedHostList.size ();
std::string& reseedHost = httpsReseedHostList[ind]; std::string& reseedHost = httpsReseedHostList[ind];
return ReseedFromSU3 (reseedHost); return ReseedFromSU3 (reseedHost);

20
RouterContext.cpp

@ -112,7 +112,7 @@ namespace i2p
void RouterContext::UpdatePort (int port) void RouterContext::UpdatePort (int port)
{ {
bool updated = false; bool updated = false;
for (auto address : m_RouterInfo.GetAddresses ()) for (auto& address : m_RouterInfo.GetAddresses ())
{ {
if (address->port != port) if (address->port != port)
{ {
@ -127,7 +127,7 @@ namespace i2p
void RouterContext::UpdateAddress (const boost::asio::ip::address& host) void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
{ {
bool updated = false; bool updated = false;
for (auto address : m_RouterInfo.GetAddresses ()) for (auto& address : m_RouterInfo.GetAddresses ())
{ {
if (address->host != host && address->IsCompatible (host)) 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 m_RouterInfo.SetCaps (i2p::data::RouterInfo::eUnreachable | i2p::data::RouterInfo::eSSUTesting); // LU, B
// remove NTCP address // remove NTCP address
auto& addresses = m_RouterInfo.GetAddresses (); 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 && if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportNTCP &&
(*it)->host.is_v4 ()) (*it)->host.is_v4 ())
@ -254,7 +254,7 @@ namespace i2p
} }
} }
// delete previous introducers // delete previous introducers
for (auto addr : addresses) for (auto& addr : addresses)
addr->introducers.clear (); addr->introducers.clear ();
// update // update
@ -274,7 +274,7 @@ namespace i2p
// insert NTCP back // insert NTCP back
auto& addresses = m_RouterInfo.GetAddresses (); auto& addresses = m_RouterInfo.GetAddresses ();
for (auto addr : addresses) for (const auto& addr : addresses)
{ {
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU && if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
addr->host.is_v4 ()) addr->host.is_v4 ())
@ -285,7 +285,7 @@ namespace i2p
} }
} }
// delete previous introducers // delete previous introducers
for (auto addr : addresses) for (auto& addr : addresses)
addr->introducers.clear (); addr->introducers.clear ();
// update // update
@ -316,7 +316,7 @@ namespace i2p
bool updated = false, found = false; bool updated = false, found = false;
int port = 0; int port = 0;
auto& addresses = m_RouterInfo.GetAddresses (); auto& addresses = m_RouterInfo.GetAddresses ();
for (auto addr: addresses) for (auto& addr: addresses)
{ {
if (addr->host.is_v6 () && addr->transportStyle == i2p::data::RouterInfo::eTransportNTCP) if (addr->host.is_v6 () && addr->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
{ {
@ -440,6 +440,12 @@ namespace i2p
i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg); i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg);
} }
void RouterContext::CleanupDestination ()
{
std::unique_lock<std::mutex> l(m_GarlicMutex);
i2p::garlic::GarlicDestination::CleanupExpiredTags ();
}
uint32_t RouterContext::GetUptime () const uint32_t RouterContext::GetUptime () const
{ {
return i2p::util::GetSecondsSinceEpoch () - m_StartupTime; return i2p::util::GetSecondsSinceEpoch () - m_StartupTime;

1
RouterContext.h

@ -72,6 +72,7 @@ namespace i2p
void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session
void UpdateStats (); void UpdateStats ();
void CleanupDestination (); // garlic destination
// implements LocalDestination // implements LocalDestination
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); }; std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };

45
RouterInfo.cpp

@ -369,19 +369,19 @@ namespace data
SetProperty ("caps", caps); SetProperty ("caps", caps);
} }
void RouterInfo::WriteToStream (std::ostream& s) void RouterInfo::WriteToStream (std::ostream& s) const
{ {
uint64_t ts = htobe64 (m_Timestamp); uint64_t ts = htobe64 (m_Timestamp);
s.write ((char *)&ts, sizeof (ts)); s.write ((const char *)&ts, sizeof (ts));
// addresses // addresses
uint8_t numAddresses = m_Addresses->size (); uint8_t numAddresses = m_Addresses->size ();
s.write ((char *)&numAddresses, sizeof (numAddresses)); s.write ((char *)&numAddresses, sizeof (numAddresses));
for (auto addr : *m_Addresses) for (const auto& addr_ptr : *m_Addresses)
{ {
Address& address = *addr; const Address& address = *addr_ptr;
s.write ((char *)&address.cost, sizeof (address.cost)); s.write ((const char *)&address.cost, sizeof (address.cost));
s.write ((char *)&address.date, sizeof (address.date)); s.write ((const char *)&address.date, sizeof (address.date));
std::stringstream properties; std::stringstream properties;
if (address.transportStyle == eTransportNTCP) if (address.transportStyle == eTransportNTCP)
WriteString ("NTCP", s); WriteString ("NTCP", s);
@ -410,7 +410,7 @@ namespace data
if (address.introducers.size () > 0) if (address.introducers.size () > 0)
{ {
int i = 0; int i = 0;
for (auto introducer: address.introducers) for (const auto& introducer: address.introducers)
{ {
WriteString ("ihost" + boost::lexical_cast<std::string>(i), properties); WriteString ("ihost" + boost::lexical_cast<std::string>(i), properties);
properties << '='; properties << '=';
@ -419,7 +419,7 @@ namespace data
i++; i++;
} }
i = 0; i = 0;
for (auto introducer: address.introducers) for (const auto& introducer: address.introducers)
{ {
WriteString ("ikey" + boost::lexical_cast<std::string>(i), properties); WriteString ("ikey" + boost::lexical_cast<std::string>(i), properties);
properties << '='; properties << '=';
@ -431,7 +431,7 @@ namespace data
i++; i++;
} }
i = 0; i = 0;
for (auto introducer: address.introducers) for (const auto& introducer: address.introducers)
{ {
WriteString ("iport" + boost::lexical_cast<std::string>(i), properties); WriteString ("iport" + boost::lexical_cast<std::string>(i), properties);
properties << '='; properties << '=';
@ -440,7 +440,7 @@ namespace data
i++; i++;
} }
i = 0; i = 0;
for (auto introducer: address.introducers) for (const auto& introducer: address.introducers)
{ {
WriteString ("itag" + boost::lexical_cast<std::string>(i), properties); WriteString ("itag" + boost::lexical_cast<std::string>(i), properties);
properties << '='; properties << '=';
@ -482,7 +482,7 @@ namespace data
// properties // properties
std::stringstream properties; std::stringstream properties;
for (auto& p : m_Properties) for (const auto& p : m_Properties)
{ {
WriteString (p.first, properties); WriteString (p.first, properties);
properties << '='; properties << '=';
@ -570,10 +570,10 @@ namespace data
addr->cost = 2; addr->cost = 2;
addr->date = 0; addr->date = 0;
addr->mtu = 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; if (*it == *addr) return;
m_Addresses->push_back(addr);
m_SupportedTransports |= addr->host.is_v6 () ? eNTCPV6 : eNTCPV4; 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) void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu)
@ -586,21 +586,22 @@ namespace data
addr->date = 0; addr->date = 0;
addr->mtu = mtu; addr->mtu = mtu;
memcpy (addr->key, key, 32); 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; if (*it == *addr) return;
m_Addresses->push_back(addr);
m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4; m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4;
m_Addresses->push_back(std::move(addr));
m_Caps |= eSSUTesting; m_Caps |= eSSUTesting;
m_Caps |= eSSUIntroducer; m_Caps |= eSSUIntroducer;
} }
bool RouterInfo::AddIntroducer (const Introducer& introducer) bool RouterInfo::AddIntroducer (const Introducer& introducer)
{ {
for (auto addr : *m_Addresses) for (auto& addr : *m_Addresses)
{ {
if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ()) 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 if (intro.iTag == introducer.iTag) return false; // already presented
addr->introducers.push_back (introducer); addr->introducers.push_back (introducer);
return true; return true;
@ -611,11 +612,11 @@ namespace data
bool RouterInfo::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e) 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 ()) if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ())
{ {
for (std::vector<Introducer>::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) if ( boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e)
{ {
addr->introducers.erase (it); addr->introducers.erase (it);
@ -707,7 +708,7 @@ namespace data
if (addr->host.is_v6 ()) if (addr->host.is_v6 ())
it = m_Addresses->erase (it); it = m_Addresses->erase (it);
else else
it++; ++it;
} }
} }
} }
@ -723,7 +724,7 @@ namespace data
if (addr->host.is_v4 ()) if (addr->host.is_v4 ())
it = m_Addresses->erase (it); it = m_Addresses->erase (it);
else else
it++; ++it;
} }
} }
} }
@ -752,7 +753,7 @@ namespace data
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (TransportStyle s, bool v4only, bool v6only) const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (TransportStyle s, bool v4only, bool v6only) const
{ {
auto addresses = m_Addresses; auto addresses = m_Addresses;
for (auto address : *addresses) for (const auto& address : *addresses)
{ {
if (address->transportStyle == s) if (address->transportStyle == s)
{ {

6
RouterInfo.h

@ -187,9 +187,9 @@ namespace data
void ReadFromFile (); void ReadFromFile ();
void ReadFromStream (std::istream& s); void ReadFromStream (std::istream& s);
void ReadFromBuffer (bool verifySignature); void ReadFromBuffer (bool verifySignature);
void WriteToStream (std::ostream& s); void WriteToStream (std::ostream& s) const;
size_t ReadString (char * str, std::istream& s); static size_t ReadString (char* str, std::istream& s);
void WriteString (const std::string& str, std::ostream& s); static void WriteString (const std::string& str, std::ostream& s);
void ExtractCaps (const char * value); void ExtractCaps (const char * value);
std::shared_ptr<const Address> GetAddress (TransportStyle s, bool v4only, bool v6only = false) const; std::shared_ptr<const Address> GetAddress (TransportStyle s, bool v4only, bool v6only = false) const;
void UpdateCapsProperty (); void UpdateCapsProperty ();

4
SAM.cpp

@ -686,7 +686,7 @@ namespace client
{ {
{ {
std::lock_guard<std::mutex> lock(m_SocketsMutex); std::lock_guard<std::mutex> lock(m_SocketsMutex);
for (auto sock : m_Sockets) { for (auto& sock : m_Sockets) {
sock->CloseStream(); sock->CloseStream();
} }
} }
@ -719,7 +719,7 @@ namespace client
{ {
m_IsRunning = false; m_IsRunning = false;
m_Acceptor.cancel (); m_Acceptor.cancel ();
for (auto it: m_Sessions) for (auto& it: m_Sessions)
it.second->CloseStreams (); it.second->CloseStreams ();
m_Sessions.clear (); m_Sessions.clear ();
m_Service.stop (); m_Service.stop ();

2
SAM.h

@ -154,7 +154,7 @@ namespace client
std::list<std::shared_ptr<SAMSocket> > l; std::list<std::shared_ptr<SAMSocket> > l;
{ {
std::lock_guard<std::mutex> lock(m_SocketsMutex); std::lock_guard<std::mutex> lock(m_SocketsMutex);
for( auto & sock : m_Sockets ) l.push_back(sock); for(const auto& sock : m_Sockets ) l.push_back(sock);
} }
return l; return l;
} }

2
SOCKS.cpp

@ -26,7 +26,7 @@ namespace proxy
{ {
uint8_t size; uint8_t size;
char value[max_socks_hostname_size]; char value[max_socks_hostname_size];
void FromString (std::string str) void FromString (const std::string& str)
{ {
size = str.length(); size = str.length();
if (str.length() > max_socks_hostname_size) size = max_socks_hostname_size; if (str.length() > max_socks_hostname_size) size = max_socks_hostname_size;

22
SSU.cpp

@ -237,9 +237,8 @@ namespace transport
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSUSession> > * sessions) std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSUSession> > * sessions)
{ {
std::shared_ptr<SSUSession> session; std::shared_ptr<SSUSession> session;
for (auto it1: packets) for (auto& packet: packets)
{ {
auto packet = it1;
try try
{ {
if (!session || session->GetRemoteEndpoint () != packet->from) // we received packet for other session than previous if (!session || session->GetRemoteEndpoint () != packet->from) // we received packet for other session than previous
@ -431,11 +430,11 @@ namespace transport
void SSUServer::DeleteAllSessions () void SSUServer::DeleteAllSessions ()
{ {
for (auto it: m_Sessions) for (auto& it: m_Sessions)
it.second->Close (); it.second->Close ();
m_Sessions.clear (); m_Sessions.clear ();
for (auto it: m_SessionsV6) for (auto& it: m_SessionsV6)
it.second->Close (); it.second->Close ();
m_SessionsV6.clear (); m_SessionsV6.clear ();
} }
@ -444,7 +443,7 @@ namespace transport
std::shared_ptr<SSUSession> SSUServer::GetRandomV4Session (Filter filter) // v4 only std::shared_ptr<SSUSession> SSUServer::GetRandomV4Session (Filter filter) // v4 only
{ {
std::vector<std::shared_ptr<SSUSession> > filteredSessions; std::vector<std::shared_ptr<SSUSession> > filteredSessions;
for (auto s :m_Sessions) for (const auto& s :m_Sessions)
if (filter (s.second)) filteredSessions.push_back (s.second); if (filter (s.second)) filteredSessions.push_back (s.second);
if (filteredSessions.size () > 0) if (filteredSessions.size () > 0)
{ {
@ -468,7 +467,7 @@ namespace transport
std::shared_ptr<SSUSession> SSUServer::GetRandomV6Session (Filter filter) // v6 only std::shared_ptr<SSUSession> SSUServer::GetRandomV6Session (Filter filter) // v6 only
{ {
std::vector<std::shared_ptr<SSUSession> > filteredSessions; std::vector<std::shared_ptr<SSUSession> > filteredSessions;
for (auto s :m_SessionsV6) for (const auto& s :m_SessionsV6)
if (filter (s.second)) filteredSessions.push_back (s.second); if (filter (s.second)) filteredSessions.push_back (s.second);
if (filteredSessions.size () > 0) if (filteredSessions.size () > 0)
{ {
@ -535,7 +534,7 @@ namespace transport
std::list<boost::asio::ip::udp::endpoint> newList; std::list<boost::asio::ip::udp::endpoint> newList;
size_t numIntroducers = 0; size_t numIntroducers = 0;
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it :m_Introducers) for (const auto& it : m_Introducers)
{ {
auto session = FindSession (it); auto session = FindSession (it);
if (session && ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION) if (session && ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION)
@ -552,11 +551,9 @@ namespace transport
{ {
// create new // create new
auto introducers = FindIntroducers (SSU_MAX_NUM_INTRODUCERS); 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 ();
{
auto& ep = it1->GetRemoteEndpoint ();
i2p::data::RouterInfo::Introducer introducer; i2p::data::RouterInfo::Introducer introducer;
introducer.iHost = ep.address (); introducer.iHost = ep.address ();
introducer.iPort = ep.port (); introducer.iPort = ep.port ();
@ -569,7 +566,6 @@ namespace transport
} }
} }
} }
}
m_Introducers = newList; m_Introducers = newList;
if (m_Introducers.size () < SSU_MAX_NUM_INTRODUCERS) if (m_Introducers.size () < SSU_MAX_NUM_INTRODUCERS)
{ {
@ -637,7 +633,7 @@ namespace transport
it = m_PeerTests.erase (it); it = m_PeerTests.erase (it);
} }
else else
it++; ++it;
} }
if (numDeleted > 0) if (numDeleted > 0)
LogPrint (eLogDebug, "SSU: ", numDeleted, " peer tests have been expired"); LogPrint (eLogDebug, "SSU: ", numDeleted, " peer tests have been expired");

36
SSUData.cpp

@ -25,10 +25,10 @@ namespace transport
} }
SSUData::SSUData (SSUSession& session): 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_IncompleteMessagesCleanupTimer (session.GetService ()),
m_MaxPacketSize (session.IsV6 () ? SSU_V6_MAX_PACKET_SIZE : SSU_V4_MAX_PACKET_SIZE), 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 () void SSUData::Stop ()
{ {
m_ResendTimer.cancel (); m_ResendTimer.cancel ();
m_DecayTimer.cancel ();
m_IncompleteMessagesCleanupTimer.cancel (); m_IncompleteMessagesCleanupTimer.cancel ();
} }
@ -233,11 +232,8 @@ namespace transport
{ {
if (!m_ReceivedMessages.count (msgID)) if (!m_ReceivedMessages.count (msgID))
{ {
if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES)
m_ReceivedMessages.clear ();
else
ScheduleDecay ();
m_ReceivedMessages.insert (msgID); m_ReceivedMessages.insert (msgID);
m_LastMessageReceivedTime = i2p::util::GetSecondsSinceEpoch ();
if (!msg->IsExpired ()) if (!msg->IsExpired ())
m_Handler.PutNextMessage (msg); m_Handler.PutNextMessage (msg);
else else
@ -448,7 +444,7 @@ namespace transport
it->second->numResends++; it->second->numResends++;
it->second->nextResendTime += it->second->numResends*RESEND_INTERVAL; it->second->nextResendTime += it->second->numResends*RESEND_INTERVAL;
it++; ++it;
} }
else else
{ {
@ -457,7 +453,7 @@ namespace transport
} }
} }
else else
it++; ++it;
} }
if (numResent < MAX_OUTGOING_WINDOW_SIZE) if (numResent < MAX_OUTGOING_WINDOW_SIZE)
ScheduleResend (); 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 () void SSUData::ScheduleIncompleteMessagesCleanup ()
{ {
m_IncompleteMessagesCleanupTimer.cancel (); m_IncompleteMessagesCleanupTimer.cancel ();
@ -506,8 +487,13 @@ namespace transport
it = m_IncompleteMessages.erase (it); it = m_IncompleteMessages.erase (it);
} }
else else
it++; ++it;
} }
// decay
if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES ||
i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL)
m_ReceivedMessages.clear ();
ScheduleIncompleteMessagesCleanup (); ScheduleIncompleteMessagesCleanup ();
} }
} }

10
SSUData.h

@ -5,7 +5,7 @@
#include <string.h> #include <string.h>
#include <map> #include <map>
#include <vector> #include <vector>
#include <set> #include <unordered_set>
#include <memory> #include <memory>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "I2NPProtocol.h" #include "I2NPProtocol.h"
@ -109,9 +109,6 @@ namespace transport
void ScheduleResend (); void ScheduleResend ();
void HandleResendTimer (const boost::system::error_code& ecode); void HandleResendTimer (const boost::system::error_code& ecode);
void ScheduleDecay ();
void HandleDecayTimer (const boost::system::error_code& ecode);
void ScheduleIncompleteMessagesCleanup (); void ScheduleIncompleteMessagesCleanup ();
void HandleIncompleteMessagesCleanupTimer (const boost::system::error_code& ecode); void HandleIncompleteMessagesCleanupTimer (const boost::system::error_code& ecode);
@ -121,10 +118,11 @@ namespace transport
SSUSession& m_Session; SSUSession& m_Session;
std::map<uint32_t, std::unique_ptr<IncompleteMessage> > m_IncompleteMessages; std::map<uint32_t, std::unique_ptr<IncompleteMessage> > m_IncompleteMessages;
std::map<uint32_t, std::unique_ptr<SentMessage> > m_SentMessages; std::map<uint32_t, std::unique_ptr<SentMessage> > m_SentMessages;
std::set<uint32_t> m_ReceivedMessages; std::unordered_set<uint32_t> m_ReceivedMessages;
boost::asio::deadline_timer m_ResendTimer, m_DecayTimer, m_IncompleteMessagesCleanupTimer; boost::asio::deadline_timer m_ResendTimer, m_IncompleteMessagesCleanupTimer;
int m_MaxPacketSize, m_PacketSize; int m_MaxPacketSize, m_PacketSize;
i2p::I2NPMessagesHandler m_Handler; i2p::I2NPMessagesHandler m_Handler;
uint32_t m_LastMessageReceivedTime; // in second
}; };
} }
} }

9
SSUSession.cpp

@ -12,7 +12,8 @@ namespace i2p
namespace transport namespace transport
{ {
SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint,
std::shared_ptr<const i2p::data::RouterInfo> router, bool peerTest ): TransportSession (router), std::shared_ptr<const i2p::data::RouterInfo> router, bool peerTest ):
TransportSession (router, SSU_TERMINATION_TIMEOUT),
m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_Timer (GetService ()), m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_Timer (GetService ()),
m_IsPeerTest (peerTest),m_State (eSessionStateUnknown), m_IsSessionKey (false), m_IsPeerTest (peerTest),m_State (eSessionStateUnknown), m_IsSessionKey (false),
m_RelayTag (0),m_Data (*this), m_IsDataReceived (false) m_RelayTag (0),m_Data (*this), m_IsDataReceived (false)
@ -882,7 +883,7 @@ namespace transport
void SSUSession::ScheduleTermination () void SSUSession::ScheduleTermination ()
{ {
m_Timer.cancel (); 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, m_Timer.async_wait (std::bind (&SSUSession::HandleTerminationTimer,
shared_from_this (), std::placeholders::_1)); shared_from_this (), std::placeholders::_1));
} }
@ -891,7 +892,7 @@ namespace transport
{ {
if (ecode != boost::asio::error::operation_aborted) 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 (); Failed ();
} }
} }
@ -906,7 +907,7 @@ namespace transport
{ {
if (m_State == eSessionStateEstablished) if (m_State == eSessionStateEstablished)
{ {
for (auto it: msgs) for (const auto& it: msgs)
if (it) m_Data.Send (it); if (it) m_Data.Send (it);
} }
} }

14
Streaming.cpp

@ -263,7 +263,7 @@ namespace stream
if (nacked) if (nacked)
{ {
LogPrint (eLogDebug, "Streaming: Packet ", seqn, " NACK"); LogPrint (eLogDebug, "Streaming: Packet ", seqn, " NACK");
it++; ++it;
continue; continue;
} }
} }
@ -412,7 +412,7 @@ namespace stream
} }
bool isEmpty = m_SentPackets.empty (); bool isEmpty = m_SentPackets.empty ();
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto it: packets) for (auto& it: packets)
{ {
it->sendTime = ts; it->sendTime = ts;
m_SentPackets.insert (it); m_SentPackets.insert (it);
@ -762,7 +762,7 @@ namespace stream
bool updated = false; bool updated = false;
if (expired && m_CurrentRemoteLease) if (expired && m_CurrentRemoteLease)
{ {
for (auto it: leases) for (const auto& it: leases)
if ((it->tunnelGateway == m_CurrentRemoteLease->tunnelGateway) && (it->tunnelID != m_CurrentRemoteLease->tunnelID)) if ((it->tunnelGateway == m_CurrentRemoteLease->tunnelGateway) && (it->tunnelID != m_CurrentRemoteLease->tunnelID))
{ {
m_CurrentRemoteLease = it; m_CurrentRemoteLease = it;
@ -798,7 +798,7 @@ namespace stream
StreamingDestination::~StreamingDestination () StreamingDestination::~StreamingDestination ()
{ {
for (auto it: m_SavedPackets) for (auto& it: m_SavedPackets)
{ {
for (auto it1: it.second) delete it1; for (auto it1: it.second) delete it1;
it.second.clear (); it.second.clear ();
@ -877,7 +877,7 @@ namespace stream
else // follow on packet without SYN else // follow on packet without SYN
{ {
uint32_t receiveStreamID = packet->GetReceiveStreamID (); uint32_t receiveStreamID = packet->GetReceiveStreamID ();
for (auto it: m_Streams) for (auto& it: m_Streams)
if (it.second->GetSendStreamID () == receiveStreamID) if (it.second->GetSendStreamID () == receiveStreamID)
{ {
// found // found
@ -944,7 +944,7 @@ namespace stream
m_Owner->GetService ().post([acceptor, this](void) m_Owner->GetService ().post([acceptor, this](void)
{ {
m_Acceptor = acceptor; m_Acceptor = acceptor;
for (auto it: m_PendingIncomingStreams) for (auto& it: m_PendingIncomingStreams)
if (it->GetStatus () == eStreamStatusOpen) // still open? if (it->GetStatus () == eStreamStatusOpen) // still open?
m_Acceptor (it); m_Acceptor (it);
m_PendingIncomingStreams.clear (); m_PendingIncomingStreams.clear ();
@ -963,7 +963,7 @@ namespace stream
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
LogPrint (eLogWarning, "Streaming: Pending incoming timeout expired"); LogPrint (eLogWarning, "Streaming: Pending incoming timeout expired");
for (auto it: m_PendingIncomingStreams) for (auto& it: m_PendingIncomingStreams)
it->Close (); it->Close ();
m_PendingIncomingStreams.clear (); m_PendingIncomingStreams.clear ();
} }

8
TransportSession.h

@ -53,8 +53,8 @@ namespace transport
{ {
public: public:
TransportSession (std::shared_ptr<const i2p::data::RouterInfo> router): TransportSession (std::shared_ptr<const i2p::data::RouterInfo> router, int terminationTimeout):
m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router) m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout)
{ {
if (router) if (router)
m_RemoteIdentity = router->GetRouterIdentity (); m_RemoteIdentity = router->GetRouterIdentity ();
@ -70,6 +70,9 @@ namespace transport
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
bool IsOutgoing () const { return m_IsOutgoing; }; 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<std::shared_ptr<I2NPMessage> >& msgs) = 0; virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
protected: protected:
@ -78,6 +81,7 @@ namespace transport
std::shared_ptr<i2p::crypto::DHKeys> m_DHKeysPair; // X - for client and Y - for server std::shared_ptr<i2p::crypto::DHKeys> m_DHKeysPair; // X - for client and Y - for server
size_t m_NumSentBytes, m_NumReceivedBytes; size_t m_NumSentBytes, m_NumReceivedBytes;
bool m_IsOutgoing; bool m_IsOutgoing;
int m_TerminationTimeout;
}; };
} }
} }

12
Transports.cpp

@ -112,7 +112,7 @@ namespace transport
m_Thread = new std::thread (std::bind (&Transports::Run, this)); m_Thread = new std::thread (std::bind (&Transports::Run, this));
// create acceptors // create acceptors
auto& addresses = context.GetRouterInfo ().GetAddresses (); auto& addresses = context.GetRouterInfo ().GetAddresses ();
for (auto address : addresses) for (const auto& address : addresses)
{ {
if (m_NTCPServer == nullptr && enableNTCP) if (m_NTCPServer == nullptr && enableNTCP)
{ {
@ -236,7 +236,7 @@ namespace transport
if (ident == i2p::context.GetRouterInfo ().GetIdentHash ()) if (ident == i2p::context.GetRouterInfo ().GetIdentHash ())
{ {
// we send it to ourself // we send it to ourself
for (auto it: msgs) for (auto& it: msgs)
i2p::HandleI2NPMessage (it); i2p::HandleI2NPMessage (it);
return; return;
} }
@ -266,7 +266,7 @@ namespace transport
{ {
if (it->second.delayedMessages.size () < MAX_NUM_DELAYED_MESSAGES) if (it->second.delayedMessages.size () < MAX_NUM_DELAYED_MESSAGES)
{ {
for (auto it1: msgs) for (auto& it1: msgs)
it->second.delayedMessages.push_back (it1); it->second.delayedMessages.push_back (it1);
} }
else else
@ -569,6 +569,8 @@ namespace transport
} }
if (sendDatabaseStore) if (sendDatabaseStore)
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); 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); it->second.sessions.push_back (session);
session->SendI2NPMessages (it->second.delayedMessages); session->SendI2NPMessages (it->second.delayedMessages);
it->second.delayedMessages.clear (); it->second.delayedMessages.clear ();
@ -634,7 +636,7 @@ namespace transport
it = m_Peers.erase (it); it = m_Peers.erase (it);
} }
else else
it++; ++it;
} }
UpdateBandwidth (); // TODO: use separate timer(s) for it UpdateBandwidth (); // TODO: use separate timer(s) for it
if (i2p::context.GetStatus () == eRouterStatusTesting) // if still testing, repeat peer test if (i2p::context.GetStatus () == eRouterStatusTesting) // if still testing, repeat peer test
@ -656,7 +658,7 @@ namespace transport
{ {
std::lock_guard<std::mutex> lock(m_FamilyMutex); std::lock_guard<std::mutex> lock(m_FamilyMutex);
m_TrustedFamilies.clear(); m_TrustedFamilies.clear();
for ( auto fam : families ) for ( const auto& fam : families )
m_TrustedFamilies.push_back(fam); m_TrustedFamilies.push_back(fam);
} }

2
Transports.h

@ -60,7 +60,7 @@ namespace transport
void Done () void Done ()
{ {
for (auto it: sessions) for (auto& it: sessions)
it->Done (); it->Done ();
} }
}; };

26
Tunnel.cpp

@ -186,7 +186,7 @@ namespace tunnel
{ {
for (auto& it: m_Hops) for (auto& it: m_Hops)
{ {
s << " "; s << " &#8658; ";
s << i2p::data::GetIdentHashAbbreviation (it->ident->GetIdentHash ()); s << i2p::data::GetIdentHashAbbreviation (it->ident->GetIdentHash ());
} }
} }
@ -203,7 +203,7 @@ namespace tunnel
void InboundTunnel::Print (std::stringstream& s) const void InboundTunnel::Print (std::stringstream& s) const
{ {
PrintHops (s); PrintHops (s);
s << " " << GetTunnelID () << ":me"; s << " &#8658; " << GetTunnelID () << ":me";
} }
ZeroHopsInboundTunnel::ZeroHopsInboundTunnel (): ZeroHopsInboundTunnel::ZeroHopsInboundTunnel ():
@ -224,7 +224,7 @@ namespace tunnel
void ZeroHopsInboundTunnel::Print (std::stringstream& s) const void ZeroHopsInboundTunnel::Print (std::stringstream& s) const
{ {
s << " " << GetTunnelID () << ":me"; s << " &#8658; " << GetTunnelID () << ":me";
} }
void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg) void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg)
@ -265,7 +265,7 @@ namespace tunnel
{ {
s << GetTunnelID () << ":me"; s << GetTunnelID () << ":me";
PrintHops (s); PrintHops (s);
s << " "; s << " &#8658; ";
} }
ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel (): ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel ():
@ -297,7 +297,7 @@ namespace tunnel
void ZeroHopsOutboundTunnel::Print (std::stringstream& s) const void ZeroHopsOutboundTunnel::Print (std::stringstream& s) const
{ {
s << GetTunnelID () << ":me "; s << GetTunnelID () << ":me &#8658; ";
} }
Tunnels tunnels; Tunnels tunnels;
@ -345,7 +345,7 @@ namespace tunnel
{ {
std::shared_ptr<InboundTunnel> tunnel; std::shared_ptr<InboundTunnel> tunnel;
size_t minReceived = 0; size_t minReceived = 0;
for (auto it : m_InboundTunnels) for (const auto& it : m_InboundTunnels)
{ {
if (!it->IsEstablished ()) continue; if (!it->IsEstablished ()) continue;
if (!tunnel || it->GetNumReceivedBytes () < minReceived) if (!tunnel || it->GetNumReceivedBytes () < minReceived)
@ -362,7 +362,7 @@ namespace tunnel
if (m_OutboundTunnels.empty ()) return nullptr; if (m_OutboundTunnels.empty ()) return nullptr;
uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0; uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0;
std::shared_ptr<OutboundTunnel> tunnel; std::shared_ptr<OutboundTunnel> tunnel;
for (auto it: m_OutboundTunnels) for (const auto& it: m_OutboundTunnels)
{ {
if (it->IsEstablished ()) if (it->IsEstablished ())
{ {
@ -586,7 +586,7 @@ namespace tunnel
m_NumFailedTunnelCreations++; m_NumFailedTunnelCreations++;
} }
else else
it++; ++it;
break; break;
case eTunnelStateBuildFailed: case eTunnelStateBuildFailed:
LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " failed, deleted"); LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " failed, deleted");
@ -595,7 +595,7 @@ namespace tunnel
break; break;
case eTunnelStateBuildReplyReceived: case eTunnelStateBuildReplyReceived:
// intermediate state, will be either established of build failed // intermediate state, will be either established of build failed
it++; ++it;
break; break;
default: default:
// success // success
@ -635,7 +635,7 @@ namespace tunnel
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
tunnel->SetState (eTunnelStateExpiring); tunnel->SetState (eTunnelStateExpiring);
} }
it++; ++it;
} }
} }
} }
@ -738,9 +738,8 @@ namespace tunnel
void Tunnels::ManageTunnelPools () void Tunnels::ManageTunnelPools ()
{ {
std::unique_lock<std::mutex> l(m_PoolsMutex); std::unique_lock<std::mutex> l(m_PoolsMutex);
for (auto it: m_Pools) for (auto& pool : m_Pools)
{ {
auto pool = it;
if (pool && pool->IsActive ()) if (pool && pool->IsActive ())
{ {
pool->CreateTunnels (); pool->CreateTunnels ();
@ -856,7 +855,7 @@ namespace tunnel
int timeout = 0; int timeout = 0;
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
// TODO: possible race condition with I2PControl // 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; int t = it->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT - ts;
if (t > timeout) timeout = t; if (t > timeout) timeout = t;
@ -883,4 +882,3 @@ namespace tunnel
} }
} }
} }

2
TunnelConfig.h

@ -213,7 +213,7 @@ namespace tunnel
void CreatePeers (const Peers& peers) void CreatePeers (const Peers& peers)
{ {
TunnelHopConfig * prev = nullptr; TunnelHopConfig * prev = nullptr;
for (auto it: peers) for (const auto& it: peers)
{ {
auto hop = new TunnelHopConfig (it); auto hop = new TunnelHopConfig (it);
if (prev) if (prev)

2
TunnelGateway.cpp

@ -197,7 +197,7 @@ namespace tunnel
{ {
m_Buffer.CompleteCurrentTunnelDataMessage (); m_Buffer.CompleteCurrentTunnelDataMessage ();
auto tunnelMsgs = m_Buffer.GetTunnelDataMsgs (); auto tunnelMsgs = m_Buffer.GetTunnelDataMsgs ();
for (auto tunnelMsg : tunnelMsgs) for (auto& tunnelMsg : tunnelMsgs)
{ {
m_Tunnel->EncryptTunnelMsg (tunnelMsg, tunnelMsg); m_Tunnel->EncryptTunnelMsg (tunnelMsg, tunnelMsg);
tunnelMsg->FillI2NPMessageHeader (eI2NPTunnelData); tunnelMsg->FillI2NPMessageHeader (eI2NPTunnelData);

29
TunnelPool.cpp

@ -49,13 +49,13 @@ namespace tunnel
{ {
{ {
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex); std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
for (auto it: m_InboundTunnels) for (auto& it: m_InboundTunnels)
it->SetTunnelPool (nullptr); it->SetTunnelPool (nullptr);
m_InboundTunnels.clear (); m_InboundTunnels.clear ();
} }
{ {
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex); std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
for (auto it: m_OutboundTunnels) for (auto& it: m_OutboundTunnels)
it->SetTunnelPool (nullptr); it->SetTunnelPool (nullptr);
m_OutboundTunnels.clear (); m_OutboundTunnels.clear ();
} }
@ -78,7 +78,7 @@ namespace tunnel
if (expiredTunnel) if (expiredTunnel)
{ {
expiredTunnel->SetTunnelPool (nullptr); expiredTunnel->SetTunnelPool (nullptr);
for (auto it: m_Tests) for (auto& it: m_Tests)
if (it.second.second == expiredTunnel) it.second.second = nullptr; if (it.second.second == expiredTunnel) it.second.second = nullptr;
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex); std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
@ -101,7 +101,7 @@ namespace tunnel
if (expiredTunnel) if (expiredTunnel)
{ {
expiredTunnel->SetTunnelPool (nullptr); expiredTunnel->SetTunnelPool (nullptr);
for (auto it: m_Tests) for (auto& it: m_Tests)
if (it.second.first == expiredTunnel) it.second.first = nullptr; if (it.second.first == expiredTunnel) it.second.first = nullptr;
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex); std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
@ -114,7 +114,7 @@ namespace tunnel
std::vector<std::shared_ptr<InboundTunnel> > v; std::vector<std::shared_ptr<InboundTunnel> > v;
int i = 0; int i = 0;
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex); std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
for (auto it : m_InboundTunnels) for (const auto& it : m_InboundTunnels)
{ {
if (i >= num) break; if (i >= num) break;
if (it->IsEstablished ()) if (it->IsEstablished ())
@ -144,7 +144,7 @@ namespace tunnel
if (tunnels.empty ()) return nullptr; if (tunnels.empty ()) return nullptr;
uint32_t ind = rand () % (tunnels.size ()/2 + 1), i = 0; uint32_t ind = rand () % (tunnels.size ()/2 + 1), i = 0;
typename TTunnels::value_type tunnel = nullptr; typename TTunnels::value_type tunnel = nullptr;
for (auto it: tunnels) for (const auto& it: tunnels)
{ {
if (it->IsEstablished () && it != excluded) if (it->IsEstablished () && it != excluded)
{ {
@ -164,7 +164,7 @@ namespace tunnel
if (old) if (old)
{ {
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex); std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
for (auto it: m_OutboundTunnels) for (const auto& it: m_OutboundTunnels)
if (it->IsEstablished () && old->GetEndpointIdentHash () == it->GetEndpointIdentHash ()) if (it->IsEstablished () && old->GetEndpointIdentHash () == it->GetEndpointIdentHash ())
{ {
tunnel = it; tunnel = it;
@ -182,7 +182,7 @@ namespace tunnel
int num = 0; int num = 0;
{ {
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex); std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
for (auto it : m_InboundTunnels) for (const auto& it : m_InboundTunnels)
if (it->IsEstablished ()) num++; if (it->IsEstablished ()) num++;
} }
for (int i = num; i < m_NumInboundTunnels; i++) for (int i = num; i < m_NumInboundTunnels; i++)
@ -191,7 +191,7 @@ namespace tunnel
num = 0; num = 0;
{ {
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex); std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
for (auto it : m_OutboundTunnels) for (const auto& it : m_OutboundTunnels)
if (it->IsEstablished ()) num++; if (it->IsEstablished ()) num++;
} }
for (int i = num; i < m_NumOutboundTunnels; i++) for (int i = num; i < m_NumOutboundTunnels; i++)
@ -203,11 +203,10 @@ namespace tunnel
decltype(m_Tests) tests; decltype(m_Tests) tests;
{ {
std::unique_lock<std::mutex> l(m_TestsMutex); std::unique_lock<std::mutex> l(m_TestsMutex);
tests = m_Tests; tests.swap(m_Tests);
m_Tests.clear ();
} }
for (auto it: tests) for (auto& it: tests)
{ {
LogPrint (eLogWarning, "Tunnels: test of tunnel ", it.first, " failed"); LogPrint (eLogWarning, "Tunnels: test of tunnel ", it.first, " failed");
// if test failed again with another tunnel we consider it failed // if test failed again with another tunnel we consider it failed
@ -248,12 +247,12 @@ namespace tunnel
if ((*it1)->IsFailed ()) if ((*it1)->IsFailed ())
{ {
failed = true; failed = true;
it1++; ++it1;
} }
if ((*it2)->IsFailed ()) if ((*it2)->IsFailed ())
{ {
failed = true; failed = true;
it2++; ++it2;
} }
if (!failed) if (!failed)
{ {
@ -265,7 +264,7 @@ namespace tunnel
} }
(*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), (*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (),
CreateDeliveryStatusMsg (msgID)); CreateDeliveryStatusMsg (msgID));
it1++; it2++; ++it1; ++it2;
} }
} }
} }

15
UPnP.cpp

@ -49,7 +49,9 @@ namespace transport
m_IsRunning = true; m_IsRunning = true;
LogPrint(eLogInfo, "UPnP: starting"); LogPrint(eLogInfo, "UPnP: starting");
m_Service.post (std::bind (&UPnP::Discover, this)); m_Service.post (std::bind (&UPnP::Discover, this));
std::unique_lock<std::mutex> l(m_StartedMutex);
m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this))); 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 () UPnP::~UPnP ()
@ -80,6 +82,11 @@ namespace transport
#else #else
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror); m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror);
#endif #endif
{
// notify satrting thread
std::unique_lock<std::mutex> l(m_StartedMutex);
m_Started.notify_all ();
}
int r; int r;
r = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr)); r = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
@ -115,8 +122,8 @@ namespace transport
void UPnP::PortMapping () void UPnP::PortMapping ()
{ {
auto a = context.GetRouterInfo().GetAddresses(); const auto& a = context.GetRouterInfo().GetAddresses();
for (auto address : a) for (const auto& address : a)
{ {
if (!address->host.is_v6 ()) if (!address->host.is_v6 ())
TryPortMapping (address); TryPortMapping (address);
@ -132,8 +139,8 @@ namespace transport
void UPnP::CloseMapping () void UPnP::CloseMapping ()
{ {
auto a = context.GetRouterInfo().GetAddresses(); const auto& a = context.GetRouterInfo().GetAddresses();
for (auto address : a) for (const auto& address : a)
{ {
if (!address->host.is_v6 ()) if (!address->host.is_v6 ())
CloseMapping (address); CloseMapping (address);

6
UPnP.h

@ -4,6 +4,8 @@
#ifdef USE_UPNP #ifdef USE_UPNP
#include <string> #include <string>
#include <thread> #include <thread>
#include <condition_variable>
#include <mutex>
#include <memory> #include <memory>
#include <miniupnpc/miniwget.h> #include <miniupnpc/miniwget.h>
@ -13,8 +15,6 @@
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "util.h"
namespace i2p namespace i2p
{ {
namespace transport namespace transport
@ -45,6 +45,8 @@ namespace transport
bool m_IsRunning; bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread; std::unique_ptr<std::thread> m_Thread;
std::condition_variable m_Started;
std::mutex m_StartedMutex;
boost::asio::io_service m_Service; boost::asio::io_service m_Service;
boost::asio::deadline_timer m_Timer; boost::asio::deadline_timer m_Timer;
struct UPNPUrls m_upnpUrls; struct UPNPUrls m_upnpUrls;

29
Win32/Win32App.cpp

@ -2,6 +2,7 @@
#include <windows.h> #include <windows.h>
#include <shellapi.h> #include <shellapi.h>
#include "../Config.h" #include "../Config.h"
#include "../RouterContext.h"
#include "../version.h" #include "../version.h"
#include "resource.h" #include "resource.h"
#include "Win32App.h" #include "Win32App.h"
@ -15,10 +16,13 @@
#define ID_EXIT 2001 #define ID_EXIT 2001
#define ID_CONSOLE 2002 #define ID_CONSOLE 2002
#define ID_APP 2003 #define ID_APP 2003
#define ID_GRACEFUL_SHUTDOWN 2004
#define ID_TRAY_ICON 2050 #define ID_TRAY_ICON 2050
#define WM_TRAYICON (WM_USER + 1) #define WM_TRAYICON (WM_USER + 1)
#define IDT_GRACEFUL_SHUTDOWN_TIMER 2100
namespace i2p namespace i2p
{ {
namespace win32 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_APP, "Show app");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About..."); 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_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"); InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit");
SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE); SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE);
SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0); SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);
@ -82,6 +87,7 @@ namespace win32
case WM_CLOSE: case WM_CLOSE:
{ {
RemoveTrayIcon (hWnd); RemoveTrayIcon (hWnd);
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
PostQuitMessage (0); PostQuitMessage (0);
break; break;
} }
@ -101,6 +107,12 @@ namespace win32
PostMessage (hWnd, WM_CLOSE, 0, 0); PostMessage (hWnd, WM_CLOSE, 0, 0);
return 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: case ID_CONSOLE:
{ {
char buf[30]; char buf[30];
@ -167,6 +179,15 @@ namespace win32
} }
break; 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); return DefWindowProc( hWnd, uMsg, wParam, lParam);
} }
@ -218,5 +239,13 @@ namespace win32
{ {
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL)); 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;
}
} }
} }

1
Win32/Win32App.h

@ -10,6 +10,7 @@ namespace win32
bool StartWin32App (); bool StartWin32App ();
void StopWin32App (); void StopWin32App ();
int RunWin32App (); int RunWin32App ();
bool GracefulShutdown ();
} }
} }
#endif // WIN32APP_H__ #endif // WIN32APP_H__

5
debian/patches/01-tune-build-opts.patch vendored

@ -1,14 +1,15 @@
diff --git a/Makefile b/Makefile diff --git a/Makefile b/Makefile
index fe8ae7e..fc8abda 100644 index 7d04ba0..33ee184 100644
--- a/Makefile --- a/Makefile
+++ b/Makefile +++ b/Makefile
@@ -9,9 +9,9 @@ DEPS := obj/make.dep @@ -9,10 +9,10 @@ DEPS := obj/make.dep
include filelist.mk include filelist.mk
-USE_AESNI := yes -USE_AESNI := yes
+USE_AESNI := no +USE_AESNI := no
USE_STATIC := no USE_STATIC := no
USE_MESHNET := no
-USE_UPNP := no -USE_UPNP := no
+USE_UPNP := yes +USE_UPNP := yes

39
docs/build_notes_android.md

@ -1,6 +1,8 @@
Building on Android Building on Android
=================== ===================
There are two versions: with QT and without QT.
Pre-requesties 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) - [SDK](https://developer.android.com/studio/index.html) (choose command line tools only)
- [NDK](https://developer.android.com/ndk/downloads/index.html) - [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. You also need Java JDK and Ant.
QT-Creator QT-Creator (for QT only)
---------- ------------------------
Open QT-creator that should be installed with QT. Open QT-creator that should be installed with QT.
Go to Settings/Anndroid and specify correct paths to SDK and NDK. Go to Settings/Anndroid and specify correct paths to SDK and NDK.
If everything is correct you will see two set avaiable: If everything is correct you will see two set avaiable:
@ -30,11 +32,26 @@ git clone https://github.com/PurpleI2P/android-ifaddrs.git
``` ```
Building the app Building the app with QT
---------------- ------------------------
- Open qt/i2pd_qt/i2pd_qt.pro in the QT-creator. - 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. - 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. - Select appropriate project (usually armeabi-v7a) and build
- You will find an .apk file in android-build/bin folder. - 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=<path to SDK>' and 'ndk.dir=<path to NDK>'
- 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'

2
docs/build_notes_unix.md

@ -23,7 +23,7 @@ After successfull build i2pd could be installed with:
```bash ```bash
make install 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 ```bash
git clone https://github.com/PurpleI2P/i2pd.git git clone https://github.com/PurpleI2P/i2pd.git

10
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 e.g. C:\dev\miniupnpc . You may want to remove version number from
folder name included in downloaded archive. 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 You can also install it through the MSYS2
and build with USE_UPNP key. and build with USE_UPNP key.
```bash ```bash
pacman -S mingw-w64-i686-miniupnpc 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 ### Creating Visual Studio project

4
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.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 * --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 * --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 * --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, # * 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 # if set and file missing, keys will be generated and placed to this file
# * address -- local interface to bind # * 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] [IRC]
type = client type = client
address = 127.0.0.1 address = 127.0.0.1

4
filelist.mk

@ -5,7 +5,7 @@ LIB_SRC = \
SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \ SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \
Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \ Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \
Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.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 = \ LIB_CLIENT_SRC = \
AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \ 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 # also: Daemon{Linux,Win32}.cpp will be added later
DAEMON_SRC = \ DAEMON_SRC = \
HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp Config.cpp i2pd.cpp HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp

159
util.cpp

@ -1,12 +1,7 @@
#include <cstdlib> #include <cstdlib>
#include <string> #include <string>
#include <algorithm>
#include <cctype>
#include <functional>
#include <fstream>
#include <set>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include "util.h" #include "util.h"
#include "Log.h" #include "Log.h"
@ -60,158 +55,6 @@ namespace i2p
{ {
namespace util 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<int,int>(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<int,int>(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<decltype(port_)>(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 namespace net
{ {
#ifdef WIN32 #ifdef WIN32

29
util.h

@ -22,7 +22,6 @@ namespace i2p
{ {
namespace util namespace util
{ {
/** /**
wrapper arround boost::lexical_cast that "never" fails wrapper arround boost::lexical_cast that "never" fails
*/ */
@ -35,34 +34,6 @@ namespace util
} }
} }
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 namespace net
{ {
int GetMTU (const boost::asio::ip::address& localAddress); int GetMTU (const boost::asio::ip::address& localAddress);

2
version.h

@ -7,7 +7,7 @@
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
#define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MAJOR 2
#define I2PD_VERSION_MINOR 8 #define I2PD_VERSION_MINOR 9
#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_MICRO 0
#define I2PD_VERSION_PATCH 0 #define I2PD_VERSION_PATCH 0
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)

Loading…
Cancel
Save