Browse Source

Merge tag 'tags/2.9.0'

pull/628/head
Jeff Becker 8 years ago
parent
commit
56254e728c
No known key found for this signature in database
GPG Key ID: AB950234D6EA286B
  1. 18
      AddressBook.cpp
  2. 4
      AddressBook.h
  3. 20
      Config.cpp
  4. 9
      Destination.cpp
  5. 2
      Destination.h
  6. 84
      HTTPServer.cpp
  7. 6
      NTCPSession.cpp
  8. 8
      Reseed.cpp
  9. 14
      RouterContext.cpp
  10. 51
      RouterInfo.cpp
  11. 6
      RouterInfo.h
  12. 4
      SAM.cpp
  13. 2
      SAM.h
  14. 42
      SSU.cpp
  15. 44
      SSUData.cpp
  16. 10
      SSUData.h
  17. 2
      SSUSession.cpp
  18. 16
      Streaming.cpp
  19. 10
      Transports.cpp
  20. 2
      Transports.h
  21. 332
      Tunnel.cpp
  22. 2
      TunnelConfig.h
  23. 2
      TunnelGateway.cpp
  24. 29
      TunnelPool.cpp
  25. 8
      UPnP.cpp
  26. 4
      debian/i2pd.default
  27. 39
      docs/build_notes_android.md
  28. 2
      docs/configuration.md
  29. 4
      filelist.mk
  30. 2
      version.h

18
AddressBook.cpp

@ -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");
} }
@ -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;
}; };

20
Config.cpp

@ -147,12 +147,17 @@ namespace config {
#endif #endif
"Enable or disable elgamal precomputation table") "Enable or disable elgamal precomputation table")
; ;
options_description trust("Trust options"); options_description reseed("Reseed options");
trust.add_options() reseed.add_options()
("trust.enabled", value<bool>()->default_value(false), "enable explicit trust options") ("reseed.file", value<std::string>()->default_value(""), "Path to .su3 file")
("trust.family", value<std::string>()->default_value(""), "Router Familiy to trust for first hops") ;
("trust.hidden", value<bool>()->default_value(false), "should we hide our router from other routers?");
options_description trust("Trust options");
trust.add_options()
("trust.enabled", value<bool>()->default_value(false), "enable explicit trust options")
("trust.family", value<std::string>()->default_value(""), "Router Familiy to trust for first hops")
("trust.hidden", value<bool>()->default_value(false), "should we hide our router from other routers?");
m_OptionsDesc m_OptionsDesc
.add(general) .add(general)
@ -166,7 +171,8 @@ namespace config {
.add(i2pcontrol) .add(i2pcontrol)
.add(upnp) .add(upnp)
.add(precomputation) .add(precomputation)
.add(trust) .add(reseed)
.add(trust)
; ;
} }

9
Destination.cpp

@ -501,24 +501,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);
} }
}); });
} }

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 ();

84
HTTPServer.cpp

@ -68,7 +68,7 @@ namespace http {
const char HTTP_PAGE_TUNNELS[] = "tunnels"; const char HTTP_PAGE_TUNNELS[] = "tunnels";
const char HTTP_PAGE_TRANSIT_TUNNELS[] = "transit_tunnels"; const char HTTP_PAGE_TRANSIT_TUNNELS[] = "transit_tunnels";
const char HTTP_PAGE_TRANSPORTS[] = "transports"; const char HTTP_PAGE_TRANSPORTS[] = "transports";
const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations"; const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations";
const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination"; const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination";
const char HTTP_PAGE_SAM_SESSIONS[] = "sam_sessions"; const char HTTP_PAGE_SAM_SESSIONS[] = "sam_sessions";
@ -82,7 +82,7 @@ namespace http {
const char HTTP_COMMAND_SHUTDOWN_CANCEL[] = "shutdown_cancel"; const char HTTP_COMMAND_SHUTDOWN_CANCEL[] = "shutdown_cancel";
const char HTTP_COMMAND_SHUTDOWN_NOW[] = "terminate"; const char HTTP_COMMAND_SHUTDOWN_NOW[] = "terminate";
const char HTTP_COMMAND_RUN_PEER_TEST[] = "run_peer_test"; const char HTTP_COMMAND_RUN_PEER_TEST[] = "run_peer_test";
const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config"; const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config";
const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
const char HTTP_PARAM_ADDRESS[] = "address"; const char HTTP_PARAM_ADDRESS[] = "address";
@ -144,12 +144,14 @@ namespace http {
" <a href=\"/\">Main page</a><br>\r\n<br>\r\n" " <a href=\"/\">Main page</a><br>\r\n<br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_COMMANDS << "\">Router commands</a><br>\r\n" " <a href=\"/?page=" << HTTP_PAGE_COMMANDS << "\">Router commands</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << "\">Local destinations</a><br>\r\n" " <a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << "\">Local destinations</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_LEASESETS << "\">Lease Sets</a><br>\r\n" " <a href=\"/?page=" << HTTP_PAGE_LEASESETS << "\">LeaseSets</a><br>\r\n"
" <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>";
} }
@ -239,9 +241,9 @@ namespace http {
size_t clientTunnelCount = i2p::tunnel::tunnels.CountOutboundTunnels(); size_t clientTunnelCount = i2p::tunnel::tunnels.CountOutboundTunnels();
clientTunnelCount += i2p::tunnel::tunnels.CountInboundTunnels(); clientTunnelCount += i2p::tunnel::tunnels.CountInboundTunnels();
size_t transitTunnelCount = i2p::tunnel::tunnels.CountTransitTunnels(); size_t transitTunnelCount = i2p::tunnel::tunnels.CountTransitTunnels();
s << "<b>Client Tunnels:</b> " << std::to_string(clientTunnelCount) << " "; s << "<b>Client Tunnels:</b> " << std::to_string(clientTunnelCount) << " ";
s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n"; s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n";
} }
void ShowLocalDestinations (std::stringstream& s) void ShowLocalDestinations (std::stringstream& s)
@ -280,18 +282,18 @@ namespace http {
it->Print(s); it->Print(s);
ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ()); ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ());
} }
} }
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 (const 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;
} }
s << "<br>" << std::endl; s << "<br>" << std::endl;
// s << "<br>\r\n<b>Streams:</b><br>\r\n"; // s << "<br>\r\n<b>Streams:</b><br>\r\n";
// for (auto it: dest->GetStreamingDestination ()->GetStreams ()) // for (auto it: dest->GetStreamingDestination ()->GetStreams ())
// { // {
// s << it.first << "->" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetRemoteIdentity ()) << " "; // s << it.first << "->" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetRemoteIdentity ()) << " ";
// s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; // s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
// s << " [out:" << it.second->GetSendQueueSize () << "][in:" << it.second->GetReceiveQueueSize () << "]"; // s << " [out:" << it.second->GetSendQueueSize () << "][in:" << it.second->GetReceiveQueueSize () << "]";
@ -300,7 +302,7 @@ namespace http {
// s << "[Window:" << it.second->GetWindowSize () << "]"; // s << "[Window:" << it.second->GetWindowSize () << "]";
// s << "[Status:" << (int)it.second->GetStatus () << "]"; // s << "[Status:" << (int)it.second->GetStatus () << "]";
// s << "<br>\r\n"<< std::endl; // s << "<br>\r\n"<< std::endl;
// } // }
s << "<br>\r\n<table><caption>Streams</caption><tr>"; s << "<br>\r\n<table><caption>Streams</caption><tr>";
s << "<th>StreamID</th>"; s << "<th>StreamID</th>";
s << "<th>Destination</th>"; s << "<th>Destination</th>";
@ -315,7 +317,7 @@ namespace http {
s << "</tr>"; s << "</tr>";
for (const auto& it: dest->GetAllStreams ()) for (const auto& it: dest->GetAllStreams ())
{ {
s << "<tr>"; s << "<tr>";
s << "<td>" << it->GetSendStreamID () << "</td>"; s << "<td>" << it->GetSendStreamID () << "</td>";
s << "<td>" << i2p::client::context.GetAddressBook ().ToAddress(it->GetRemoteIdentity ()) << "</td>"; s << "<td>" << i2p::client::context.GetAddressBook ().ToAddress(it->GetRemoteIdentity ()) << "</td>";
@ -329,12 +331,12 @@ namespace http {
s << "<td>" << (int)it->GetStatus () << "</td>"; s << "<td>" << (int)it->GetStatus () << "</td>";
s << "</tr><br>\r\n" << std::endl; s << "</tr><br>\r\n" << std::endl;
} }
} }
} }
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)
@ -382,7 +384,7 @@ namespace http {
); );
// end for each lease set // end for each lease set
} }
void ShowTunnels (std::stringstream& s) void ShowTunnels (std::stringstream& s)
{ {
s << "<b>Queue size:</b> " << i2p::tunnel::tunnels.GetQueueSize () << "<br>\r\n"; s << "<b>Queue size:</b> " << i2p::tunnel::tunnels.GetQueueSize () << "<br>\r\n";
@ -399,7 +401,7 @@ namespace http {
ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ()); ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ());
} }
s << "<br>\r\n"; s << "<br>\r\n";
} }
void ShowCommands (std::stringstream& s) void ShowCommands (std::stringstream& s)
{ {
@ -409,7 +411,7 @@ namespace http {
//s << " <a href=\"/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << "\">Reload config</a><br>\r\n"; //s << " <a href=\"/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << "\">Reload config</a><br>\r\n";
if (i2p::context.AcceptsTunnels ()) if (i2p::context.AcceptsTunnels ())
s << " <a href=\"/?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "\">Decline transit tunnels</a><br>\r\n"; s << " <a href=\"/?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "\">Decline transit tunnels</a><br>\r\n";
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)
@ -435,11 +437,11 @@ namespace http {
for (const 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";
} }
} }
@ -449,22 +451,22 @@ namespace http {
s << "<b>Transports:</b><br>\r\n<br>\r\n"; s << "<b>Transports:</b><br>\r\n<br>\r\n";
auto ntcpServer = i2p::transport::transports.GetNTCPServer (); auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
if (ntcpServer) if (ntcpServer)
{ {
s << "<b>NTCP</b><br>\r\n"; s << "<b>NTCP</b><br>\r\n";
for (const 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;
} }
} }
} }
auto ssuServer = i2p::transport::transports.GetSSUServer (); auto ssuServer = i2p::transport::transports.GetSSUServer ();
if (ssuServer) if (ssuServer)
{ {
@ -472,9 +474,9 @@ namespace http {
for (const 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 () << "]";
@ -484,15 +486,15 @@ namespace http {
for (const 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;
} }
} }
} }
void ShowSAMSessions (std::stringstream& s) void ShowSAMSessions (std::stringstream& s)
{ {
auto sam = i2p::client::context.GetSAMBridge (); auto sam = i2p::client::context.GetSAMBridge ();
@ -505,8 +507,8 @@ namespace http {
{ {
s << "<a href=\"/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">"; s << "<a href=\"/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
s << it.first << "</a><br>\r\n" << std::endl; s << it.first << "</a><br>\r\n" << std::endl;
} }
} }
void ShowSAMSession (std::stringstream& s, const std::string& id) void ShowSAMSession (std::stringstream& s, const std::string& id)
{ {
@ -537,8 +539,8 @@ namespace http {
} }
s << " [" << it->GetSocket ().remote_endpoint() << "]"; s << " [" << it->GetSocket ().remote_endpoint() << "]";
s << "<br>\r\n"; s << "<br>\r\n";
} }
} }
void ShowI2PTunnels (std::stringstream& s) void ShowI2PTunnels (std::stringstream& s)
{ {
@ -547,21 +549,21 @@ 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;
} }
s << "<br>\r\n<b>Server Tunnels:</b><br>\r\n<br>\r\n"; s << "<br>\r\n<b>Server Tunnels:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetServerTunnels ()) for (auto& it: i2p::client::context.GetServerTunnels ())
{ {
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;
} }
} }
HTTPConnection::HTTPConnection (std::shared_ptr<boost::asio::ip::tcp::socket> socket): HTTPConnection::HTTPConnection (std::shared_ptr<boost::asio::ip::tcp::socket> socket):
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0) m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0)
@ -734,7 +736,7 @@ namespace http {
Daemon.gracefullShutdownInterval = 10*60; Daemon.gracefullShutdownInterval = 10*60;
#endif #endif
#ifdef WIN32_APP #ifdef WIN32_APP
i2p::win32::GracefulShutdown (); 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);
@ -752,7 +754,7 @@ namespace http {
s << "<a href=\"/?page=commands\">Back to commands list</a><br>\r\n"; s << "<a href=\"/?page=commands\">Back to commands list</a><br>\r\n";
s << "<p>You will be redirected in 5 seconds</b>"; s << "<p>You will be redirected in 5 seconds</b>";
res.add_header("Refresh", "5; url=/?page=commands"); res.add_header("Refresh", "5; url=/?page=commands");
} }
void HTTPConnection::SendReply (HTTPRes& reply, std::string& content) void HTTPConnection::SendReply (HTTPRes& reply, std::string& content)
{ {

6
NTCPSession.cpp

@ -666,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));
@ -716,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
@ -767,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) continue; if (!address) continue;
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP) if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP)

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);

14
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)
{ {

51
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_Caps |= eSSUTesting; m_Addresses->push_back(std::move(addr));
m_Caps |= eSSUIntroducer;
m_Caps |= eSSUTesting;
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,16 +612,16 @@ 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);
return true; return true;
} }
} }
} }
return false; return false;
@ -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;
} }

42
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,23 +551,20 @@ 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 ();
i2p::data::RouterInfo::Introducer introducer;
introducer.iHost = ep.address ();
introducer.iPort = ep.port ();
introducer.iTag = it1->GetRelayTag ();
introducer.iKey = it1->GetIntroKey ();
if (i2p::context.AddIntroducer (introducer))
{ {
auto& ep = it1->GetRemoteEndpoint (); newList.push_back (ep);
i2p::data::RouterInfo::Introducer introducer; if (newList.size () >= SSU_MAX_NUM_INTRODUCERS) break;
introducer.iHost = ep.address (); }
introducer.iPort = ep.port (); }
introducer.iTag = it1->GetRelayTag ();
introducer.iKey = it1->GetIntroKey ();
if (i2p::context.AddIntroducer (introducer))
{
newList.push_back (ep);
if (newList.size () >= SSU_MAX_NUM_INTRODUCERS) break;
}
}
}
} }
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");

44
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
@ -431,12 +427,12 @@ namespace transport
if (ts >= it->second->nextResendTime) if (ts >= it->second->nextResendTime)
{ {
if (it->second->numResends < MAX_NUM_RESENDS) if (it->second->numResends < MAX_NUM_RESENDS)
{ {
for (auto& f: it->second->fragments) for (auto& f: it->second->fragments)
if (f) if (f)
{ {
try try
{ {
m_Session.Send (f->buf, f->len); // resend m_Session.Send (f->buf, f->len); // resend
numResent++; numResent++;
} }
@ -444,11 +440,11 @@ namespace transport
{ {
LogPrint (eLogWarning, "SSU: Can't resend data fragment ", ec.what ()); LogPrint (eLogWarning, "SSU: Can't resend data fragment ", ec.what ());
} }
} }
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
}; };
} }
} }

2
SSUSession.cpp

@ -907,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);
} }
} }

16
Streaming.cpp

@ -247,7 +247,7 @@ namespace stream
} }
int nackCount = packet->GetNACKCount (); int nackCount = packet->GetNACKCount ();
for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();) for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();)
{ {
auto seqn = (*it)->GetSeqn (); auto seqn = (*it)->GetSeqn ();
if (seqn <= ackThrough) if (seqn <= ackThrough)
{ {
@ -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;
} }
} }
@ -417,7 +417,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);
@ -767,7 +767,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;
@ -806,7 +806,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 ();
@ -903,7 +903,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
@ -970,7 +970,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 ();
@ -989,7 +989,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 ();
} }

10
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 (!address) continue; if (!address) continue;
if (m_NTCPServer == nullptr && enableNTCP) if (m_NTCPServer == nullptr && enableNTCP)
@ -237,7 +237,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;
} }
@ -267,7 +267,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
@ -637,7 +637,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
@ -659,7 +659,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 ();
} }
}; };

332
Tunnel.cpp

@ -13,19 +13,19 @@
#include "Tunnel.h" #include "Tunnel.h"
namespace i2p namespace i2p
{ {
namespace tunnel namespace tunnel
{ {
Tunnel::Tunnel (std::shared_ptr<const TunnelConfig> config): Tunnel::Tunnel (std::shared_ptr<const TunnelConfig> config):
TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()), TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()),
m_Config (config), m_Pool (nullptr), m_State (eTunnelStatePending), m_IsRecreated (false) m_Config (config), m_Pool (nullptr), m_State (eTunnelStatePending), m_IsRecreated (false)
{ {
} }
Tunnel::~Tunnel () Tunnel::~Tunnel ()
{ {
} }
void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel) void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel)
{ {
@ -33,7 +33,7 @@ namespace tunnel
int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops; int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops;
auto msg = NewI2NPShortMessage (); auto msg = NewI2NPShortMessage ();
*msg->GetPayload () = numRecords; *msg->GetPayload () = numRecords;
msg->len += numRecords*TUNNEL_BUILD_RECORD_SIZE + 1; msg->len += numRecords*TUNNEL_BUILD_RECORD_SIZE + 1;
// shuffle records // shuffle records
std::vector<int> recordIndicies; std::vector<int> recordIndicies;
@ -56,13 +56,13 @@ namespace tunnel
hop->recordIndex = idx; hop->recordIndex = idx;
i++; i++;
hop = hop->next; hop = hop->next;
} }
// fill up fake records with random data // fill up fake records with random data
for (int i = numHops; i < numRecords; i++) for (int i = numHops; i < numRecords; i++)
{ {
int idx = recordIndicies[i]; int idx = recordIndicies[i];
RAND_bytes (records + idx*TUNNEL_BUILD_RECORD_SIZE, TUNNEL_BUILD_RECORD_SIZE); RAND_bytes (records + idx*TUNNEL_BUILD_RECORD_SIZE, TUNNEL_BUILD_RECORD_SIZE);
} }
// decrypt real records // decrypt real records
i2p::crypto::CBCDecryption decryption; i2p::crypto::CBCDecryption decryption;
@ -73,31 +73,31 @@ namespace tunnel
// decrypt records after current hop // decrypt records after current hop
TunnelHopConfig * hop1 = hop->next; TunnelHopConfig * hop1 = hop->next;
while (hop1) while (hop1)
{ {
decryption.SetIV (hop->replyIV); decryption.SetIV (hop->replyIV);
uint8_t * record = records + hop1->recordIndex*TUNNEL_BUILD_RECORD_SIZE; uint8_t * record = records + hop1->recordIndex*TUNNEL_BUILD_RECORD_SIZE;
decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record); decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record);
hop1 = hop1->next; hop1 = hop1->next;
} }
hop = hop->prev; hop = hop->prev;
} }
msg->FillI2NPMessageHeader (eI2NPVariableTunnelBuild); msg->FillI2NPMessageHeader (eI2NPVariableTunnelBuild);
// send message // send message
if (outboundTunnel) if (outboundTunnel)
outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg); outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg);
else else
i2p::transport::transports.SendMessage (GetNextIdentHash (), msg); i2p::transport::transports.SendMessage (GetNextIdentHash (), msg);
} }
bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len) bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len)
{ {
LogPrint (eLogDebug, "Tunnel: TunnelBuildResponse ", (int)msg[0], " records."); LogPrint (eLogDebug, "Tunnel: TunnelBuildResponse ", (int)msg[0], " records.");
i2p::crypto::CBCDecryption decryption; i2p::crypto::CBCDecryption decryption;
TunnelHopConfig * hop = m_Config->GetLastHop (); TunnelHopConfig * hop = m_Config->GetLastHop ();
while (hop) while (hop)
{ {
decryption.SetKey (hop->replyKey); decryption.SetKey (hop->replyKey);
// decrypt records before and including current hop // decrypt records before and including current hop
TunnelHopConfig * hop1 = hop; TunnelHopConfig * hop1 = hop;
@ -105,22 +105,22 @@ namespace tunnel
{ {
auto idx = hop1->recordIndex; auto idx = hop1->recordIndex;
if (idx >= 0 && idx < msg[0]) if (idx >= 0 && idx < msg[0])
{ {
uint8_t * record = msg + 1 + idx*TUNNEL_BUILD_RECORD_SIZE; uint8_t * record = msg + 1 + idx*TUNNEL_BUILD_RECORD_SIZE;
decryption.SetIV (hop->replyIV); decryption.SetIV (hop->replyIV);
decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record); decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record);
} }
else else
LogPrint (eLogWarning, "Tunnel: hop index ", idx, " is out of range"); LogPrint (eLogWarning, "Tunnel: hop index ", idx, " is out of range");
hop1 = hop1->prev; hop1 = hop1->prev;
} }
hop = hop->prev; hop = hop->prev;
} }
bool established = true; bool established = true;
hop = m_Config->GetFirstHop (); hop = m_Config->GetFirstHop ();
while (hop) while (hop)
{ {
const uint8_t * record = msg + 1 + hop->recordIndex*TUNNEL_BUILD_RECORD_SIZE; const uint8_t * record = msg + 1 + hop->recordIndex*TUNNEL_BUILD_RECORD_SIZE;
uint8_t ret = record[BUILD_RESPONSE_RECORD_RET_OFFSET]; uint8_t ret = record[BUILD_RESPONSE_RECORD_RET_OFFSET];
LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret); LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret);
@ -143,12 +143,12 @@ namespace tunnel
tunnelHop->decryption.SetKeys (hop->layerKey, hop->ivKey); tunnelHop->decryption.SetKeys (hop->layerKey, hop->ivKey);
m_Hops.push_back (std::unique_ptr<TunnelHop>(tunnelHop)); m_Hops.push_back (std::unique_ptr<TunnelHop>(tunnelHop));
hop = hop->prev; hop = hop->prev;
} }
m_Config = nullptr; m_Config = nullptr;
} }
if (established) m_State = eTunnelStateEstablished; if (established) m_State = eTunnelStateEstablished;
return established; return established;
} }
void Tunnel::EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out) void Tunnel::EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out)
{ {
@ -158,20 +158,20 @@ namespace tunnel
{ {
it->decryption.Decrypt (inPayload, outPayload); it->decryption.Decrypt (inPayload, outPayload);
inPayload = outPayload; inPayload = outPayload;
} }
} }
void Tunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg) void Tunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg)
{ {
LogPrint (eLogWarning, "Tunnel: Can't send I2NP messages without delivery instructions"); LogPrint (eLogWarning, "Tunnel: Can't send I2NP messages without delivery instructions");
} }
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > Tunnel::GetPeers () const std::vector<std::shared_ptr<const i2p::data::IdentityEx> > Tunnel::GetPeers () const
{ {
auto peers = GetInvertedPeers (); auto peers = GetInvertedPeers ();
std::reverse (peers.begin (), peers.end ()); std::reverse (peers.begin (), peers.end ());
return peers; return peers;
} }
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > Tunnel::GetInvertedPeers () const std::vector<std::shared_ptr<const i2p::data::IdentityEx> > Tunnel::GetInvertedPeers () const
{ {
@ -179,54 +179,54 @@ namespace tunnel
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > ret; std::vector<std::shared_ptr<const i2p::data::IdentityEx> > ret;
for (auto& it: m_Hops) for (auto& it: m_Hops)
ret.push_back (it->ident); ret.push_back (it->ident);
return ret; return ret;
} }
void Tunnel::PrintHops (std::stringstream& s) const void Tunnel::PrintHops (std::stringstream& s) const
{ {
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 ());
} }
} }
void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr<const I2NPMessage> msg) void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr<const I2NPMessage> msg)
{ {
if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive
auto newMsg = CreateEmptyTunnelDataMsg (); auto newMsg = CreateEmptyTunnelDataMsg ();
EncryptTunnelMsg (msg, newMsg); EncryptTunnelMsg (msg, newMsg);
newMsg->from = shared_from_this (); newMsg->from = shared_from_this ();
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg);
} }
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 ():
InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()), InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
m_NumReceivedBytes (0) m_NumReceivedBytes (0)
{ {
} }
void ZeroHopsInboundTunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg) void ZeroHopsInboundTunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg)
{ {
if (msg) if (msg)
{ {
m_NumReceivedBytes += msg->GetLength (); m_NumReceivedBytes += msg->GetLength ();
msg->from = shared_from_this (); msg->from = shared_from_this ();
HandleI2NPMessage (msg); HandleI2NPMessage (msg);
} }
} }
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)
{ {
TunnelMessageBlock block; TunnelMessageBlock block;
@ -234,28 +234,28 @@ namespace tunnel
{ {
block.hash = gwHash; block.hash = gwHash;
if (gwTunnel) if (gwTunnel)
{ {
block.deliveryType = eDeliveryTypeTunnel; block.deliveryType = eDeliveryTypeTunnel;
block.tunnelID = gwTunnel; block.tunnelID = gwTunnel;
} }
else else
block.deliveryType = eDeliveryTypeRouter; block.deliveryType = eDeliveryTypeRouter;
} }
else else
block.deliveryType = eDeliveryTypeLocal; block.deliveryType = eDeliveryTypeLocal;
block.data = msg; block.data = msg;
SendTunnelDataMsg ({block}); SendTunnelDataMsg ({block});
} }
void OutboundTunnel::SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs) void OutboundTunnel::SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs)
{ {
std::unique_lock<std::mutex> l(m_SendMutex); std::unique_lock<std::mutex> l(m_SendMutex);
for (auto& it : msgs) for (auto& it : msgs)
m_Gateway.PutTunnelDataMsg (it); m_Gateway.PutTunnelDataMsg (it);
m_Gateway.SendBuffer (); m_Gateway.SendBuffer ();
} }
void OutboundTunnel::HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg) void OutboundTunnel::HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg)
{ {
LogPrint (eLogError, "Tunnel: incoming message for outbound tunnel ", GetTunnelID ()); LogPrint (eLogError, "Tunnel: incoming message for outbound tunnel ", GetTunnelID ());
@ -265,9 +265,9 @@ namespace tunnel
{ {
s << GetTunnelID () << ":me"; s << GetTunnelID () << ":me";
PrintHops (s); PrintHops (s);
s << " "; s << " &#8658; ";
} }
ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel (): ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel ():
OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()), OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
m_NumSentBytes (0) m_NumSentBytes (0)
@ -286,30 +286,30 @@ namespace tunnel
case eDeliveryTypeTunnel: case eDeliveryTypeTunnel:
i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data)); i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data));
break; break;
case eDeliveryTypeRouter: case eDeliveryTypeRouter:
i2p::transport::transports.SendMessage (msg.hash, msg.data); i2p::transport::transports.SendMessage (msg.hash, msg.data);
break; break;
default: default:
LogPrint (eLogError, "Tunnel: Unknown delivery type ", (int)msg.deliveryType); LogPrint (eLogError, "Tunnel: Unknown delivery type ", (int)msg.deliveryType);
} }
} }
} }
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;
Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr),
m_NumSuccesiveTunnelCreations (0), m_NumFailedTunnelCreations (0) m_NumSuccesiveTunnelCreations (0), m_NumFailedTunnelCreations (0)
{ {
} }
Tunnels::~Tunnels () Tunnels::~Tunnels ()
{ {
} }
std::shared_ptr<TunnelBase> Tunnels::GetTunnel (uint32_t tunnelID) std::shared_ptr<TunnelBase> Tunnels::GetTunnel (uint32_t tunnelID)
{ {
@ -317,35 +317,35 @@ namespace tunnel
if (it != m_Tunnels.end ()) if (it != m_Tunnels.end ())
return it->second; return it->second;
return nullptr; return nullptr;
} }
std::shared_ptr<InboundTunnel> Tunnels::GetPendingInboundTunnel (uint32_t replyMsgID) std::shared_ptr<InboundTunnel> Tunnels::GetPendingInboundTunnel (uint32_t replyMsgID)
{ {
return GetPendingTunnel (replyMsgID, m_PendingInboundTunnels); return GetPendingTunnel (replyMsgID, m_PendingInboundTunnels);
} }
std::shared_ptr<OutboundTunnel> Tunnels::GetPendingOutboundTunnel (uint32_t replyMsgID) std::shared_ptr<OutboundTunnel> Tunnels::GetPendingOutboundTunnel (uint32_t replyMsgID)
{ {
return GetPendingTunnel (replyMsgID, m_PendingOutboundTunnels); return GetPendingTunnel (replyMsgID, m_PendingOutboundTunnels);
} }
template<class TTunnel> template<class TTunnel>
std::shared_ptr<TTunnel> Tunnels::GetPendingTunnel (uint32_t replyMsgID, const std::map<uint32_t, std::shared_ptr<TTunnel> >& pendingTunnels) std::shared_ptr<TTunnel> Tunnels::GetPendingTunnel (uint32_t replyMsgID, const std::map<uint32_t, std::shared_ptr<TTunnel> >& pendingTunnels)
{ {
auto it = pendingTunnels.find(replyMsgID); auto it = pendingTunnels.find(replyMsgID);
if (it != pendingTunnels.end () && it->second->GetState () == eTunnelStatePending) if (it != pendingTunnels.end () && it->second->GetState () == eTunnelStatePending)
{ {
it->second->SetState (eTunnelStateBuildReplyReceived); it->second->SetState (eTunnelStateBuildReplyReceived);
return it->second; return it->second;
} }
return nullptr; return nullptr;
} }
std::shared_ptr<InboundTunnel> Tunnels::GetNextInboundTunnel () std::shared_ptr<InboundTunnel> Tunnels::GetNextInboundTunnel ()
{ {
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)
@ -353,26 +353,26 @@ namespace tunnel
tunnel = it; tunnel = it;
minReceived = it->GetNumReceivedBytes (); minReceived = it->GetNumReceivedBytes ();
} }
} }
return tunnel; return tunnel;
} }
std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel () std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel ()
{ {
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 ())
{ {
tunnel = it; tunnel = it;
i++; i++;
} }
if (i > ind && tunnel) break; if (i > ind && tunnel) break;
} }
return tunnel; return tunnel;
} }
std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops, std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops,
int numOutboundHops, int numInboundTunnels, int numOutboundTunnels) int numOutboundHops, int numInboundTunnels, int numOutboundTunnels)
@ -381,19 +381,19 @@ namespace tunnel
std::unique_lock<std::mutex> l(m_PoolsMutex); std::unique_lock<std::mutex> l(m_PoolsMutex);
m_Pools.push_back (pool); m_Pools.push_back (pool);
return pool; return pool;
} }
void Tunnels::DeleteTunnelPool (std::shared_ptr<TunnelPool> pool) void Tunnels::DeleteTunnelPool (std::shared_ptr<TunnelPool> pool)
{ {
if (pool) if (pool)
{ {
StopTunnelPool (pool); StopTunnelPool (pool);
{ {
std::unique_lock<std::mutex> l(m_PoolsMutex); std::unique_lock<std::mutex> l(m_PoolsMutex);
m_Pools.remove (pool); m_Pools.remove (pool);
} }
} }
} }
void Tunnels::StopTunnelPool (std::shared_ptr<TunnelPool> pool) void Tunnels::StopTunnelPool (std::shared_ptr<TunnelPool> pool)
{ {
@ -401,47 +401,47 @@ namespace tunnel
{ {
pool->SetActive (false); pool->SetActive (false);
pool->DetachTunnels (); pool->DetachTunnels ();
} }
} }
void Tunnels::AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel) void Tunnels::AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel)
{ {
if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second) if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second)
m_TransitTunnels.push_back (tunnel); m_TransitTunnels.push_back (tunnel);
else else
LogPrint (eLogError, "Tunnel: tunnel with id ", tunnel->GetTunnelID (), " already exists"); LogPrint (eLogError, "Tunnel: tunnel with id ", tunnel->GetTunnelID (), " already exists");
} }
void Tunnels::Start () void Tunnels::Start ()
{ {
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&Tunnels::Run, this)); m_Thread = new std::thread (std::bind (&Tunnels::Run, this));
} }
void Tunnels::Stop () void Tunnels::Stop ()
{ {
m_IsRunning = false; m_IsRunning = false;
m_Queue.WakeUp (); m_Queue.WakeUp ();
if (m_Thread) if (m_Thread)
{ {
m_Thread->join (); m_Thread->join ();
delete m_Thread; delete m_Thread;
m_Thread = 0; m_Thread = 0;
} }
} }
void Tunnels::Run () void Tunnels::Run ()
{ {
std::this_thread::sleep_for (std::chrono::seconds(1)); // wait for other parts are ready std::this_thread::sleep_for (std::chrono::seconds(1)); // wait for other parts are ready
uint64_t lastTs = 0; uint64_t lastTs = 0;
while (m_IsRunning) while (m_IsRunning)
{ {
try try
{ {
auto msg = m_Queue.GetNextWithTimeout (1000); // 1 sec auto msg = m_Queue.GetNextWithTimeout (1000); // 1 sec
if (msg) if (msg)
{ {
uint32_t prevTunnelID = 0, tunnelID = 0; uint32_t prevTunnelID = 0, tunnelID = 0;
std::shared_ptr<TunnelBase> prevTunnel; std::shared_ptr<TunnelBase> prevTunnel;
do do
@ -449,16 +449,16 @@ namespace tunnel
std::shared_ptr<TunnelBase> tunnel; std::shared_ptr<TunnelBase> tunnel;
uint8_t typeID = msg->GetTypeID (); uint8_t typeID = msg->GetTypeID ();
switch (typeID) switch (typeID)
{ {
case eI2NPTunnelData: case eI2NPTunnelData:
case eI2NPTunnelGateway: case eI2NPTunnelGateway:
{ {
tunnelID = bufbe32toh (msg->GetPayload ()); tunnelID = bufbe32toh (msg->GetPayload ());
if (tunnelID == prevTunnelID) if (tunnelID == prevTunnelID)
tunnel = prevTunnel; tunnel = prevTunnel;
else if (prevTunnel) else if (prevTunnel)
prevTunnel->FlushTunnelDataMsgs (); prevTunnel->FlushTunnelDataMsgs ();
if (!tunnel) if (!tunnel)
tunnel = GetTunnel (tunnelID); tunnel = GetTunnel (tunnelID);
if (tunnel) if (tunnel)
@ -472,17 +472,17 @@ namespace tunnel
LogPrint (eLogWarning, "Tunnel: tunnel not found, tunnelID=", tunnelID, " previousTunnelID=", prevTunnelID, " type=", (int)typeID); LogPrint (eLogWarning, "Tunnel: tunnel not found, tunnelID=", tunnelID, " previousTunnelID=", prevTunnelID, " type=", (int)typeID);
break; break;
} }
case eI2NPVariableTunnelBuild: case eI2NPVariableTunnelBuild:
case eI2NPVariableTunnelBuildReply: case eI2NPVariableTunnelBuildReply:
case eI2NPTunnelBuild: case eI2NPTunnelBuild:
case eI2NPTunnelBuildReply: case eI2NPTunnelBuildReply:
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ()); HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
break; break;
default: default:
LogPrint (eLogWarning, "Tunnel: unexpected messsage type ", (int) typeID); LogPrint (eLogWarning, "Tunnel: unexpected messsage type ", (int) typeID);
} }
msg = m_Queue.Get (); msg = m_Queue.Get ();
if (msg) if (msg)
{ {
@ -493,8 +493,8 @@ namespace tunnel
tunnel->FlushTunnelDataMsgs (); tunnel->FlushTunnelDataMsgs ();
} }
while (msg); while (msg);
} }
uint64_t ts = i2p::util::GetSecondsSinceEpoch (); uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
if (ts - lastTs >= 15) // manage tunnels every 15 seconds if (ts - lastTs >= 15) // manage tunnels every 15 seconds
{ {
@ -505,9 +505,9 @@ namespace tunnel
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "Tunnel: runtime exception: ", ex.what ()); LogPrint (eLogError, "Tunnel: runtime exception: ", ex.what ());
} }
} }
} }
void Tunnels::HandleTunnelGatewayMsg (std::shared_ptr<TunnelBase> tunnel, std::shared_ptr<I2NPMessage> msg) void Tunnels::HandleTunnelGatewayMsg (std::shared_ptr<TunnelBase> tunnel, std::shared_ptr<I2NPMessage> msg)
{ {
@ -528,7 +528,7 @@ namespace tunnel
msg->len = msg->offset + len; msg->len = msg->offset + len;
auto typeID = msg->GetTypeID (); auto typeID = msg->GetTypeID ();
LogPrint (eLogDebug, "Tunnel: gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID); LogPrint (eLogDebug, "Tunnel: gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID);
if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply) if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply)
// transit DatabaseStore my contain new/updated RI // transit DatabaseStore my contain new/updated RI
// or DatabaseSearchReply with new routers // or DatabaseSearchReply with new routers
@ -543,7 +543,7 @@ namespace tunnel
ManageOutboundTunnels (); ManageOutboundTunnels ();
ManageTransitTunnels (); ManageTransitTunnels ();
ManageTunnelPools (); ManageTunnelPools ();
} }
void Tunnels::ManagePendingTunnels () void Tunnels::ManagePendingTunnels ()
{ {
@ -557,7 +557,7 @@ namespace tunnel
// check pending tunnel. delete failed or timeout // check pending tunnel. delete failed or timeout
uint64_t ts = i2p::util::GetSecondsSinceEpoch (); uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it = pendingTunnels.begin (); it != pendingTunnels.end ();) for (auto it = pendingTunnels.begin (); it != pendingTunnels.end ();)
{ {
auto tunnel = it->second; auto tunnel = it->second;
switch (tunnel->GetState ()) switch (tunnel->GetState ())
{ {
@ -579,14 +579,14 @@ namespace tunnel
profile->TunnelNonReplied (); profile->TunnelNonReplied ();
} }
hop = hop->next; hop = hop->next;
} }
} }
// delete // delete
it = pendingTunnels.erase (it); it = pendingTunnels.erase (it);
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,14 +595,14 @@ 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
it = pendingTunnels.erase (it); it = pendingTunnels.erase (it);
m_NumSuccesiveTunnelCreations++; m_NumSuccesiveTunnelCreations++;
} }
} }
} }
void Tunnels::ManageOutboundTunnels () void Tunnels::ManageOutboundTunnels ()
@ -620,26 +620,26 @@ namespace tunnel
pool->TunnelExpired (tunnel); pool->TunnelExpired (tunnel);
// we don't have outbound tunnels in m_Tunnels // we don't have outbound tunnels in m_Tunnels
it = m_OutboundTunnels.erase (it); it = m_OutboundTunnels.erase (it);
} }
else else
{ {
if (tunnel->IsEstablished ()) if (tunnel->IsEstablished ())
{ {
if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
{ {
tunnel->SetIsRecreated (); tunnel->SetIsRecreated ();
auto pool = tunnel->GetTunnelPool (); auto pool = tunnel->GetTunnelPool ();
if (pool) if (pool)
pool->RecreateOutboundTunnel (tunnel); pool->RecreateOutboundTunnel (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;
} }
} }
} }
if (m_OutboundTunnels.size () < 5) if (m_OutboundTunnels.size () < 5)
{ {
// trying to create one more oubound tunnel // trying to create one more oubound tunnel
@ -648,12 +648,12 @@ namespace tunnel
if (!inboundTunnel || !router) return; if (!inboundTunnel || !router) return;
LogPrint (eLogDebug, "Tunnel: creating one hop outbound tunnel"); LogPrint (eLogDebug, "Tunnel: creating one hop outbound tunnel");
CreateTunnel<OutboundTunnel> ( CreateTunnel<OutboundTunnel> (
std::make_shared<TunnelConfig> (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > { router->GetRouterIdentity () }, std::make_shared<TunnelConfig> (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > { router->GetRouterIdentity () },
inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()) inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ())
); );
} }
} }
void Tunnels::ManageInboundTunnels () void Tunnels::ManageInboundTunnels ()
{ {
uint64_t ts = i2p::util::GetSecondsSinceEpoch (); uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
@ -669,26 +669,26 @@ namespace tunnel
pool->TunnelExpired (tunnel); pool->TunnelExpired (tunnel);
m_Tunnels.erase (tunnel->GetTunnelID ()); m_Tunnels.erase (tunnel->GetTunnelID ());
it = m_InboundTunnels.erase (it); it = m_InboundTunnels.erase (it);
} }
else else
{ {
if (tunnel->IsEstablished ()) if (tunnel->IsEstablished ())
{ {
if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
{ {
tunnel->SetIsRecreated (); tunnel->SetIsRecreated ();
auto pool = tunnel->GetTunnelPool (); auto pool = tunnel->GetTunnelPool ();
if (pool) if (pool)
pool->RecreateInboundTunnel (tunnel); pool->RecreateInboundTunnel (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++;
} }
} }
} }
if (m_InboundTunnels.empty ()) if (m_InboundTunnels.empty ())
{ {
@ -702,10 +702,10 @@ namespace tunnel
} }
return; return;
} }
if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 5) if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 5)
{ {
// trying to create one more inbound tunnel // trying to create one more inbound tunnel
auto router = i2p::data::netdb.GetRandomRouter (); auto router = i2p::data::netdb.GetRandomRouter ();
if (!router) { if (!router) {
LogPrint (eLogWarning, "Tunnel: can't find any router, skip creating tunnel"); LogPrint (eLogWarning, "Tunnel: can't find any router, skip creating tunnel");
@ -714,9 +714,9 @@ namespace tunnel
LogPrint (eLogDebug, "Tunnel: creating one hop inbound tunnel"); LogPrint (eLogDebug, "Tunnel: creating one hop inbound tunnel");
CreateTunnel<InboundTunnel> ( CreateTunnel<InboundTunnel> (
std::make_shared<TunnelConfig> (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > { router->GetRouterIdentity () }) std::make_shared<TunnelConfig> (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > { router->GetRouterIdentity () })
); );
} }
} }
void Tunnels::ManageTransitTunnels () void Tunnels::ManageTransitTunnels ()
{ {
@ -729,36 +729,35 @@ namespace tunnel
LogPrint (eLogDebug, "Tunnel: Transit tunnel with id ", tunnel->GetTunnelID (), " expired"); LogPrint (eLogDebug, "Tunnel: Transit tunnel with id ", tunnel->GetTunnelID (), " expired");
m_Tunnels.erase (tunnel->GetTunnelID ()); m_Tunnels.erase (tunnel->GetTunnelID ());
it = m_TransitTunnels.erase (it); it = m_TransitTunnels.erase (it);
} }
else else
it++; it++;
} }
} }
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 ();
pool->TestTunnels (); pool->TestTunnels ();
} }
} }
} }
void Tunnels::PostTunnelData (std::shared_ptr<I2NPMessage> msg) void Tunnels::PostTunnelData (std::shared_ptr<I2NPMessage> msg)
{ {
if (msg) m_Queue.Put (msg); if (msg) m_Queue.Put (msg);
} }
void Tunnels::PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) void Tunnels::PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
{ {
m_Queue.Put (msgs); m_Queue.Put (msgs);
} }
template<class TTunnel> template<class TTunnel>
std::shared_ptr<TTunnel> Tunnels::CreateTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel) std::shared_ptr<TTunnel> Tunnels::CreateTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel)
{ {
@ -768,7 +767,7 @@ namespace tunnel
AddPendingTunnel (replyMsgID, newTunnel); AddPendingTunnel (replyMsgID, newTunnel);
newTunnel->Build (replyMsgID, outboundTunnel); newTunnel->Build (replyMsgID, outboundTunnel);
return newTunnel; return newTunnel;
} }
std::shared_ptr<InboundTunnel> Tunnels::CreateInboundTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel) std::shared_ptr<InboundTunnel> Tunnels::CreateInboundTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel)
{ {
@ -805,20 +804,20 @@ namespace tunnel
pool->TunnelCreated (newTunnel); pool->TunnelCreated (newTunnel);
else else
newTunnel->SetTunnelPool (nullptr); newTunnel->SetTunnelPool (nullptr);
} }
void Tunnels::AddInboundTunnel (std::shared_ptr<InboundTunnel> newTunnel) void Tunnels::AddInboundTunnel (std::shared_ptr<InboundTunnel> newTunnel)
{ {
if (m_Tunnels.emplace (newTunnel->GetTunnelID (), newTunnel).second) if (m_Tunnels.emplace (newTunnel->GetTunnelID (), newTunnel).second)
{ {
m_InboundTunnels.push_back (newTunnel); m_InboundTunnels.push_back (newTunnel);
auto pool = newTunnel->GetTunnelPool (); auto pool = newTunnel->GetTunnelPool ();
if (!pool) if (!pool)
{ {
// build symmetric outbound tunnel // build symmetric outbound tunnel
CreateTunnel<OutboundTunnel> (std::make_shared<TunnelConfig>(newTunnel->GetInvertedPeers (), CreateTunnel<OutboundTunnel> (std::make_shared<TunnelConfig>(newTunnel->GetInvertedPeers (),
newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash ()), newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash ()),
GetNextOutboundTunnel ()); GetNextOutboundTunnel ());
} }
else else
{ {
@ -830,9 +829,9 @@ namespace tunnel
} }
else else
LogPrint (eLogError, "Tunnel: tunnel with id ", newTunnel->GetTunnelID (), " already exists"); LogPrint (eLogError, "Tunnel: tunnel with id ", newTunnel->GetTunnelID (), " already exists");
} }
std::shared_ptr<ZeroHopsInboundTunnel> Tunnels::CreateZeroHopsInboundTunnel () std::shared_ptr<ZeroHopsInboundTunnel> Tunnels::CreateZeroHopsInboundTunnel ()
{ {
auto inboundTunnel = std::make_shared<ZeroHopsInboundTunnel> (); auto inboundTunnel = std::make_shared<ZeroHopsInboundTunnel> ();
@ -840,7 +839,7 @@ namespace tunnel
m_InboundTunnels.push_back (inboundTunnel); m_InboundTunnels.push_back (inboundTunnel);
m_Tunnels[inboundTunnel->GetTunnelID ()] = inboundTunnel; m_Tunnels[inboundTunnel->GetTunnelID ()] = inboundTunnel;
return inboundTunnel; return inboundTunnel;
} }
std::shared_ptr<ZeroHopsOutboundTunnel> Tunnels::CreateZeroHopsOutboundTunnel () std::shared_ptr<ZeroHopsOutboundTunnel> Tunnels::CreateZeroHopsOutboundTunnel ()
{ {
@ -856,11 +855,11 @@ 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;
} }
return timeout; return timeout;
} }
@ -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;
} }
} }
} }

8
UPnP.cpp

@ -122,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);
@ -139,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);

4
debian/i2pd.default vendored

@ -4,8 +4,8 @@
I2PD_ENABLED="yes" I2PD_ENABLED="yes"
# port to listen for incoming connections # port to listen for incoming connections
# comment this line if you want to use value from config # uncomment following line if you want to specify it here
I2PD_PORT="4567" # I2PD_PORT="4567"
# Additional options that are passed to the Daemon. # Additional options that are passed to the Daemon.
# see possible switches in /usr/share/doc/i2pd/configuration.md.gz # see possible switches in /usr/share/doc/i2pd/configuration.md.gz

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/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

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

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