mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 00:20:46 +00:00 
			
		
		
		
	atomics have been used for threads stop
This commit is contained in:
		
							parent
							
								
									8c09a7429c
								
							
						
					
					
						commit
						dfa1482ab2
					
				
					 15 changed files with 259 additions and 212 deletions
				
			
		| 
						 | 
					@ -15,7 +15,7 @@ namespace util
 | 
				
			||||||
			virtual bool init(int argc, char* argv[]);
 | 
								virtual bool init(int argc, char* argv[]);
 | 
				
			||||||
			virtual bool start();
 | 
								virtual bool start();
 | 
				
			||||||
			virtual bool stop();
 | 
								virtual bool stop();
 | 
				
			||||||
			virtual void run () {};
 | 
								virtual void run () {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bool isDaemon;
 | 
								bool isDaemon;
 | 
				
			||||||
			bool running;
 | 
								bool running;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -943,44 +943,50 @@ namespace http {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void HTTPServer::Start ()
 | 
						void HTTPServer::Start ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		bool needAuth;    i2p::config::GetOption("http.auth", needAuth);
 | 
							if (!m_IsRunning.load())
 | 
				
			||||||
		std::string user; i2p::config::GetOption("http.user", user);
 | 
							{
 | 
				
			||||||
		std::string pass; i2p::config::GetOption("http.pass", pass);
 | 
								bool needAuth;    i2p::config::GetOption("http.auth", needAuth);
 | 
				
			||||||
		/* generate pass if needed */
 | 
								std::string user; i2p::config::GetOption("http.user", user);
 | 
				
			||||||
		if (needAuth && pass == "") {
 | 
								std::string pass; i2p::config::GetOption("http.pass", pass);
 | 
				
			||||||
			uint8_t random[16];
 | 
								/* generate pass if needed */
 | 
				
			||||||
			char alnum[] = "0123456789"
 | 
								if (needAuth && pass == "") {
 | 
				
			||||||
			  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 | 
									uint8_t random[16];
 | 
				
			||||||
			  "abcdefghijklmnopqrstuvwxyz";
 | 
									char alnum[] = "0123456789"
 | 
				
			||||||
			pass.resize(sizeof(random));
 | 
									  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 | 
				
			||||||
			RAND_bytes(random, sizeof(random));
 | 
									  "abcdefghijklmnopqrstuvwxyz";
 | 
				
			||||||
			for (size_t i = 0; i < sizeof(random); i++) {
 | 
									pass.resize(sizeof(random));
 | 
				
			||||||
				pass[i] = alnum[random[i] % (sizeof(alnum) - 1)];
 | 
									RAND_bytes(random, sizeof(random));
 | 
				
			||||||
 | 
									for (size_t i = 0; i < sizeof(random); i++) {
 | 
				
			||||||
 | 
										pass[i] = alnum[random[i] % (sizeof(alnum) - 1)];
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									i2p::config::SetOption("http.pass", pass);
 | 
				
			||||||
 | 
									LogPrint(eLogInfo, "HTTPServer: password set to ", pass);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			i2p::config::SetOption("http.pass", pass);
 | 
								m_IsRunning.store(true);
 | 
				
			||||||
			LogPrint(eLogInfo, "HTTPServer: password set to ", pass);
 | 
								m_Thread = std::unique_ptr<std::thread>(new std::thread (std::bind (&HTTPServer::Run, this)));
 | 
				
			||||||
 | 
								m_Acceptor.listen ();
 | 
				
			||||||
 | 
								Accept ();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		m_IsRunning = true;
 | 
					 | 
				
			||||||
		m_Thread = std::unique_ptr<std::thread>(new std::thread (std::bind (&HTTPServer::Run, this)));
 | 
					 | 
				
			||||||
		m_Acceptor.listen ();
 | 
					 | 
				
			||||||
		Accept ();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void HTTPServer::Stop ()
 | 
						void HTTPServer::Stop ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_IsRunning = false;
 | 
							if (m_IsRunning.load())
 | 
				
			||||||
		m_Acceptor.close();
 | 
					 | 
				
			||||||
		m_Service.stop ();
 | 
					 | 
				
			||||||
		if (m_Thread)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			m_Thread->join ();
 | 
								m_IsRunning.store(false);
 | 
				
			||||||
			m_Thread = nullptr;
 | 
								m_Acceptor.close();
 | 
				
			||||||
 | 
								m_Service.stop ();
 | 
				
			||||||
 | 
								if (m_Thread)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									m_Thread->join ();
 | 
				
			||||||
 | 
									m_Thread = nullptr;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void HTTPServer::Run ()
 | 
						void HTTPServer::Run ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		while (m_IsRunning)
 | 
							while (m_IsRunning.load(std::memory_order_acquire))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			try
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
#include <boost/asio.hpp>
 | 
					#include <boost/asio.hpp>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
#include "HTTP.h"
 | 
					#include "HTTP.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace i2p 
 | 
					namespace i2p 
 | 
				
			||||||
| 
						 | 
					@ -70,7 +71,7 @@ namespace http
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bool m_IsRunning;
 | 
								std::atomic_bool m_IsRunning;
 | 
				
			||||||
			std::unique_ptr<std::thread> m_Thread;
 | 
								std::unique_ptr<std::thread> m_Thread;
 | 
				
			||||||
			boost::asio::io_service m_Service;
 | 
								boost::asio::io_service m_Service;
 | 
				
			||||||
			boost::asio::io_service::work m_Work;
 | 
								boost::asio::io_service::work m_Work;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,19 +101,19 @@ namespace client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void I2PControlService::Start ()
 | 
						void I2PControlService::Start ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!m_IsRunning)
 | 
							if (!m_IsRunning.load())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Accept ();
 | 
								Accept ();
 | 
				
			||||||
			m_IsRunning = true;
 | 
								m_IsRunning.store(true);
 | 
				
			||||||
			m_Thread = new std::thread (std::bind (&I2PControlService::Run, this));
 | 
								m_Thread = new std::thread (std::bind (&I2PControlService::Run, this));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void I2PControlService::Stop ()
 | 
						void I2PControlService::Stop ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (m_IsRunning)
 | 
							if (m_IsRunning.load())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			m_IsRunning = false;
 | 
								m_IsRunning.store(false);
 | 
				
			||||||
			m_Acceptor.cancel ();
 | 
								m_Acceptor.cancel ();
 | 
				
			||||||
			m_Service.stop ();
 | 
								m_Service.stop ();
 | 
				
			||||||
			if (m_Thread)
 | 
								if (m_Thread)
 | 
				
			||||||
| 
						 | 
					@ -127,7 +127,7 @@ namespace client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void I2PControlService::Run ()
 | 
						void I2PControlService::Run ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		while (m_IsRunning)
 | 
							while (m_IsRunning.load(std::memory_order_acquire))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				m_Service.run ();
 | 
									m_Service.run ();
 | 
				
			||||||
| 
						 | 
					@ -160,7 +160,7 @@ namespace client
 | 
				
			||||||
	void I2PControlService::Handshake (std::shared_ptr<ssl_socket> socket)
 | 
						void I2PControlService::Handshake (std::shared_ptr<ssl_socket> socket)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		socket->async_handshake(boost::asio::ssl::stream_base::server,
 | 
							socket->async_handshake(boost::asio::ssl::stream_base::server,
 | 
				
			||||||
        	std::bind( &I2PControlService::HandleHandshake, this, std::placeholders::_1, socket));
 | 
							std::bind( &I2PControlService::HandleHandshake, this, std::placeholders::_1, socket));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
 | 
						void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
#include <map>
 | 
					#include <map>
 | 
				
			||||||
#include <set>
 | 
					#include <set>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
#include <boost/asio.hpp>
 | 
					#include <boost/asio.hpp>
 | 
				
			||||||
#include <boost/asio/ssl.hpp> 
 | 
					#include <boost/asio/ssl.hpp> 
 | 
				
			||||||
#include <boost/property_tree/ptree.hpp>
 | 
					#include <boost/property_tree/ptree.hpp>
 | 
				
			||||||
| 
						 | 
					@ -101,7 +102,7 @@ namespace client
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string m_Password;
 | 
								std::string m_Password;
 | 
				
			||||||
			bool m_IsRunning;
 | 
								std::atomic_bool m_IsRunning;
 | 
				
			||||||
			std::thread * m_Thread;
 | 
								std::thread * m_Thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			boost::asio::io_service m_Service;
 | 
								boost::asio::io_service m_Service;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,10 +28,10 @@ namespace transport
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void UPnP::Stop ()
 | 
						void UPnP::Stop ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (m_IsRunning)
 | 
							if (m_IsRunning.load())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			LogPrint(eLogInfo, "UPnP: stopping");
 | 
								LogPrint(eLogInfo, "UPnP: stopping");
 | 
				
			||||||
			m_IsRunning = false;
 | 
								m_IsRunning.store(false);
 | 
				
			||||||
			m_Timer.cancel ();
 | 
								m_Timer.cancel ();
 | 
				
			||||||
			m_Service.stop ();
 | 
								m_Service.stop ();
 | 
				
			||||||
			if (m_Thread)
 | 
								if (m_Thread)
 | 
				
			||||||
| 
						 | 
					@ -46,12 +46,15 @@ namespace transport
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void UPnP::Start()
 | 
						void UPnP::Start()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_IsRunning = true;
 | 
							if (!m_IsRunning.load())
 | 
				
			||||||
		LogPrint(eLogInfo, "UPnP: starting");
 | 
							{
 | 
				
			||||||
		m_Service.post (std::bind (&UPnP::Discover, this));
 | 
								m_IsRunning.store(true);
 | 
				
			||||||
		std::unique_lock<std::mutex> l(m_StartedMutex);
 | 
								LogPrint(eLogInfo, "UPnP: starting");
 | 
				
			||||||
		m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this)));
 | 
								m_Service.post (std::bind (&UPnP::Discover, this));
 | 
				
			||||||
		m_Started.wait_for (l, std::chrono::seconds (5)); // 5 seconds maximum
 | 
								std::unique_lock<std::mutex> l(m_StartedMutex);
 | 
				
			||||||
 | 
								m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this)));
 | 
				
			||||||
 | 
								m_Started.wait_for (l, std::chrono::seconds (5)); // 5 seconds maximum
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	UPnP::~UPnP ()
 | 
						UPnP::~UPnP ()
 | 
				
			||||||
| 
						 | 
					@ -61,7 +64,7 @@ namespace transport
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void UPnP::Run ()
 | 
						void UPnP::Run ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		while (m_IsRunning)
 | 
							while (m_IsRunning.load(std::memory_order_acquire))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			try
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@
 | 
				
			||||||
#include <condition_variable>
 | 
					#include <condition_variable>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <miniupnpc/miniwget.h>
 | 
					#include <miniupnpc/miniwget.h>
 | 
				
			||||||
#include <miniupnpc/miniupnpc.h>
 | 
					#include <miniupnpc/miniupnpc.h>
 | 
				
			||||||
| 
						 | 
					@ -43,8 +44,8 @@ namespace transport
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
		bool m_IsRunning;
 | 
							std::atomic_bool m_IsRunning;
 | 
				
			||||||
        std::unique_ptr<std::thread> m_Thread;
 | 
							std::unique_ptr<std::thread> m_Thread;
 | 
				
			||||||
		std::condition_variable m_Started;	
 | 
							std::condition_variable m_Started;	
 | 
				
			||||||
		std::mutex m_StartedMutex;	
 | 
							std::mutex m_StartedMutex;	
 | 
				
			||||||
		boost::asio::io_service m_Service;
 | 
							boost::asio::io_service m_Service;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace i2p {
 | 
					namespace i2p {
 | 
				
			||||||
namespace log {
 | 
					namespace log {
 | 
				
			||||||
	static Log logger;
 | 
					 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @brief Maps our loglevel to their symbolic name
 | 
						 * @brief Maps our loglevel to their symbolic name
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -70,17 +69,21 @@ namespace log {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Log::Start ()
 | 
						void Log::Start ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!m_IsRunning)
 | 
							// separate load and store for atomic is valid here
 | 
				
			||||||
		{	
 | 
							// because only one thread changes m_IsRunning
 | 
				
			||||||
			m_IsRunning = true;	
 | 
							if (!m_IsRunning.load())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								m_IsRunning.store(true);
 | 
				
			||||||
			m_Thread = new std::thread (std::bind (&Log::Run, this));
 | 
								m_Thread = new std::thread (std::bind (&Log::Run, this));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Log::Stop ()	
 | 
						void Log::Stop ()	
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		switch (m_Destination) 
 | 
							if (m_IsRunning.load())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								switch (m_Destination)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
#ifndef _WIN32
 | 
					#ifndef _WIN32
 | 
				
			||||||
			case eLogSyslog :
 | 
								case eLogSyslog :
 | 
				
			||||||
				closelog();
 | 
									closelog();
 | 
				
			||||||
| 
						 | 
					@ -88,20 +91,22 @@ namespace log {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
			case eLogFile:
 | 
								case eLogFile:
 | 
				
			||||||
			case eLogStream:
 | 
								case eLogStream:
 | 
				
			||||||
					if (m_LogStream) m_LogStream->flush();
 | 
									if (m_LogStream) m_LogStream->flush();
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				/* do nothing */
 | 
									/* do nothing */
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								m_IsRunning.store(false);
 | 
				
			||||||
 | 
								m_Queue.WakeUp ();
 | 
				
			||||||
 | 
								if (m_Thread)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									m_Thread->join ();
 | 
				
			||||||
 | 
									delete m_Thread;
 | 
				
			||||||
 | 
									m_Thread = nullptr;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		m_IsRunning = false;
 | 
					 | 
				
			||||||
		m_Queue.WakeUp ();
 | 
					 | 
				
			||||||
		if (m_Thread)
 | 
					 | 
				
			||||||
		{	
 | 
					 | 
				
			||||||
			m_Thread->join (); 
 | 
					 | 
				
			||||||
			delete m_Thread;
 | 
					 | 
				
			||||||
			m_Thread = nullptr;
 | 
					 | 
				
			||||||
		}		
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Log::SetLogLevel (const std::string& level) {
 | 
						void Log::SetLogLevel (const std::string& level) {
 | 
				
			||||||
| 
						 | 
					@ -162,13 +167,13 @@ namespace log {
 | 
				
			||||||
	void Log::Run ()
 | 
						void Log::Run ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Reopen ();
 | 
							Reopen ();
 | 
				
			||||||
		while (m_IsRunning)
 | 
							while (m_IsRunning.load(std::memory_order_acquire))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			std::shared_ptr<LogMsg> msg;
 | 
								std::shared_ptr<LogMsg> msg;
 | 
				
			||||||
			while (msg = m_Queue.Get ())
 | 
								while (msg = m_Queue.Get ())
 | 
				
			||||||
				Process (msg);
 | 
									Process (msg);
 | 
				
			||||||
			if (m_LogStream) m_LogStream->flush();
 | 
								if (m_LogStream) m_LogStream->flush();
 | 
				
			||||||
			if (m_IsRunning)
 | 
								if (m_IsRunning.load(std::memory_order_acquire))
 | 
				
			||||||
				m_Queue.Wait ();
 | 
									m_Queue.Wait ();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}		
 | 
						}		
 | 
				
			||||||
| 
						 | 
					@ -215,6 +220,7 @@ namespace log {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Log & Logger() {
 | 
						Log & Logger() {
 | 
				
			||||||
 | 
							static Log logger;
 | 
				
			||||||
		return logger;
 | 
							return logger;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} // log
 | 
					} // log
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,7 @@
 | 
				
			||||||
#include <chrono>
 | 
					#include <chrono>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
#include "Queue.h"
 | 
					#include "Queue.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef _WIN32
 | 
					#ifndef _WIN32
 | 
				
			||||||
| 
						 | 
					@ -59,7 +60,7 @@ namespace log {
 | 
				
			||||||
			i2p::util::Queue<std::shared_ptr<LogMsg> > m_Queue;
 | 
								i2p::util::Queue<std::shared_ptr<LogMsg> > m_Queue;
 | 
				
			||||||
			bool m_HasColors;
 | 
								bool m_HasColors;
 | 
				
			||||||
			std::string m_TimeFormat;
 | 
								std::string m_TimeFormat;
 | 
				
			||||||
			volatile bool m_IsRunning;
 | 
								std::atomic_bool m_IsRunning;
 | 
				
			||||||
			std::thread * m_Thread;
 | 
								std::thread * m_Thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
| 
						 | 
					@ -84,8 +85,8 @@ namespace log {
 | 
				
			||||||
			Log ();
 | 
								Log ();
 | 
				
			||||||
			~Log ();
 | 
								~Log ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			LogType  GetLogType  () { return m_Destination; };
 | 
								LogType  GetLogType  () { return m_Destination; }
 | 
				
			||||||
			LogLevel GetLogLevel () { return m_MinLevel; };
 | 
								LogLevel GetLogLevel () { return m_MinLevel; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void Start ();
 | 
								void Start ();
 | 
				
			||||||
			void Stop ();
 | 
								void Stop ();
 | 
				
			||||||
| 
						 | 
					@ -112,7 +113,7 @@ namespace log {
 | 
				
			||||||
			 * @brief  Sets format for timestamps in log
 | 
								 * @brief  Sets format for timestamps in log
 | 
				
			||||||
			 * @param  format  String with timestamp format
 | 
								 * @param  format  String with timestamp format
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			void SetTimeFormat (std::string format) { m_TimeFormat = format; };
 | 
								void SetTimeFormat (std::string format) { m_TimeFormat = format; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#ifndef _WIN32
 | 
						#ifndef _WIN32
 | 
				
			||||||
			/**
 | 
								/**
 | 
				
			||||||
| 
						 | 
					@ -145,8 +146,8 @@ namespace log {
 | 
				
			||||||
		std::string text; /**< message text as single string */
 | 
							std::string text; /**< message text as single string */
 | 
				
			||||||
		LogLevel level;   /**< message level */
 | 
							LogLevel level;   /**< message level */
 | 
				
			||||||
		std::thread::id tid; /**< id of thread that generated message */
 | 
							std::thread::id tid; /**< id of thread that generated message */
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
		LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {};
 | 
							LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Log & Logger();
 | 
						Log & Logger();
 | 
				
			||||||
| 
						 | 
					@ -184,7 +185,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept
 | 
				
			||||||
	std::stringstream ss("");
 | 
						std::stringstream ss("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LogPrint (ss, std::forward<TArgs>(args)...);
 | 
						LogPrint (ss, std::forward<TArgs>(args)...);
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
	auto msg = std::make_shared<i2p::log::LogMsg>(level, std::time(nullptr), ss.str());
 | 
						auto msg = std::make_shared<i2p::log::LogMsg>(level, std::time(nullptr), ss.str());
 | 
				
			||||||
	msg->tid = std::this_thread::get_id();
 | 
						msg->tid = std::this_thread::get_id();
 | 
				
			||||||
	log.Append(msg);
 | 
						log.Append(msg);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ using namespace i2p::transport;
 | 
				
			||||||
namespace i2p
 | 
					namespace i2p
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
namespace data
 | 
					namespace data
 | 
				
			||||||
{		
 | 
					{
 | 
				
			||||||
	NetDb netdb;
 | 
						NetDb netdb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_FloodfillBootstrap(nullptr), m_HiddenMode(false)
 | 
						NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_FloodfillBootstrap(nullptr), m_HiddenMode(false)
 | 
				
			||||||
| 
						 | 
					@ -31,65 +31,70 @@ namespace data
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	NetDb::~NetDb ()
 | 
						NetDb::~NetDb ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Stop ();	
 | 
							Stop ();
 | 
				
			||||||
		delete m_Reseeder;
 | 
							delete m_Reseeder;
 | 
				
			||||||
	}	
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void NetDb::Start ()
 | 
						void NetDb::Start ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_Storage.SetPlace(i2p::fs::GetDataDir());
 | 
							// separate load and store for atomic is valid here
 | 
				
			||||||
		m_Storage.Init(i2p::data::GetBase64SubstitutionTable(), 64);
 | 
							// because only one thread changes m_IsRunning
 | 
				
			||||||
		InitProfilesStorage ();
 | 
							if (!m_IsRunning.load())
 | 
				
			||||||
		m_Families.LoadCertificates ();
 | 
							{
 | 
				
			||||||
		Load ();
 | 
								m_Storage.SetPlace(i2p::fs::GetDataDir());
 | 
				
			||||||
 | 
								m_Storage.Init(i2p::data::GetBase64SubstitutionTable(), 64);
 | 
				
			||||||
 | 
								InitProfilesStorage ();
 | 
				
			||||||
 | 
								m_Families.LoadCertificates ();
 | 
				
			||||||
 | 
								Load ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
 | 
								uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
 | 
				
			||||||
		if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
 | 
								if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
 | 
				
			||||||
			Reseed ();
 | 
									Reseed ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m_IsRunning = true;
 | 
								m_IsRunning.store(true);
 | 
				
			||||||
		m_Thread = new std::thread (std::bind (&NetDb::Run, this));
 | 
								m_Thread = new std::thread (std::bind (&NetDb::Run, this));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	void NetDb::Stop ()
 | 
						void NetDb::Stop ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (m_IsRunning)
 | 
							if (m_IsRunning.load())
 | 
				
			||||||
		{	
 | 
							{
 | 
				
			||||||
			for (auto& it: m_RouterInfos)
 | 
								for (auto& it: m_RouterInfos)
 | 
				
			||||||
				it.second->SaveProfile ();
 | 
									it.second->SaveProfile ();
 | 
				
			||||||
			DeleteObsoleteProfiles ();
 | 
								DeleteObsoleteProfiles ();
 | 
				
			||||||
			m_RouterInfos.clear ();
 | 
								m_RouterInfos.clear ();
 | 
				
			||||||
			m_Floodfills.clear ();
 | 
								m_Floodfills.clear ();
 | 
				
			||||||
			if (m_Thread)
 | 
								if (m_Thread)
 | 
				
			||||||
			{	
 | 
								{
 | 
				
			||||||
				m_IsRunning = false;
 | 
									m_IsRunning.store(false);
 | 
				
			||||||
				m_Queue.WakeUp ();
 | 
									m_Queue.WakeUp ();
 | 
				
			||||||
				m_Thread->join (); 
 | 
									m_Thread->join (); 
 | 
				
			||||||
				delete m_Thread;
 | 
									delete m_Thread;
 | 
				
			||||||
				m_Thread = 0;
 | 
									m_Thread = nullptr;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			m_LeaseSets.clear();
 | 
								m_LeaseSets.clear();
 | 
				
			||||||
			m_Requests.Stop ();
 | 
								m_Requests.Stop ();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}	
 | 
						}
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
	void NetDb::Run ()
 | 
						void NetDb::Run ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
 | 
							uint64_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
 | 
				
			||||||
		while (m_IsRunning)
 | 
							while (m_IsRunning.load(std::memory_order_acquire))
 | 
				
			||||||
		{	
 | 
							{
 | 
				
			||||||
			try
 | 
								try
 | 
				
			||||||
			{	
 | 
								{
 | 
				
			||||||
				auto msg = m_Queue.GetNextWithTimeout (15000); // 15 sec
 | 
									auto msg = m_Queue.GetNextWithTimeout (15000); // 15 sec
 | 
				
			||||||
				if (msg)
 | 
									if (msg)
 | 
				
			||||||
				{	
 | 
									{
 | 
				
			||||||
					int numMsgs = 0;	
 | 
										int numMsgs = 0;
 | 
				
			||||||
					while (msg)
 | 
										while (msg)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						LogPrint(eLogDebug, "NetDb: got request with type ", (int) msg->GetTypeID ());
 | 
											LogPrint(eLogDebug, "NetDb: got request with type ", (int) msg->GetTypeID ());
 | 
				
			||||||
						switch (msg->GetTypeID ()) 
 | 
											switch (msg->GetTypeID ()) 
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							case eI2NPDatabaseStore:	
 | 
												case eI2NPDatabaseStore:
 | 
				
			||||||
								HandleDatabaseStoreMsg (msg);
 | 
													HandleDatabaseStoreMsg (msg);
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
							case eI2NPDatabaseSearchReply:
 | 
												case eI2NPDatabaseSearchReply:
 | 
				
			||||||
| 
						 | 
					@ -97,7 +102,7 @@ namespace data
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
							case eI2NPDatabaseLookup:
 | 
												case eI2NPDatabaseLookup:
 | 
				
			||||||
								HandleDatabaseLookupMsg (msg);
 | 
													HandleDatabaseLookupMsg (msg);
 | 
				
			||||||
							break;	
 | 
												break;
 | 
				
			||||||
							default: // WTF?
 | 
												default: // WTF?
 | 
				
			||||||
								LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ());
 | 
													LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ());
 | 
				
			||||||
								//i2p::HandleI2NPMessage (msg);
 | 
													//i2p::HandleI2NPMessage (msg);
 | 
				
			||||||
| 
						 | 
					@ -105,23 +110,25 @@ namespace data
 | 
				
			||||||
						if (numMsgs > 100) break;
 | 
											if (numMsgs > 100) break;
 | 
				
			||||||
						msg = m_Queue.Get ();
 | 
											msg = m_Queue.Get ();
 | 
				
			||||||
						numMsgs++;
 | 
											numMsgs++;
 | 
				
			||||||
					}	
 | 
										}
 | 
				
			||||||
				}			
 | 
									}
 | 
				
			||||||
				if (!m_IsRunning) break;
 | 
					
 | 
				
			||||||
 | 
									if (!m_IsRunning.load(std::memory_order_acquire))
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
 | 
									uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
 | 
				
			||||||
				if (ts - lastManageRequest >= 15) // manage requests every 15 seconds
 | 
									if (ts - lastManageRequest >= 15) // manage requests every 15 seconds
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					m_Requests.ManageRequests ();
 | 
										m_Requests.ManageRequests ();
 | 
				
			||||||
					lastManageRequest = ts;
 | 
										lastManageRequest = ts;
 | 
				
			||||||
				}	
 | 
									}
 | 
				
			||||||
				if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
 | 
									if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					if (lastSave)
 | 
										if (lastSave)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						SaveUpdated ();
 | 
											SaveUpdated ();
 | 
				
			||||||
						ManageLeaseSets ();
 | 
											ManageLeaseSets ();
 | 
				
			||||||
					}	
 | 
										}
 | 
				
			||||||
					lastSave = ts;
 | 
										lastSave = ts;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT) 
 | 
									if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT) 
 | 
				
			||||||
| 
						 | 
					@ -129,23 +136,23 @@ namespace data
 | 
				
			||||||
					i2p::context.CleanupDestination ();
 | 
										i2p::context.CleanupDestination ();
 | 
				
			||||||
					lastDestinationCleanup = ts;
 | 
										lastDestinationCleanup = ts;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
				if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish 
 | 
									if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish 
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Publish ();
 | 
										Publish ();
 | 
				
			||||||
					lastPublish = ts;
 | 
										lastPublish = ts;
 | 
				
			||||||
				}	
 | 
									}
 | 
				
			||||||
				if (ts - lastExploratory >= 30) // exploratory every 30 seconds
 | 
									if (ts - lastExploratory >= 30) // exploratory every 30 seconds
 | 
				
			||||||
				{	
 | 
									{
 | 
				
			||||||
					auto numRouters = m_RouterInfos.size ();
 | 
										auto numRouters = m_RouterInfos.size ();
 | 
				
			||||||
					if (numRouters == 0)
 | 
										if (numRouters == 0)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
                                                throw std::runtime_error("No known routers, reseed seems to be totally failed");
 | 
											throw std::runtime_error("No known routers, reseed seems to be totally failed");
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					else // we have peers now
 | 
										else // we have peers now
 | 
				
			||||||
						m_FloodfillBootstrap = nullptr;
 | 
											m_FloodfillBootstrap = nullptr;
 | 
				
			||||||
					if (numRouters < 2500 || ts - lastExploratory >= 90)
 | 
										if (numRouters < 2500 || ts - lastExploratory >= 90)
 | 
				
			||||||
					{	
 | 
										{
 | 
				
			||||||
						numRouters = 800/numRouters;
 | 
											numRouters = 800/numRouters;
 | 
				
			||||||
						if (numRouters < 1) numRouters = 1;
 | 
											if (numRouters < 1) numRouters = 1;
 | 
				
			||||||
						if (numRouters > 9) numRouters = 9;	
 | 
											if (numRouters > 9) numRouters = 9;	
 | 
				
			||||||
| 
						 | 
					@ -153,15 +160,15 @@ namespace data
 | 
				
			||||||
						if(!m_HiddenMode)
 | 
											if(!m_HiddenMode)
 | 
				
			||||||
							Explore (numRouters);
 | 
												Explore (numRouters);
 | 
				
			||||||
						lastExploratory = ts;
 | 
											lastExploratory = ts;
 | 
				
			||||||
					}	
 | 
										}
 | 
				
			||||||
				}	
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			catch (std::exception& ex)
 | 
								catch (std::exception& ex)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				LogPrint (eLogError, "NetDb: runtime exception: ", ex.what ());
 | 
									LogPrint (eLogError, "NetDb: runtime exception: ", ex.what ());
 | 
				
			||||||
			}	
 | 
								}
 | 
				
			||||||
		}	
 | 
							}
 | 
				
			||||||
	}	
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
 | 
						bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -171,11 +178,11 @@ namespace data
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void NetDb::SetHidden(bool hide) {
 | 
						void NetDb::SetHidden(bool hide) {
 | 
				
			||||||
    // TODO: remove reachable addresses from router info
 | 
							// TODO: remove reachable addresses from router info
 | 
				
			||||||
    m_HiddenMode = hide;
 | 
							m_HiddenMode = hide;
 | 
				
			||||||
  }
 | 
						}
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
	bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
 | 
						bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
 | 
				
			||||||
	{	
 | 
						{	
 | 
				
			||||||
		bool updated = true;	
 | 
							bool updated = true;	
 | 
				
			||||||
| 
						 | 
					@ -330,7 +337,7 @@ namespace data
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                m_Reseeder->Bootstrap ();
 | 
							m_Reseeder->Bootstrap ();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
 | 
						void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
 | 
				
			||||||
| 
						 | 
					@ -392,7 +399,7 @@ namespace data
 | 
				
			||||||
	void NetDb::VisitStoredRouterInfos(RouterInfoVisitor v)
 | 
						void NetDb::VisitStoredRouterInfos(RouterInfoVisitor v)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_Storage.Iterate([v] (const std::string & filename) {
 | 
							m_Storage.Iterate([v] (const std::string & filename) {
 | 
				
			||||||
        auto ri = std::make_shared<i2p::data::RouterInfo>(filename);
 | 
								auto ri = std::make_shared<i2p::data::RouterInfo>(filename);
 | 
				
			||||||
				v(ri);
 | 
									v(ri);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Base.h"
 | 
					#include "Base.h"
 | 
				
			||||||
#include "Gzip.h"
 | 
					#include "Gzip.h"
 | 
				
			||||||
| 
						 | 
					@ -25,7 +26,7 @@
 | 
				
			||||||
namespace i2p
 | 
					namespace i2p
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
namespace data
 | 
					namespace data
 | 
				
			||||||
{		
 | 
					{
 | 
				
			||||||
	const int NETDB_MIN_ROUTERS = 90;
 | 
						const int NETDB_MIN_ROUTERS = 90;
 | 
				
			||||||
	const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds
 | 
						const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds
 | 
				
			||||||
	const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60;
 | 
						const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60;
 | 
				
			||||||
| 
						 | 
					@ -41,7 +42,7 @@ namespace data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/** function for visiting a router info and determining if we want to use it */
 | 
						/** function for visiting a router info and determining if we want to use it */
 | 
				
			||||||
	typedef std::function<bool(std::shared_ptr<const i2p::data::RouterInfo>)> RouterInfoFilter;
 | 
						typedef std::function<bool(std::shared_ptr<const i2p::data::RouterInfo>)> RouterInfoFilter;
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
	class NetDb
 | 
						class NetDb
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		public:
 | 
							public:
 | 
				
			||||||
| 
						 | 
					@ -51,7 +52,7 @@ namespace data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void Start ();
 | 
								void Start ();
 | 
				
			||||||
			void Stop ();
 | 
								void Stop ();
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
			bool AddRouterInfo (const uint8_t * buf, int len);
 | 
								bool AddRouterInfo (const uint8_t * buf, int len);
 | 
				
			||||||
			bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len);
 | 
								bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len);
 | 
				
			||||||
			bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
 | 
								bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
 | 
				
			||||||
| 
						 | 
					@ -60,7 +61,7 @@ namespace data
 | 
				
			||||||
			std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
 | 
								std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);			
 | 
								void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);			
 | 
				
			||||||
		void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);			
 | 
								void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);			
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
								void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
				
			||||||
			void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
								void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
				
			||||||
| 
						 | 
					@ -75,21 +76,21 @@ namespace data
 | 
				
			||||||
			std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
 | 
								std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
 | 
				
			||||||
				std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
 | 
									std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
 | 
				
			||||||
			std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
 | 
								std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
 | 
				
			||||||
      std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
 | 
								std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
 | 
				
			||||||
			void SetUnreachable (const IdentHash& ident, bool unreachable);			
 | 
								void SetUnreachable (const IdentHash& ident, bool unreachable);			
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
								void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      /** set hidden mode, aka don't publish our RI to netdb and don't explore */
 | 
								/** set hidden mode, aka don't publish our RI to netdb and don't explore */
 | 
				
			||||||
      void SetHidden(bool hide); 
 | 
								void SetHidden(bool hide); 
 | 
				
			||||||
      
 | 
					
 | 
				
			||||||
			void Reseed ();
 | 
								void Reseed ();
 | 
				
			||||||
			Families& GetFamilies () { return m_Families; };
 | 
								Families& GetFamilies () { return m_Families; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// for web interface
 | 
								// for web interface
 | 
				
			||||||
			int GetNumRouters () const { return m_RouterInfos.size (); };
 | 
								int GetNumRouters () const { return m_RouterInfos.size (); }
 | 
				
			||||||
			int GetNumFloodfills () const { return m_Floodfills.size (); };
 | 
								int GetNumFloodfills () const { return m_Floodfills.size (); }
 | 
				
			||||||
			int GetNumLeaseSets () const { return m_LeaseSets.size (); };
 | 
								int GetNumLeaseSets () const { return m_LeaseSets.size (); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/** visit all lease sets we currently store */
 | 
								/** visit all lease sets we currently store */
 | 
				
			||||||
			void VisitLeaseSets(LeaseSetVisitor v);
 | 
								void VisitLeaseSets(LeaseSetVisitor v);
 | 
				
			||||||
| 
						 | 
					@ -100,7 +101,7 @@ namespace data
 | 
				
			||||||
			/** visit N random router that match using filter, then visit them with a visitor, return number of RouterInfos that were visited */
 | 
								/** visit N random router that match using filter, then visit them with a visitor, return number of RouterInfos that were visited */
 | 
				
			||||||
			size_t VisitRandomRouterInfos(RouterInfoFilter f, RouterInfoVisitor v, size_t n);
 | 
								size_t VisitRandomRouterInfos(RouterInfoFilter f, RouterInfoVisitor v, size_t n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void ClearRouterInfos () { m_RouterInfos.clear (); };
 | 
								void ClearRouterInfos () { m_RouterInfos.clear (); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,8 +116,8 @@ namespace data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20);
 | 
							void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
    	template<typename Filter>
 | 
							template<typename Filter>
 | 
				
			||||||
        std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;	
 | 
							std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					@ -127,9 +128,9 @@ namespace data
 | 
				
			||||||
			mutable std::mutex m_FloodfillsMutex;
 | 
								mutable std::mutex m_FloodfillsMutex;
 | 
				
			||||||
			std::list<std::shared_ptr<RouterInfo> > m_Floodfills;
 | 
								std::list<std::shared_ptr<RouterInfo> > m_Floodfills;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			bool m_IsRunning;
 | 
								std::atomic_bool m_IsRunning;
 | 
				
			||||||
			uint64_t m_LastLoad;
 | 
								uint64_t m_LastLoad;
 | 
				
			||||||
			std::thread * m_Thread;	
 | 
								std::thread * m_Thread;
 | 
				
			||||||
			i2p::util::Queue<std::shared_ptr<const I2NPMessage> > m_Queue; // of I2NPDatabaseStoreMsg
 | 
								i2p::util::Queue<std::shared_ptr<const I2NPMessage> > m_Queue; // of I2NPDatabaseStoreMsg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			GzipInflator m_Inflator;
 | 
								GzipInflator m_Inflator;
 | 
				
			||||||
| 
						 | 
					@ -142,10 +143,10 @@ namespace data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
 | 
							/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
 | 
				
			||||||
		std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
 | 
							std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
 | 
				
			||||||
				
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      /** true if in hidden mode */
 | 
					
 | 
				
			||||||
      bool m_HiddenMode;
 | 
							/** true if in hidden mode */
 | 
				
			||||||
 | 
							bool m_HiddenMode;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	extern NetDb netdb;
 | 
						extern NetDb netdb;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -445,19 +445,25 @@ namespace tunnel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Tunnels::Start ()
 | 
						void Tunnels::Start ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_IsRunning = true;
 | 
							if (!m_IsRunning.load())
 | 
				
			||||||
		m_Thread = new std::thread (std::bind (&Tunnels::Run, this));
 | 
							{
 | 
				
			||||||
 | 
								m_IsRunning.store(true);
 | 
				
			||||||
 | 
								m_Thread = new std::thread (std::bind (&Tunnels::Run, this));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Tunnels::Stop ()
 | 
						void Tunnels::Stop ()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_IsRunning = false;
 | 
							if (m_IsRunning.load())
 | 
				
			||||||
		m_Queue.WakeUp ();
 | 
					 | 
				
			||||||
		if (m_Thread)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			m_Thread->join (); 
 | 
								m_IsRunning.store(false);
 | 
				
			||||||
			delete m_Thread;
 | 
								m_Queue.WakeUp ();
 | 
				
			||||||
			m_Thread = 0;
 | 
								if (m_Thread)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									m_Thread->join ();
 | 
				
			||||||
 | 
									delete m_Thread;
 | 
				
			||||||
 | 
									m_Thread = 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -466,7 +472,7 @@ namespace tunnel
 | 
				
			||||||
		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.load(std::memory_order_acquire))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			try
 | 
								try
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
#include "Queue.h"
 | 
					#include "Queue.h"
 | 
				
			||||||
#include "Crypto.h"
 | 
					#include "Crypto.h"
 | 
				
			||||||
#include "TunnelConfig.h"
 | 
					#include "TunnelConfig.h"
 | 
				
			||||||
| 
						 | 
					@ -61,7 +62,7 @@ namespace tunnel
 | 
				
			||||||
#endif 
 | 
					#endif 
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
	const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes	
 | 
						const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes	
 | 
				
			||||||
	const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute	
 | 
						const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute	
 | 
				
			||||||
	const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes	
 | 
						const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes	
 | 
				
			||||||
| 
						 | 
					@ -99,20 +100,20 @@ namespace tunnel
 | 
				
			||||||
			std::shared_ptr<const TunnelConfig> GetTunnelConfig () const { return m_Config; }
 | 
								std::shared_ptr<const TunnelConfig> GetTunnelConfig () const { return m_Config; }
 | 
				
			||||||
			std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetPeers () const; 
 | 
								std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetPeers () const; 
 | 
				
			||||||
			std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetInvertedPeers () const; 
 | 
								std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetInvertedPeers () const; 
 | 
				
			||||||
			TunnelState GetState () const { return m_State; };
 | 
								TunnelState GetState () const { return m_State; }
 | 
				
			||||||
			void SetState (TunnelState state);
 | 
								void SetState (TunnelState state);
 | 
				
			||||||
			bool IsEstablished () const { return m_State == eTunnelStateEstablished; };
 | 
								bool IsEstablished () const { return m_State == eTunnelStateEstablished; }
 | 
				
			||||||
			bool IsFailed () const { return m_State == eTunnelStateFailed; };
 | 
								bool IsFailed () const { return m_State == eTunnelStateFailed; }
 | 
				
			||||||
			bool IsRecreated () const { return m_IsRecreated; };
 | 
								bool IsRecreated () const { return m_IsRecreated; }
 | 
				
			||||||
			void SetIsRecreated () { m_IsRecreated = true; };
 | 
								void SetIsRecreated () { m_IsRecreated = true; }
 | 
				
			||||||
			virtual bool IsInbound() const = 0;
 | 
								virtual bool IsInbound() const = 0;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; };
 | 
								std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; }
 | 
				
			||||||
			void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; };			
 | 
								void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; }
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
 | 
								bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			virtual void Print (std::stringstream&) const {};
 | 
								virtual void Print (std::stringstream&) const {}
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			// implements TunnelBase
 | 
								// implements TunnelBase
 | 
				
			||||||
			void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
 | 
								void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
 | 
				
			||||||
| 
						 | 
					@ -145,12 +146,12 @@ namespace tunnel
 | 
				
			||||||
		public:
 | 
							public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			OutboundTunnel (std::shared_ptr<const TunnelConfig> config): 
 | 
								OutboundTunnel (std::shared_ptr<const TunnelConfig> config): 
 | 
				
			||||||
				Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {};
 | 
									Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg);
 | 
								void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg);
 | 
				
			||||||
			virtual void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs); // multiple messages
 | 
								virtual void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs); // multiple messages
 | 
				
			||||||
			const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }; 
 | 
								const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }
 | 
				
			||||||
			virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); };
 | 
								virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }
 | 
				
			||||||
			void Print (std::stringstream& s) const;
 | 
								void Print (std::stringstream& s) const;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			// implements TunnelBase
 | 
								// implements TunnelBase
 | 
				
			||||||
| 
						 | 
					@ -169,14 +170,14 @@ namespace tunnel
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		public:
 | 
							public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			InboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Endpoint (true) {};
 | 
								InboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Endpoint (true) {}
 | 
				
			||||||
			void HandleTunnelDataMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
								void HandleTunnelDataMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
				
			||||||
			virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
 | 
								virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); }
 | 
				
			||||||
			void Print (std::stringstream& s) const;
 | 
								void Print (std::stringstream& s) const;
 | 
				
			||||||
			bool IsInbound() const { return true; }
 | 
								bool IsInbound() const { return true; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// override TunnelBase
 | 
								// override TunnelBase
 | 
				
			||||||
			void Cleanup () { m_Endpoint.Cleanup (); };	
 | 
								void Cleanup () { m_Endpoint.Cleanup (); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,7 +191,7 @@ namespace tunnel
 | 
				
			||||||
			ZeroHopsInboundTunnel ();
 | 
								ZeroHopsInboundTunnel ();
 | 
				
			||||||
			void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg); 
 | 
								void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg); 
 | 
				
			||||||
			void Print (std::stringstream& s) const;
 | 
								void Print (std::stringstream& s) const;
 | 
				
			||||||
			size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
 | 
								size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -204,7 +205,7 @@ namespace tunnel
 | 
				
			||||||
			ZeroHopsOutboundTunnel ();
 | 
								ZeroHopsOutboundTunnel ();
 | 
				
			||||||
			void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs);
 | 
								void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs);
 | 
				
			||||||
			void Print (std::stringstream& s) const;
 | 
								void Print (std::stringstream& s) const;
 | 
				
			||||||
			size_t GetNumSentBytes () const { return m_NumSentBytes; };
 | 
								size_t GetNumSentBytes () const { return m_NumSentBytes; }
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -224,7 +225,7 @@ namespace tunnel
 | 
				
			||||||
			std::shared_ptr<OutboundTunnel> GetPendingOutboundTunnel (uint32_t replyMsgID);			
 | 
								std::shared_ptr<OutboundTunnel> GetPendingOutboundTunnel (uint32_t replyMsgID);			
 | 
				
			||||||
			std::shared_ptr<InboundTunnel> GetNextInboundTunnel ();
 | 
								std::shared_ptr<InboundTunnel> GetNextInboundTunnel ();
 | 
				
			||||||
			std::shared_ptr<OutboundTunnel> GetNextOutboundTunnel ();
 | 
								std::shared_ptr<OutboundTunnel> GetNextOutboundTunnel ();
 | 
				
			||||||
			std::shared_ptr<TunnelPool> GetExploratoryPool () const { return m_ExploratoryPool; };
 | 
								std::shared_ptr<TunnelPool> GetExploratoryPool () const { return m_ExploratoryPool; }
 | 
				
			||||||
			std::shared_ptr<TunnelBase> GetTunnel (uint32_t tunnelID);
 | 
								std::shared_ptr<TunnelBase> GetTunnel (uint32_t tunnelID);
 | 
				
			||||||
			int GetTransitTunnelsExpirationTimeout ();
 | 
								int GetTransitTunnelsExpirationTimeout ();
 | 
				
			||||||
			void AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel);
 | 
								void AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel);
 | 
				
			||||||
| 
						 | 
					@ -266,7 +267,7 @@ namespace tunnel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bool m_IsRunning;
 | 
								std::atomic_bool m_IsRunning;
 | 
				
			||||||
			std::thread * m_Thread;	
 | 
								std::thread * m_Thread;	
 | 
				
			||||||
			std::map<uint32_t, std::shared_ptr<InboundTunnel> > m_PendingInboundTunnels; // by replyMsgID
 | 
								std::map<uint32_t, std::shared_ptr<InboundTunnel> > m_PendingInboundTunnels; // by replyMsgID
 | 
				
			||||||
			std::map<uint32_t, std::shared_ptr<OutboundTunnel> > m_PendingOutboundTunnels; // by replyMsgID
 | 
								std::map<uint32_t, std::shared_ptr<OutboundTunnel> > m_PendingOutboundTunnels; // by replyMsgID
 | 
				
			||||||
| 
						 | 
					@ -285,24 +286,24 @@ namespace tunnel
 | 
				
			||||||
		public:
 | 
							public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// for HTTP only
 | 
								// for HTTP only
 | 
				
			||||||
			const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; };
 | 
								const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; }
 | 
				
			||||||
			const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; };
 | 
								const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; }
 | 
				
			||||||
			const decltype(m_TransitTunnels)& GetTransitTunnels () const { return m_TransitTunnels; };
 | 
								const decltype(m_TransitTunnels)& GetTransitTunnels () const { return m_TransitTunnels; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			size_t CountTransitTunnels() const;
 | 
								size_t CountTransitTunnels() const;
 | 
				
			||||||
			size_t CountInboundTunnels() const;
 | 
								size_t CountInboundTunnels() const;
 | 
				
			||||||
			size_t CountOutboundTunnels() const;
 | 
								size_t CountOutboundTunnels() const;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			int GetQueueSize () { return m_Queue.GetSize (); };
 | 
								int GetQueueSize () { return m_Queue.GetSize (); }
 | 
				
			||||||
			int GetTunnelCreationSuccessRate () const // in percents
 | 
								int GetTunnelCreationSuccessRate () const // in percents
 | 
				
			||||||
			{ 
 | 
								{ 
 | 
				
			||||||
				int totalNum = m_NumSuccesiveTunnelCreations + m_NumFailedTunnelCreations;
 | 
									int totalNum = m_NumSuccesiveTunnelCreations + m_NumFailedTunnelCreations;
 | 
				
			||||||
				return totalNum ? m_NumSuccesiveTunnelCreations*100/totalNum : 0;
 | 
									return totalNum ? m_NumSuccesiveTunnelCreations*100/totalNum : 0;
 | 
				
			||||||
			}		
 | 
								}		
 | 
				
			||||||
	};	
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	extern Tunnels tunnels;
 | 
						extern Tunnels tunnels;
 | 
				
			||||||
}	
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
#include "Destination.h"
 | 
					#include "Destination.h"
 | 
				
			||||||
#include "Streaming.h"
 | 
					#include "Streaming.h"
 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <websocketpp/config/asio_no_tls.hpp>
 | 
					#include <websocketpp/config/asio_no_tls.hpp>
 | 
				
			||||||
#include <websocketpp/server.hpp>
 | 
					#include <websocketpp/server.hpp>
 | 
				
			||||||
| 
						 | 
					@ -100,35 +101,41 @@ namespace client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void Start()
 | 
							void Start()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(m_Run) return; // already started
 | 
								if (!m_Run.load())
 | 
				
			||||||
			m_Server.listen(boost::asio::ip::address::from_string(m_Addr), m_Port);
 | 
								{
 | 
				
			||||||
			m_Server.start_accept();
 | 
									m_Run.store(true);
 | 
				
			||||||
			m_Run = true;
 | 
									m_Server.listen(boost::asio::ip::address::from_string(m_Addr), m_Port);
 | 
				
			||||||
			m_Thread = new std::thread([&] (){
 | 
									m_Server.start_accept();
 | 
				
			||||||
					while(m_Run) {
 | 
									m_Run = true;
 | 
				
			||||||
 | 
									m_Thread = new std::thread([&] (){
 | 
				
			||||||
 | 
										while (m_Run.load(std::memory_order_acquire)) {
 | 
				
			||||||
						try {
 | 
											try {
 | 
				
			||||||
							m_Server.run();
 | 
												m_Server.run();
 | 
				
			||||||
						} catch( std::exception & ex) {
 | 
											} catch( std::exception & ex) {
 | 
				
			||||||
							LogPrint(eLogError, "Websocks runtime exception: ", ex.what());
 | 
												LogPrint(eLogError, "Websocks runtime exception: ", ex.what());
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
			});
 | 
									});
 | 
				
			||||||
			m_Dest->Start();
 | 
									m_Dest->Start();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void Stop()
 | 
							void Stop()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			for(const auto & conn : m_Conns)
 | 
								if (m_Run.load())
 | 
				
			||||||
				conn->Close();
 | 
								{
 | 
				
			||||||
 | 
									for(const auto & conn : m_Conns)
 | 
				
			||||||
 | 
										conn->Close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			m_Dest->Stop();
 | 
									m_Dest->Stop();
 | 
				
			||||||
			m_Run = false;
 | 
									m_Run.store(false);
 | 
				
			||||||
			m_Server.stop();
 | 
									m_Server.stop();
 | 
				
			||||||
			if(m_Thread) {
 | 
									if(m_Thread) {
 | 
				
			||||||
				m_Thread->join();
 | 
										m_Thread->join();
 | 
				
			||||||
				delete m_Thread;
 | 
										delete m_Thread;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									m_Thread = nullptr;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			m_Thread = nullptr;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		boost::asio::ip::tcp::endpoint GetLocalEndpoint()
 | 
							boost::asio::ip::tcp::endpoint GetLocalEndpoint()
 | 
				
			||||||
| 
						 | 
					@ -140,7 +147,7 @@ namespace client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
		std::vector<WebSocksConn_ptr> m_Conns;
 | 
							std::vector<WebSocksConn_ptr> m_Conns;
 | 
				
			||||||
		bool m_Run;
 | 
							std::atomic_bool m_Run;
 | 
				
			||||||
		ServerImpl m_Server;
 | 
							ServerImpl m_Server;
 | 
				
			||||||
		std::string m_Addr;
 | 
							std::string m_Addr;
 | 
				
			||||||
		int m_Port;
 | 
							int m_Port;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ namespace i2p
 | 
				
			||||||
		public:
 | 
							public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			WebsocketServerImpl(const std::string & addr, int port) :
 | 
								WebsocketServerImpl(const std::string & addr, int port) :
 | 
				
			||||||
				m_run(false),
 | 
									m_IsRunning(false),
 | 
				
			||||||
				m_ws_thread(nullptr),
 | 
									m_ws_thread(nullptr),
 | 
				
			||||||
				m_ev_thread(nullptr),
 | 
									m_ev_thread(nullptr),
 | 
				
			||||||
				m_WebsocketTicker(m_Service)
 | 
									m_WebsocketTicker(m_Service)
 | 
				
			||||||
| 
						 | 
					@ -48,10 +48,12 @@ namespace i2p
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void Start() {
 | 
								void Start() {
 | 
				
			||||||
				m_run = true;
 | 
									if (!m_IsRunning.load())
 | 
				
			||||||
				m_server.start_accept();
 | 
									{
 | 
				
			||||||
				m_ws_thread = new std::thread([&] () {
 | 
										m_IsRunning.store(true);
 | 
				
			||||||
						while(m_run) {
 | 
										m_server.start_accept();
 | 
				
			||||||
 | 
										m_ws_thread = new std::thread([&] () {
 | 
				
			||||||
 | 
											while(m_IsRunning.load(std::memory_order_acquire)) {
 | 
				
			||||||
							try {
 | 
												try {
 | 
				
			||||||
								m_server.run();
 | 
													m_server.run();
 | 
				
			||||||
							} catch (std::exception & e ) {
 | 
												} catch (std::exception & e ) {
 | 
				
			||||||
| 
						 | 
					@ -59,8 +61,8 @@ namespace i2p
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				m_ev_thread = new std::thread([&] () {
 | 
										m_ev_thread = new std::thread([&] () {
 | 
				
			||||||
						while(m_run) {
 | 
											while(m_IsRunning.load(std::memory_order_acquire)) {
 | 
				
			||||||
							try {
 | 
												try {
 | 
				
			||||||
								m_Service.run();
 | 
													m_Service.run();
 | 
				
			||||||
								break;
 | 
													break;
 | 
				
			||||||
| 
						 | 
					@ -69,25 +71,29 @@ namespace i2p
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				ScheduleTick();
 | 
										ScheduleTick();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void Stop() {
 | 
								void Stop() {
 | 
				
			||||||
				m_run = false;
 | 
									if (m_IsRunning.load())
 | 
				
			||||||
				m_Service.stop();
 | 
									{
 | 
				
			||||||
				m_server.stop();
 | 
										m_IsRunning.store(false);
 | 
				
			||||||
 | 
										m_Service.stop();
 | 
				
			||||||
 | 
										m_server.stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(m_ev_thread) {
 | 
										if(m_ev_thread) {
 | 
				
			||||||
					m_ev_thread->join();
 | 
											m_ev_thread->join();
 | 
				
			||||||
					delete m_ev_thread;
 | 
											delete m_ev_thread;
 | 
				
			||||||
				}
 | 
										}
 | 
				
			||||||
				m_ev_thread = nullptr;
 | 
										m_ev_thread = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(m_ws_thread) {
 | 
										if(m_ws_thread) {
 | 
				
			||||||
					m_ws_thread->join();
 | 
											m_ws_thread->join();
 | 
				
			||||||
					delete m_ws_thread;
 | 
											delete m_ws_thread;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										m_ws_thread = nullptr;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				m_ws_thread = nullptr;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void ConnOpened(ServerConn c)
 | 
								void ConnOpened(ServerConn c)
 | 
				
			||||||
| 
						 | 
					@ -158,7 +164,7 @@ namespace i2p
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
			typedef std::set<ServerConn, std::owner_less<ServerConn> > ConnList;
 | 
								typedef std::set<ServerConn, std::owner_less<ServerConn> > ConnList;
 | 
				
			||||||
			bool m_run;
 | 
								std::atomic_bool m_IsRunning;
 | 
				
			||||||
			std::thread * m_ws_thread;
 | 
								std::thread * m_ws_thread;
 | 
				
			||||||
			std::thread * m_ev_thread;
 | 
								std::thread * m_ev_thread;
 | 
				
			||||||
			std::mutex m_connsMutex;
 | 
								std::mutex m_connsMutex;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue