mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 08:30:46 +00:00 
			
		
		
		
	Merge tag 'tags/2.9.0'
This commit is contained in:
		
						commit
						56254e728c
					
				
					 30 changed files with 393 additions and 379 deletions
				
			
		| 
						 | 
					@ -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;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								Config.cpp
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								Config.cpp
									
										
									
									
									
								
							| 
						 | 
					@ -147,12 +147,17 @@ namespace config {
 | 
				
			||||||
#endif	   
 | 
					#endif	   
 | 
				
			||||||
	   "Enable or disable elgamal precomputation table")
 | 
						   "Enable or disable elgamal precomputation table")
 | 
				
			||||||
	  ;
 | 
						  ;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						options_description reseed("Reseed options");	
 | 
				
			||||||
 | 
						reseed.add_options()
 | 
				
			||||||
 | 
						  ("reseed.file", value<std::string>()->default_value(""),  "Path to .su3 file")
 | 
				
			||||||
 | 
						  ;	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  options_description trust("Trust options");
 | 
					  	options_description trust("Trust options");
 | 
				
			||||||
  trust.add_options()
 | 
					  	trust.add_options()
 | 
				
			||||||
    ("trust.enabled", value<bool>()->default_value(false), "enable explicit trust options")
 | 
					      ("trust.enabled", value<bool>()->default_value(false), "enable explicit trust options")
 | 
				
			||||||
    ("trust.family", value<std::string>()->default_value(""), "Router Familiy to trust for first hops")
 | 
					      ("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?");
 | 
					      ("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)	
 | 
				
			||||||
      ;
 | 
					      ;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
				}	
 | 
									}	
 | 
				
			||||||
			});				
 | 
								});				
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 ();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 () << " ⇒ ";
 | 
				
			||||||
			else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
 | 
								else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
 | 
				
			||||||
				s << " ⇒ " << it->GetTunnelID ();
 | 
									s << " ⇒ " << it->GetTunnelID ();
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				s << " ⇒ " << it->GetTunnelID () << " ⇒ ";
 | 
									s << " ⇒ " << it->GetTunnelID () << " ⇒ ";
 | 
				
			||||||
			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 << " ⇒ ";
 | 
				
			||||||
					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 << " ⇒ ";
 | 
				
			||||||
					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 << " ⇒ ";
 | 
				
			||||||
				s << endpoint.address ().to_string () << ":" << endpoint.port ();
 | 
									s << endpoint.address ().to_string () << ":" << endpoint.port ();
 | 
				
			||||||
				if (!it.second->IsOutgoing ()) s << " ⇒ ";
 | 
									if (!it.second->IsOutgoing ()) s << " ⇒ ";
 | 
				
			||||||
				s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
 | 
									s << " [" << 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 << " ⇒ ";
 | 
				
			||||||
				s << endpoint.address ().to_string () << ":" << endpoint.port ();
 | 
									s << endpoint.address ().to_string () << ":" << endpoint.port ();
 | 
				
			||||||
				if (!it.second->IsOutgoing ()) s << " ⇒ ";
 | 
									if (!it.second->IsOutgoing ()) s << " ⇒ ";
 | 
				
			||||||
				s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
 | 
									s << " [" << 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> ⇐ ";
 | 
				
			||||||
			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> ⇒ ";
 | 
				
			||||||
			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)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
			{	
 | 
								{	
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
									
										
									
									
									
								
							
							
						
						
									
										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
									
										
									
									
									
								
							
							
						
						
									
										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
									
										
									
									
									
								
							
							
						
						
									
										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
									
										
									
									
									
								
							
							
						
						
									
										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
									
										
									
									
									
								
							
							
						
						
									
										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
 | 
				
			||||||
	};	
 | 
						};	
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}	
 | 
						}	
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 ();
 | 
				
			||||||
		}	
 | 
							}	
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
									
										
									
									
									
								
							
							
						
						
									
										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 << " ⇒ ";
 | 
				
			||||||
			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 << " ⇒ " << 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 << " ⇒ " << 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 << " ⇒ ";
 | 
				
			||||||
	}	
 | 
						}
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
	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 ⇒ ";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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); 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
									
										
									
									
									
								
							
							
						
						
									
										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
									
								
								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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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   
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue