mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 08:30:46 +00:00 
			
		
		
		
	fix code syle(spaces->tabs, tabulations)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
This commit is contained in:
		
							parent
							
								
									9633c247f0
								
							
						
					
					
						commit
						7a5146ea74
					
				
					 115 changed files with 3206 additions and 3161 deletions
				
			
		| 
						 | 
				
			
			@ -26,48 +26,48 @@
 | 
			
		|||
 | 
			
		||||
class I2PService
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	public:
 | 
			
		||||
 | 
			
		||||
	I2PService(PSTR pszServiceName,
 | 
			
		||||
		BOOL fCanStop = TRUE,
 | 
			
		||||
		BOOL fCanShutdown = TRUE,
 | 
			
		||||
		BOOL fCanPauseContinue = FALSE);
 | 
			
		||||
		I2PService(PSTR pszServiceName,
 | 
			
		||||
			BOOL fCanStop = TRUE,
 | 
			
		||||
			BOOL fCanShutdown = TRUE,
 | 
			
		||||
			BOOL fCanPauseContinue = FALSE);
 | 
			
		||||
 | 
			
		||||
	virtual ~I2PService(void);
 | 
			
		||||
		virtual ~I2PService(void);
 | 
			
		||||
 | 
			
		||||
	static BOOL isService();
 | 
			
		||||
	static BOOL Run(I2PService &service);
 | 
			
		||||
	void Stop();
 | 
			
		||||
		static BOOL isService();
 | 
			
		||||
		static BOOL Run(I2PService &service);
 | 
			
		||||
		void Stop();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	protected:
 | 
			
		||||
 | 
			
		||||
	virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
 | 
			
		||||
	virtual void OnStop();
 | 
			
		||||
	virtual void OnPause();
 | 
			
		||||
	virtual void OnContinue();
 | 
			
		||||
	virtual void OnShutdown();
 | 
			
		||||
	void SetServiceStatus(DWORD dwCurrentState,
 | 
			
		||||
		DWORD dwWin32ExitCode = NO_ERROR,
 | 
			
		||||
		DWORD dwWaitHint = 0);
 | 
			
		||||
		virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
 | 
			
		||||
		virtual void OnStop();
 | 
			
		||||
		virtual void OnPause();
 | 
			
		||||
		virtual void OnContinue();
 | 
			
		||||
		virtual void OnShutdown();
 | 
			
		||||
		void SetServiceStatus(DWORD dwCurrentState,
 | 
			
		||||
			DWORD dwWin32ExitCode = NO_ERROR,
 | 
			
		||||
			DWORD dwWaitHint = 0);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	private:
 | 
			
		||||
 | 
			
		||||
	static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
 | 
			
		||||
	static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
 | 
			
		||||
	void WorkerThread();
 | 
			
		||||
	void Start(DWORD dwArgc, PSTR *pszArgv);
 | 
			
		||||
	void Pause();
 | 
			
		||||
	void Continue();
 | 
			
		||||
	void Shutdown();
 | 
			
		||||
	static I2PService* s_service;
 | 
			
		||||
	PSTR m_name;
 | 
			
		||||
	SERVICE_STATUS m_status;
 | 
			
		||||
	SERVICE_STATUS_HANDLE m_statusHandle;
 | 
			
		||||
		static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
 | 
			
		||||
		static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
 | 
			
		||||
		void WorkerThread();
 | 
			
		||||
		void Start(DWORD dwArgc, PSTR *pszArgv);
 | 
			
		||||
		void Pause();
 | 
			
		||||
		void Continue();
 | 
			
		||||
		void Shutdown();
 | 
			
		||||
		static I2PService* s_service;
 | 
			
		||||
		PSTR m_name;
 | 
			
		||||
		SERVICE_STATUS m_status;
 | 
			
		||||
		SERVICE_STATUS_HANDLE m_statusHandle;
 | 
			
		||||
 | 
			
		||||
	BOOL m_fStopping;
 | 
			
		||||
	HANDLE m_hStoppedEvent;
 | 
			
		||||
		BOOL m_fStopping;
 | 
			
		||||
		HANDLE m_hStoppedEvent;
 | 
			
		||||
 | 
			
		||||
	std::thread* _worker;
 | 
			
		||||
		std::thread* _worker;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void InstallService(
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ void InstallService(
 | 
			
		|||
	PCSTR pszDependencies,
 | 
			
		||||
	PCSTR pszAccount,
 | 
			
		||||
	PCSTR pszPassword
 | 
			
		||||
	);
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
void UninstallService(PCSTR pszServiceName);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
//{{NO_DEPENDENCIES}}
 | 
			
		||||
#define MAINICON						101
 | 
			
		||||
#define MAINICON                  101
 | 
			
		||||
 | 
			
		||||
#ifdef APSTUDIO_INVOKED
 | 
			
		||||
#ifndef APSTUDIO_READONLY_SYMBOLS
 | 
			
		||||
#define _APS_NEXT_RESOURCE_VALUE		102
 | 
			
		||||
#define _APS_NEXT_COMMAND_VALUE			40001
 | 
			
		||||
#define _APS_NEXT_CONTROL_VALUE			1001
 | 
			
		||||
#define _APS_NEXT_SYMED_VALUE			101
 | 
			
		||||
#define _APS_NEXT_RESOURCE_VALUE  102
 | 
			
		||||
#define _APS_NEXT_COMMAND_VALUE   40001
 | 
			
		||||
#define _APS_NEXT_CONTROL_VALUE   1001
 | 
			
		||||
#define _APS_NEXT_SYMED_VALUE     101
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,8 +127,8 @@ namespace i2p
 | 
			
		|||
			i2p::context.SetNetID (netID);
 | 
			
		||||
			i2p::context.Init ();
 | 
			
		||||
 | 
			
		||||
			bool ipv6;		i2p::config::GetOption("ipv6", ipv6);
 | 
			
		||||
			bool ipv4;		i2p::config::GetOption("ipv4", ipv4);
 | 
			
		||||
			bool ipv6; i2p::config::GetOption("ipv6", ipv6);
 | 
			
		||||
			bool ipv4; i2p::config::GetOption("ipv4", ipv4);
 | 
			
		||||
#ifdef MESHNET
 | 
			
		||||
			// manual override for meshnet
 | 
			
		||||
			ipv4 = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +143,7 @@ namespace i2p
 | 
			
		|||
			i2p::context.SetSupportsV6 (ipv6);
 | 
			
		||||
			i2p::context.SetSupportsV4 (ipv4);
 | 
			
		||||
 | 
			
		||||
			bool ntcp;   i2p::config::GetOption("ntcp", ntcp);
 | 
			
		||||
			bool ntcp; i2p::config::GetOption("ntcp", ntcp);
 | 
			
		||||
			i2p::context.PublishNTCPAddress (ntcp, !ipv6);
 | 
			
		||||
			bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
 | 
			
		||||
			if (ntcp2)
 | 
			
		||||
| 
						 | 
				
			
			@ -172,10 +172,13 @@ namespace i2p
 | 
			
		|||
			SetMaxNumTransitTunnels (transitTunnels);
 | 
			
		||||
 | 
			
		||||
			bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
 | 
			
		||||
			if (isFloodfill) {
 | 
			
		||||
			if (isFloodfill)
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint(eLogInfo, "Daemon: router will be floodfill");
 | 
			
		||||
				i2p::context.SetFloodfill (true);
 | 
			
		||||
			}	else {
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				i2p::context.SetFloodfill (false);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -243,7 +246,8 @@ namespace i2p
 | 
			
		|||
					i2p::transport::transports.RestrictRoutesToFamilies(fams);
 | 
			
		||||
					restricted  = fams.size() > 0;
 | 
			
		||||
				}
 | 
			
		||||
				if (routers.length() > 0) {
 | 
			
		||||
				if (routers.length() > 0)
 | 
			
		||||
				{
 | 
			
		||||
					std::set<i2p::data::IdentHash> idents;
 | 
			
		||||
					size_t pos = 0, comma;
 | 
			
		||||
					do
 | 
			
		||||
| 
						 | 
				
			
			@ -279,7 +283,8 @@ namespace i2p
 | 
			
		|||
			i2p::data::netdb.Start();
 | 
			
		||||
 | 
			
		||||
			bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
 | 
			
		||||
			if (upnp) {
 | 
			
		||||
			if (upnp)
 | 
			
		||||
			{
 | 
			
		||||
				d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP);
 | 
			
		||||
				d.UPnP->Start ();
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -292,7 +297,7 @@ namespace i2p
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			bool ntcp; i2p::config::GetOption("ntcp", ntcp);
 | 
			
		||||
			bool ssu; i2p::config::GetOption("ssu", ssu);
 | 
			
		||||
			bool ssu;  i2p::config::GetOption("ssu", ssu);
 | 
			
		||||
			LogPrint(eLogInfo, "Daemon: starting Transports");
 | 
			
		||||
			if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
 | 
			
		||||
			if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
 | 
			
		||||
| 
						 | 
				
			
			@ -310,7 +315,8 @@ namespace i2p
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			bool http; i2p::config::GetOption("http.enabled", http);
 | 
			
		||||
			if (http) {
 | 
			
		||||
			if (http)
 | 
			
		||||
			{
 | 
			
		||||
				std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
 | 
			
		||||
				uint16_t    httpPort; i2p::config::GetOption("http.port", httpPort);
 | 
			
		||||
				LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
 | 
			
		||||
| 
						 | 
				
			
			@ -326,7 +332,6 @@ namespace i2p
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			LogPrint(eLogInfo, "Daemon: starting Tunnels");
 | 
			
		||||
			i2p::tunnel::tunnels.Start();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,9 +13,10 @@ namespace util
 | 
			
		|||
	class Daemon_Singleton
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
            virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
 | 
			
		||||
            virtual bool init(int argc, char* argv[]);
 | 
			
		||||
            virtual bool start();
 | 
			
		||||
 | 
			
		||||
			virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
 | 
			
		||||
			virtual bool init(int argc, char* argv[]);
 | 
			
		||||
			virtual bool start();
 | 
			
		||||
			virtual bool stop();
 | 
			
		||||
			virtual void run () {};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +24,7 @@ namespace util
 | 
			
		|||
			bool running;
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			Daemon_Singleton();
 | 
			
		||||
			virtual ~Daemon_Singleton();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +41,7 @@ namespace util
 | 
			
		|||
	class DaemonQT: public i2p::util::Daemon_Singleton
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			static DaemonQT& Instance()
 | 
			
		||||
			{
 | 
			
		||||
				static DaemonQT instance;
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +54,7 @@ namespace util
 | 
			
		|||
	class DaemonWin32 : public Daemon_Singleton
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			static DaemonWin32& Instance()
 | 
			
		||||
			{
 | 
			
		||||
				static DaemonWin32 instance;
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +76,7 @@ namespace util
 | 
			
		|||
	class DaemonAndroid: public i2p::util::Daemon_Singleton
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			static DaemonAndroid& Instance()
 | 
			
		||||
			{
 | 
			
		||||
				static DaemonAndroid instance;
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +88,7 @@ namespace util
 | 
			
		|||
	class DaemonLinux : public Daemon_Singleton
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			static DaemonLinux& Instance()
 | 
			
		||||
			{
 | 
			
		||||
				static DaemonLinux instance;
 | 
			
		||||
| 
						 | 
				
			
			@ -94,10 +100,12 @@ namespace util
 | 
			
		|||
			void run ();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::string pidfile;
 | 
			
		||||
			int pidFH;
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			int gracefulShutdownInterval; // in seconds
 | 
			
		||||
	};
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -892,8 +892,8 @@ namespace http {
 | 
			
		|||
	void HTTPConnection::Receive ()
 | 
			
		||||
	{
 | 
			
		||||
		m_Socket->async_read_some (boost::asio::buffer (m_Buffer, HTTP_CONNECTION_BUFFER_SIZE),
 | 
			
		||||
			 std::bind(&HTTPConnection::HandleReceive, shared_from_this (),
 | 
			
		||||
				 std::placeholders::_1, std::placeholders::_2));
 | 
			
		||||
			std::bind(&HTTPConnection::HandleReceive, shared_from_this (),
 | 
			
		||||
				std::placeholders::_1, std::placeholders::_2));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void HTTPConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,17 +79,17 @@ namespace http
 | 
			
		|||
			std::string m_Hostname;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
    //all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
 | 
			
		||||
    enum OutputFormatEnum { forWebConsole, forQtUi };
 | 
			
		||||
    void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat);
 | 
			
		||||
    void ShowLocalDestinations (std::stringstream& s);
 | 
			
		||||
    void ShowLeasesSets(std::stringstream& s);
 | 
			
		||||
    void ShowTunnels (std::stringstream& s);
 | 
			
		||||
    void ShowTransitTunnels (std::stringstream& s);
 | 
			
		||||
    void ShowTransports (std::stringstream& s);
 | 
			
		||||
    void ShowSAMSessions (std::stringstream& s);
 | 
			
		||||
    void ShowI2PTunnels (std::stringstream& s);
 | 
			
		||||
    void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
 | 
			
		||||
	//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
 | 
			
		||||
	enum OutputFormatEnum { forWebConsole, forQtUi };
 | 
			
		||||
	void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat);
 | 
			
		||||
	void ShowLocalDestinations (std::stringstream& s);
 | 
			
		||||
	void ShowLeasesSets(std::stringstream& s);
 | 
			
		||||
	void ShowTunnels (std::stringstream& s);
 | 
			
		||||
	void ShowTransitTunnels (std::stringstream& s);
 | 
			
		||||
	void ShowTransports (std::stringstream& s);
 | 
			
		||||
	void ShowSAMSessions (std::stringstream& s);
 | 
			
		||||
	void ShowI2PTunnels (std::stringstream& s);
 | 
			
		||||
	void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
 | 
			
		||||
} // http
 | 
			
		||||
} // i2p
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,29 +59,28 @@ namespace client
 | 
			
		|||
		m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
 | 
			
		||||
 | 
			
		||||
		// handlers
 | 
			
		||||
		m_MethodHandlers["Authenticate"]   = &I2PControlService::AuthenticateHandler;
 | 
			
		||||
		m_MethodHandlers["Echo"]           = &I2PControlService::EchoHandler;
 | 
			
		||||
		m_MethodHandlers["I2PControl"]     = &I2PControlService::I2PControlHandler;
 | 
			
		||||
		m_MethodHandlers["RouterInfo"]     = &I2PControlService::RouterInfoHandler;
 | 
			
		||||
		m_MethodHandlers["RouterManager"]  = &I2PControlService::RouterManagerHandler;
 | 
			
		||||
		m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
 | 
			
		||||
		m_MethodHandlers["ClientServicesInfo"]     = &I2PControlService::ClientServicesInfoHandler;
 | 
			
		||||
		m_MethodHandlers["Authenticate"]       = &I2PControlService::AuthenticateHandler;
 | 
			
		||||
		m_MethodHandlers["Echo"]               = &I2PControlService::EchoHandler;
 | 
			
		||||
		m_MethodHandlers["I2PControl"]         = &I2PControlService::I2PControlHandler;
 | 
			
		||||
		m_MethodHandlers["RouterInfo"]         = &I2PControlService::RouterInfoHandler;
 | 
			
		||||
		m_MethodHandlers["RouterManager"]      = &I2PControlService::RouterManagerHandler;
 | 
			
		||||
		m_MethodHandlers["NetworkSetting"]     = &I2PControlService::NetworkSettingHandler;
 | 
			
		||||
		m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
 | 
			
		||||
 | 
			
		||||
		// I2PControl
 | 
			
		||||
		m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
 | 
			
		||||
 | 
			
		||||
		// RouterInfo
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.uptime"]  = &I2PControlService::UptimeHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.status"]  = &I2PControlService::StatusHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.netdb.knownpeers"]   = &I2PControlService::NetDbKnownPeersHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.netdb.activepeers"]  = &I2PControlService::NetDbActivePeersHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"]  = &I2PControlService::InboundBandwidth1S;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.status"]         = &I2PControlService::NetStatusHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.uptime"]                    = &I2PControlService::UptimeHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.version"]                   = &I2PControlService::VersionHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.status"]                    = &I2PControlService::StatusHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.netdb.knownpeers"]          = &I2PControlService::NetDbKnownPeersHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.netdb.activepeers"]         = &I2PControlService::NetDbActivePeersHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"]         = &I2PControlService::InboundBandwidth1S;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"]        = &I2PControlService::OutboundBandwidth1S;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.status"]                = &I2PControlService::NetStatusHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
 | 
			
		||||
&I2PControlService::TunnelsSuccessRateHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"]   = &I2PControlService::TunnelsSuccessRateHandler;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.total.received.bytes"]  = &I2PControlService::NetTotalReceivedBytes;
 | 
			
		||||
		m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"]      = &I2PControlService::NetTotalSentBytes;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -97,10 +96,10 @@ namespace client
 | 
			
		|||
		// ClientServicesInfo
 | 
			
		||||
		m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
 | 
			
		||||
		m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
 | 
			
		||||
		m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
 | 
			
		||||
		m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
 | 
			
		||||
		m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
 | 
			
		||||
		m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
 | 
			
		||||
		m_ClientServicesInfoHandlers["SOCKS"]     = &I2PControlService::SOCKSInfoHandler;
 | 
			
		||||
		m_ClientServicesInfoHandlers["SAM"]       = &I2PControlService::SAMInfoHandler;
 | 
			
		||||
		m_ClientServicesInfoHandlers["BOB"]       = &I2PControlService::BOBInfoHandler;
 | 
			
		||||
		m_ClientServicesInfoHandlers["I2CP"]      = &I2PControlService::I2CPInfoHandler;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	I2PControlService::~I2PControlService ()
 | 
			
		||||
| 
						 | 
				
			
			@ -500,7 +499,7 @@ namespace client
 | 
			
		|||
		m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
 | 
			
		||||
		m_ShutdownTimer.async_wait (
 | 
			
		||||
			[](const boost::system::error_code& ecode)
 | 
			
		||||
		    {
 | 
			
		||||
			{
 | 
			
		||||
				Daemon.running = 0;
 | 
			
		||||
			});
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -514,7 +513,7 @@ namespace client
 | 
			
		|||
		m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
 | 
			
		||||
		m_ShutdownTimer.async_wait (
 | 
			
		||||
			[](const boost::system::error_code& ecode)
 | 
			
		||||
		    {
 | 
			
		||||
			{
 | 
			
		||||
				Daemon.running = 0;
 | 
			
		||||
			});
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ namespace client
 | 
			
		|||
	class I2PControlService
 | 
			
		||||
	{
 | 
			
		||||
		typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PControlService (const std::string& address, int port);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,10 +80,10 @@ namespace transport
 | 
			
		|||
	void UPnP::Discover ()
 | 
			
		||||
	{
 | 
			
		||||
		bool isError;
 | 
			
		||||
        int err;
 | 
			
		||||
		int err;
 | 
			
		||||
 | 
			
		||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
 | 
			
		||||
        err = UPNPDISCOVER_SUCCESS;
 | 
			
		||||
		err = UPNPDISCOVER_SUCCESS;
 | 
			
		||||
 | 
			
		||||
#if (MINIUPNPC_API_VERSION >= 14)
 | 
			
		||||
		m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
 | 
			
		||||
| 
						 | 
				
			
			@ -92,9 +92,9 @@ namespace transport
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
		isError = err != UPNPDISCOVER_SUCCESS;
 | 
			
		||||
#else  // MINIUPNPC_API_VERSION >= 8
 | 
			
		||||
        err = 0;
 | 
			
		||||
        m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
 | 
			
		||||
#else // MINIUPNPC_API_VERSION >= 8
 | 
			
		||||
		err = 0;
 | 
			
		||||
		m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
 | 
			
		||||
		isError = m_Devlist == NULL;
 | 
			
		||||
#endif // MINIUPNPC_API_VERSION >= 8
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -105,15 +105,15 @@ namespace transport
 | 
			
		|||
 | 
			
		||||
		if (isError)
 | 
			
		||||
		{
 | 
			
		||||
            LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
 | 
			
		||||
			LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
 | 
			
		||||
        m_upnpUrlsInitialized=err!=0;
 | 
			
		||||
		m_upnpUrlsInitialized = err != 0;
 | 
			
		||||
		if (err == UPNP_IGD_VALID_CONNECTED)
 | 
			
		||||
		{
 | 
			
		||||
            err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
 | 
			
		||||
			err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
 | 
			
		||||
			if(err != UPNPCOMMAND_SUCCESS)
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
 | 
			
		||||
| 
						 | 
				
			
			@ -124,14 +124,14 @@ namespace transport
 | 
			
		|||
				LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
 | 
			
		||||
				if (!m_externalIPAddress[0])
 | 
			
		||||
				{
 | 
			
		||||
                    LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
 | 
			
		||||
					LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
            LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
 | 
			
		||||
			LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -182,7 +182,7 @@ namespace transport
 | 
			
		|||
		err = CheckMapping (strPort.c_str (), strType.c_str ());
 | 
			
		||||
		if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
 | 
			
		||||
		{
 | 
			
		||||
            LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
 | 
			
		||||
			LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
 | 
			
		||||
 | 
			
		||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
 | 
			
		||||
			err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +202,7 @@ namespace transport
 | 
			
		|||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
            LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
 | 
			
		||||
			LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -219,14 +219,14 @@ namespace transport
 | 
			
		|||
 | 
			
		||||
	void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
 | 
			
		||||
	{
 | 
			
		||||
        if(!m_upnpUrlsInitialized) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
		if(!m_upnpUrlsInitialized) {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		std::string strType (GetProto (address)), strPort (std::to_string (address->port));
 | 
			
		||||
		int err = UPNPCOMMAND_SUCCESS;
 | 
			
		||||
 | 
			
		||||
		err = CheckMapping (strPort.c_str (), strType.c_str ());
 | 
			
		||||
        if (err == UPNPCOMMAND_SUCCESS)
 | 
			
		||||
		if (err == UPNPCOMMAND_SUCCESS)
 | 
			
		||||
		{
 | 
			
		||||
			err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
 | 
			
		||||
			LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
 | 
			
		||||
| 
						 | 
				
			
			@ -237,11 +237,11 @@ namespace transport
 | 
			
		|||
	{
 | 
			
		||||
		freeUPNPDevlist (m_Devlist);
 | 
			
		||||
		m_Devlist = 0;
 | 
			
		||||
        if(m_upnpUrlsInitialized){
 | 
			
		||||
            FreeUPNPUrls (&m_upnpUrls);
 | 
			
		||||
            m_upnpUrlsInitialized=false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
		if(m_upnpUrlsInitialized){
 | 
			
		||||
			FreeUPNPUrls (&m_upnpUrls);
 | 
			
		||||
			m_upnpUrlsInitialized=false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,41 +33,41 @@ namespace transport
 | 
			
		|||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
		UPnP ();
 | 
			
		||||
		~UPnP ();
 | 
			
		||||
		void Close ();
 | 
			
		||||
			UPnP ();
 | 
			
		||||
			~UPnP ();
 | 
			
		||||
			void Close ();
 | 
			
		||||
 | 
			
		||||
		void Start ();
 | 
			
		||||
		void Stop ();
 | 
			
		||||
			void Start ();
 | 
			
		||||
			void Stop ();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
		void Discover ();
 | 
			
		||||
		int  CheckMapping (const char* port, const char* type);
 | 
			
		||||
		void PortMapping ();
 | 
			
		||||
		void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
 | 
			
		||||
		void CloseMapping ();
 | 
			
		||||
		void CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
 | 
			
		||||
			void Discover ();
 | 
			
		||||
			int  CheckMapping (const char* port, const char* type);
 | 
			
		||||
			void PortMapping ();
 | 
			
		||||
			void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
 | 
			
		||||
			void CloseMapping ();
 | 
			
		||||
			void CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
 | 
			
		||||
 | 
			
		||||
		void Run ();
 | 
			
		||||
		std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address);
 | 
			
		||||
			void Run ();
 | 
			
		||||
			std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
		bool m_IsRunning;
 | 
			
		||||
		std::unique_ptr<std::thread> m_Thread;
 | 
			
		||||
		std::condition_variable m_Started;
 | 
			
		||||
		std::mutex m_StartedMutex;
 | 
			
		||||
		boost::asio::io_service m_Service;
 | 
			
		||||
		boost::asio::deadline_timer m_Timer;
 | 
			
		||||
        bool m_upnpUrlsInitialized=false;
 | 
			
		||||
		struct UPNPUrls m_upnpUrls;
 | 
			
		||||
		struct IGDdatas m_upnpData;
 | 
			
		||||
			bool m_IsRunning;
 | 
			
		||||
			std::unique_ptr<std::thread> m_Thread;
 | 
			
		||||
			std::condition_variable m_Started;
 | 
			
		||||
			std::mutex m_StartedMutex;
 | 
			
		||||
			boost::asio::io_service m_Service;
 | 
			
		||||
			boost::asio::deadline_timer m_Timer;
 | 
			
		||||
			bool m_upnpUrlsInitialized = false;
 | 
			
		||||
			struct UPNPUrls m_upnpUrls;
 | 
			
		||||
			struct IGDdatas m_upnpData;
 | 
			
		||||
 | 
			
		||||
		// For miniupnpc
 | 
			
		||||
		struct UPNPDev * m_Devlist = 0;
 | 
			
		||||
		char m_NetworkAddr[64];
 | 
			
		||||
		char m_externalIPAddress[40];
 | 
			
		||||
			// For miniupnpc
 | 
			
		||||
			struct UPNPDev * m_Devlist = 0;
 | 
			
		||||
			char m_NetworkAddr[64];
 | 
			
		||||
			char m_externalIPAddress[40];
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -79,10 +79,10 @@ namespace transport {
 | 
			
		|||
	class UPnP {
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
		UPnP () {};
 | 
			
		||||
		~UPnP () {};
 | 
			
		||||
		void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
 | 
			
		||||
		void Stop () {};
 | 
			
		||||
			UPnP () {};
 | 
			
		||||
			~UPnP () {};
 | 
			
		||||
			void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
 | 
			
		||||
			void Stop () {};
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -196,5 +196,4 @@ namespace i2p
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@
 | 
			
		|||
#include "Daemon.h"
 | 
			
		||||
 | 
			
		||||
#if defined(QT_GUI_LIB)
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
namespace qt
 | 
			
		||||
| 
						 | 
				
			
			@ -10,11 +9,11 @@ namespace qt
 | 
			
		|||
	int RunQT (int argc, char* argv[]);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main( int argc, char* argv[] )
 | 
			
		||||
{
 | 
			
		||||
	return i2p::qt::RunQT (argc, argv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
int main( int argc, char* argv[] )
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										212
									
								
								libi2pd/Base.cpp
									
										
									
									
									
								
							
							
						
						
									
										212
									
								
								libi2pd/Base.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -7,7 +7,8 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
namespace data
 | 
			
		||||
{
 | 
			
		||||
	static const char T32[32] = {
 | 
			
		||||
	static const char T32[32] =
 | 
			
		||||
	{
 | 
			
		||||
		'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
 | 
			
		||||
		'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
 | 
			
		||||
		'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
 | 
			
		||||
| 
						 | 
				
			
			@ -29,15 +30,16 @@ namespace data
 | 
			
		|||
	* Direct Substitution Table
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	static const char T64[64] = {
 | 
			
		||||
		       'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
 | 
			
		||||
		       'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
 | 
			
		||||
		       'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
 | 
			
		||||
		       'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
 | 
			
		||||
		       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
 | 
			
		||||
		       'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
 | 
			
		||||
		       'w', 'x', 'y', 'z', '0', '1', '2', '3',
 | 
			
		||||
		       '4', '5', '6', '7', '8', '9', '-', '~'
 | 
			
		||||
	static const char T64[64] =
 | 
			
		||||
	{
 | 
			
		||||
		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
 | 
			
		||||
		'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
 | 
			
		||||
		'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
 | 
			
		||||
		'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
 | 
			
		||||
		'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
 | 
			
		||||
		'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
 | 
			
		||||
		'w', 'x', 'y', 'z', '0', '1', '2', '3',
 | 
			
		||||
		'4', '5', '6', '7', '8', '9', '-', '~'
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	const char * GetBase64SubstitutionTable ()
 | 
			
		||||
| 
						 | 
				
			
			@ -67,14 +69,12 @@ namespace data
 | 
			
		|||
	*
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	size_t                                /* Number of bytes in the encoded buffer */
 | 
			
		||||
	ByteStreamToBase64 (
 | 
			
		||||
		    const uint8_t * InBuffer,           /* Input buffer, binary data */
 | 
			
		||||
		    size_t    InCount,              /* Number of bytes in the input buffer */
 | 
			
		||||
		    char  * OutBuffer,          /* output buffer */
 | 
			
		||||
		size_t len			   /* length of output buffer */
 | 
			
		||||
	size_t ByteStreamToBase64 (   /* Number of bytes in the encoded buffer */
 | 
			
		||||
		const uint8_t * InBuffer, /* Input buffer, binary data */
 | 
			
		||||
		size_t InCount,           /* Number of bytes in the input buffer */
 | 
			
		||||
		char * OutBuffer,         /* output buffer */
 | 
			
		||||
		size_t len                /* length of output buffer */
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		unsigned char * ps;
 | 
			
		||||
		unsigned char * pd;
 | 
			
		||||
| 
						 | 
				
			
			@ -83,55 +83,60 @@ namespace data
 | 
			
		|||
		int             i;
 | 
			
		||||
		int             n;
 | 
			
		||||
		int             m;
 | 
			
		||||
		size_t outCount;
 | 
			
		||||
		size_t          outCount;
 | 
			
		||||
 | 
			
		||||
		ps = (unsigned char *)InBuffer;
 | 
			
		||||
		n = InCount/3;
 | 
			
		||||
		m = InCount%3;
 | 
			
		||||
		n = InCount / 3;
 | 
			
		||||
		m = InCount % 3;
 | 
			
		||||
		if (!m)
 | 
			
		||||
		     outCount = 4*n;
 | 
			
		||||
			outCount = 4 * n;
 | 
			
		||||
		else
 | 
			
		||||
		     outCount = 4*(n+1);
 | 
			
		||||
			outCount = 4 * (n + 1);
 | 
			
		||||
 | 
			
		||||
		if (outCount > len) return 0;
 | 
			
		||||
 | 
			
		||||
		pd = (unsigned char *)OutBuffer;
 | 
			
		||||
		for ( i = 0; i<n; i++ ){
 | 
			
		||||
		     acc_1 = *ps++;
 | 
			
		||||
		     acc_2 = (acc_1<<4)&0x30;
 | 
			
		||||
		     acc_1 >>= 2;              /* base64 digit #1 */
 | 
			
		||||
		     *pd++ = T64[acc_1];
 | 
			
		||||
		     acc_1 = *ps++;
 | 
			
		||||
		     acc_2 |= acc_1 >> 4;      /* base64 digit #2 */
 | 
			
		||||
		     *pd++ = T64[acc_2];
 | 
			
		||||
		     acc_1 &= 0x0f;
 | 
			
		||||
		     acc_1 <<=2;
 | 
			
		||||
		     acc_2 = *ps++;
 | 
			
		||||
		     acc_1 |= acc_2>>6;        /* base64 digit #3 */
 | 
			
		||||
		     *pd++ = T64[acc_1];
 | 
			
		||||
		     acc_2 &= 0x3f;            /* base64 digit #4 */
 | 
			
		||||
		     *pd++ = T64[acc_2];
 | 
			
		||||
		for ( i = 0; i < n; i++ )
 | 
			
		||||
		{
 | 
			
		||||
			acc_1 = *ps++;
 | 
			
		||||
			acc_2 = (acc_1 << 4) & 0x30;
 | 
			
		||||
			acc_1 >>= 2;                 /* base64 digit #1 */
 | 
			
		||||
			*pd++ = T64[acc_1];
 | 
			
		||||
			acc_1 = *ps++;
 | 
			
		||||
			acc_2 |= acc_1 >> 4;         /* base64 digit #2 */
 | 
			
		||||
			*pd++ = T64[acc_2];
 | 
			
		||||
			acc_1 &= 0x0f;
 | 
			
		||||
			acc_1 <<= 2;
 | 
			
		||||
			acc_2 = *ps++;
 | 
			
		||||
			acc_1 |= acc_2 >> 6;         /* base64 digit #3 */
 | 
			
		||||
			*pd++ = T64[acc_1];
 | 
			
		||||
			acc_2 &= 0x3f;               /* base64 digit #4 */
 | 
			
		||||
			*pd++ = T64[acc_2];
 | 
			
		||||
		}
 | 
			
		||||
		if ( m == 1 ){
 | 
			
		||||
		     acc_1 = *ps++;
 | 
			
		||||
		     acc_2 = (acc_1<<4)&0x3f;  /* base64 digit #2 */
 | 
			
		||||
		     acc_1 >>= 2;              /* base64 digit #1 */
 | 
			
		||||
		     *pd++ = T64[acc_1];
 | 
			
		||||
		     *pd++ = T64[acc_2];
 | 
			
		||||
		     *pd++ = P64;
 | 
			
		||||
		     *pd++ = P64;
 | 
			
		||||
		if ( m == 1 )
 | 
			
		||||
		{
 | 
			
		||||
			acc_1 = *ps++;
 | 
			
		||||
			acc_2 = (acc_1 << 4) & 0x3f; /* base64 digit #2 */
 | 
			
		||||
			acc_1 >>= 2;                 /* base64 digit #1 */
 | 
			
		||||
			*pd++ = T64[acc_1];
 | 
			
		||||
			*pd++ = T64[acc_2];
 | 
			
		||||
			*pd++ = P64;
 | 
			
		||||
			*pd++ = P64;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
		else if ( m == 2 ){
 | 
			
		||||
		     acc_1 = *ps++;
 | 
			
		||||
		     acc_2 = (acc_1<<4)&0x3f;
 | 
			
		||||
		     acc_1 >>= 2;              /* base64 digit #1 */
 | 
			
		||||
		     *pd++ = T64[acc_1];
 | 
			
		||||
		     acc_1 = *ps++;
 | 
			
		||||
		     acc_2 |= acc_1 >> 4;      /* base64 digit #2 */
 | 
			
		||||
		     *pd++ = T64[acc_2];
 | 
			
		||||
		     acc_1 &= 0x0f;
 | 
			
		||||
		     acc_1 <<=2;               /* base64 digit #3 */
 | 
			
		||||
		     *pd++ = T64[acc_1];
 | 
			
		||||
		     *pd++ = P64;
 | 
			
		||||
		else if ( m == 2 )
 | 
			
		||||
		{
 | 
			
		||||
			acc_1 = *ps++;
 | 
			
		||||
			acc_2 = (acc_1 << 4) & 0x3f;
 | 
			
		||||
			acc_1 >>= 2;                 /* base64 digit #1 */
 | 
			
		||||
			*pd++ = T64[acc_1];
 | 
			
		||||
			acc_1 = *ps++;
 | 
			
		||||
			acc_2 |= acc_1 >> 4;         /* base64 digit #2 */
 | 
			
		||||
			*pd++ = T64[acc_2];
 | 
			
		||||
			acc_1 &= 0x0f;
 | 
			
		||||
			acc_1 <<= 2;                 /* base64 digit #3 */
 | 
			
		||||
			*pd++ = T64[acc_1];
 | 
			
		||||
			*pd++ = P64;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return outCount;
 | 
			
		||||
| 
						 | 
				
			
			@ -147,12 +152,11 @@ namespace data
 | 
			
		|||
	*
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	size_t                              /* Number of output bytes */
 | 
			
		||||
	Base64ToByteStream (
 | 
			
		||||
		      const char * InBuffer,           /* BASE64 encoded buffer */
 | 
			
		||||
		      size_t    InCount,          /* Number of input bytes */
 | 
			
		||||
		      uint8_t  * OutBuffer,	/* output buffer length */
 | 
			
		||||
		  size_t len         	/* length of output buffer */
 | 
			
		||||
	size_t Base64ToByteStream ( /* Number of output bytes */
 | 
			
		||||
		const char * InBuffer,  /* BASE64 encoded buffer */
 | 
			
		||||
		size_t InCount,         /* Number of input bytes */
 | 
			
		||||
		uint8_t * OutBuffer,    /* output buffer length */
 | 
			
		||||
		size_t len              /* length of output buffer */
 | 
			
		||||
	)
 | 
			
		||||
	{
 | 
			
		||||
		unsigned char * ps;
 | 
			
		||||
| 
						 | 
				
			
			@ -162,42 +166,52 @@ namespace data
 | 
			
		|||
		int             i;
 | 
			
		||||
		int             n;
 | 
			
		||||
		int             m;
 | 
			
		||||
		size_t outCount;
 | 
			
		||||
		size_t          outCount;
 | 
			
		||||
 | 
			
		||||
		if (isFirstTime)
 | 
			
		||||
			iT64Build();
 | 
			
		||||
 | 
			
		||||
		n = InCount / 4;
 | 
			
		||||
		m = InCount % 4;
 | 
			
		||||
 | 
			
		||||
		if (isFirstTime) iT64Build();
 | 
			
		||||
		n = InCount/4;
 | 
			
		||||
		m = InCount%4;
 | 
			
		||||
		if (InCount && !m)
 | 
			
		||||
		     outCount = 3*n;
 | 
			
		||||
		else {
 | 
			
		||||
		     outCount = 0;
 | 
			
		||||
		     return 0;
 | 
			
		||||
			outCount = 3 * n;
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			outCount = 0;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ps = (unsigned char *)(InBuffer + InCount - 1);
 | 
			
		||||
		while ( *ps-- == P64 ) outCount--;
 | 
			
		||||
		while ( *ps-- == P64 )
 | 
			
		||||
			outCount--;
 | 
			
		||||
		ps = (unsigned char *)InBuffer;
 | 
			
		||||
 | 
			
		||||
		if (outCount > len) return -1;
 | 
			
		||||
		if (outCount > len)
 | 
			
		||||
			return -1;
 | 
			
		||||
 | 
			
		||||
		pd = OutBuffer;
 | 
			
		||||
		auto endOfOutBuffer = OutBuffer + outCount;
 | 
			
		||||
		for ( i = 0; i < n; i++ ){
 | 
			
		||||
		     acc_1 = iT64[*ps++];
 | 
			
		||||
		     acc_2 = iT64[*ps++];
 | 
			
		||||
		     acc_1 <<= 2;
 | 
			
		||||
		     acc_1 |= acc_2>>4;
 | 
			
		||||
		     *pd++  = acc_1;
 | 
			
		||||
			 if (pd >= endOfOutBuffer) break;
 | 
			
		||||
		for ( i = 0; i < n; i++ )
 | 
			
		||||
		{
 | 
			
		||||
			acc_1 = iT64[*ps++];
 | 
			
		||||
			acc_2 = iT64[*ps++];
 | 
			
		||||
			acc_1 <<= 2;
 | 
			
		||||
			acc_1 |= acc_2 >> 4;
 | 
			
		||||
			*pd++ = acc_1;
 | 
			
		||||
			if (pd >= endOfOutBuffer)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
		     acc_2 <<= 4;
 | 
			
		||||
		     acc_1 = iT64[*ps++];
 | 
			
		||||
		     acc_2 |= acc_1 >> 2;
 | 
			
		||||
		     *pd++ = acc_2;
 | 
			
		||||
			  if (pd >= endOfOutBuffer) break;
 | 
			
		||||
			acc_2 <<= 4;
 | 
			
		||||
			acc_1 = iT64[*ps++];
 | 
			
		||||
			acc_2 |= acc_1 >> 2;
 | 
			
		||||
			*pd++ = acc_2;
 | 
			
		||||
			if (pd >= endOfOutBuffer)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
		     acc_2 = iT64[*ps++];
 | 
			
		||||
		     acc_2 |= acc_1 << 6;
 | 
			
		||||
		     *pd++ = acc_2;
 | 
			
		||||
			acc_2 = iT64[*ps++];
 | 
			
		||||
			acc_2 |= acc_1 << 6;
 | 
			
		||||
			*pd++ = acc_2;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return outCount;
 | 
			
		||||
| 
						 | 
				
			
			@ -206,20 +220,25 @@ namespace data
 | 
			
		|||
	size_t Base64EncodingBufferSize (const size_t input_size)
 | 
			
		||||
	{
 | 
			
		||||
		auto d = div (input_size, 3);
 | 
			
		||||
		if (d.rem) d.quot++;
 | 
			
		||||
		return 4*d.quot;
 | 
			
		||||
		if (d.rem)
 | 
			
		||||
			d.quot++;
 | 
			
		||||
 | 
			
		||||
		return 4 * d.quot;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::string ToBase64Standard (const std::string& in)
 | 
			
		||||
	{
 | 
			
		||||
		auto len = Base64EncodingBufferSize (in.length ());
 | 
			
		||||
		char * str = new char[len+1];
 | 
			
		||||
		char * str = new char[len + 1];
 | 
			
		||||
		auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len);
 | 
			
		||||
		str[l] = 0;
 | 
			
		||||
		// replace '-' by '+' and '~' by '/'
 | 
			
		||||
		for (size_t i = 0; i < l; i++)
 | 
			
		||||
			if (str[i] == '-') str[i] = '+';
 | 
			
		||||
			else if (str[i] == '~') str[i] = '/';
 | 
			
		||||
			if (str[i] == '-')
 | 
			
		||||
				str[i] = '+';
 | 
			
		||||
			else if (str[i] == '~')
 | 
			
		||||
				str[i] = '/';
 | 
			
		||||
 | 
			
		||||
		std::string s(str);
 | 
			
		||||
		delete[] str;
 | 
			
		||||
		return s;
 | 
			
		||||
| 
						 | 
				
			
			@ -236,10 +255,10 @@ namespace data
 | 
			
		|||
 | 
			
		||||
	static void iT64Build()
 | 
			
		||||
	{
 | 
			
		||||
		int  i;
 | 
			
		||||
		int i;
 | 
			
		||||
		isFirstTime = 0;
 | 
			
		||||
		for ( i=0; i<256; i++ ) iT64[i] = -1;
 | 
			
		||||
		for ( i=0; i<64; i++ ) iT64[(int)T64[i]] = i;
 | 
			
		||||
		for ( i = 0; i < 256; i++ ) iT64[i] = -1;
 | 
			
		||||
		for ( i = 0; i < 64; i++ ) iT64[(int)T64[i]] = i;
 | 
			
		||||
		iT64[(int)P64] = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -302,4 +321,3 @@ namespace data
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,9 +15,9 @@ namespace data {
 | 
			
		|||
	size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
 | 
			
		||||
	size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
 | 
			
		||||
 | 
			
		||||
 	/**
 | 
			
		||||
     Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
 | 
			
		||||
   	*/
 | 
			
		||||
	/**
 | 
			
		||||
	 Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
 | 
			
		||||
	*/
 | 
			
		||||
	size_t Base64EncodingBufferSize(const size_t input_size);
 | 
			
		||||
 | 
			
		||||
	std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -314,4 +314,3 @@ namespace data
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,10 +5,10 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
namespace cpu
 | 
			
		||||
{
 | 
			
		||||
  extern bool aesni;
 | 
			
		||||
  extern bool avx;
 | 
			
		||||
	extern bool aesni;
 | 
			
		||||
	extern bool avx;
 | 
			
		||||
 | 
			
		||||
  void Detect();
 | 
			
		||||
	void Detect();
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,34 +21,34 @@ namespace chacha
 | 
			
		|||
{
 | 
			
		||||
void u32t8le(uint32_t v, uint8_t * p)
 | 
			
		||||
{
 | 
			
		||||
    p[0] = v & 0xff;
 | 
			
		||||
    p[1] = (v >> 8) & 0xff;
 | 
			
		||||
    p[2] = (v >> 16) & 0xff;
 | 
			
		||||
    p[3] = (v >> 24) & 0xff;
 | 
			
		||||
	p[0] = v & 0xff;
 | 
			
		||||
	p[1] = (v >> 8) & 0xff;
 | 
			
		||||
	p[2] = (v >> 16) & 0xff;
 | 
			
		||||
	p[3] = (v >> 24) & 0xff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t u8t32le(const uint8_t * p)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t value = p[3];
 | 
			
		||||
	uint32_t value = p[3];
 | 
			
		||||
 | 
			
		||||
    value = (value << 8) | p[2];
 | 
			
		||||
    value = (value << 8) | p[1];
 | 
			
		||||
    value = (value << 8) | p[0];
 | 
			
		||||
	value = (value << 8) | p[2];
 | 
			
		||||
	value = (value << 8) | p[1];
 | 
			
		||||
	value = (value << 8) | p[0];
 | 
			
		||||
 | 
			
		||||
    return value;
 | 
			
		||||
	return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t rotl32(uint32_t x, int n)
 | 
			
		||||
{
 | 
			
		||||
    return x << n | (x >> (-n & 31));
 | 
			
		||||
	return x << n | (x >> (-n & 31));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void quarterround(uint32_t *x, int a, int b, int c, int d)
 | 
			
		||||
{
 | 
			
		||||
    x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16);
 | 
			
		||||
    x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12);
 | 
			
		||||
    x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a],  8);
 | 
			
		||||
    x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c],  7);
 | 
			
		||||
	x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16);
 | 
			
		||||
	x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12);
 | 
			
		||||
	x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a],  8);
 | 
			
		||||
	x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c],  7);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -61,24 +61,23 @@ void Chacha20Block::operator << (const Chacha20State & st)
 | 
			
		|||
 | 
			
		||||
void block (Chacha20State &input, int rounds)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    Chacha20State x;
 | 
			
		||||
    x.Copy(input);
 | 
			
		||||
 | 
			
		||||
    for (i = rounds; i > 0; i -= 2) 
 | 
			
		||||
    {
 | 
			
		||||
        quarterround(x.data, 0, 4,  8, 12);
 | 
			
		||||
        quarterround(x.data, 1, 5,  9, 13);
 | 
			
		||||
        quarterround(x.data, 2, 6, 10, 14);
 | 
			
		||||
        quarterround(x.data, 3, 7, 11, 15);
 | 
			
		||||
        quarterround(x.data, 0, 5, 10, 15);
 | 
			
		||||
        quarterround(x.data, 1, 6, 11, 12);
 | 
			
		||||
        quarterround(x.data, 2, 7,  8, 13);
 | 
			
		||||
        quarterround(x.data, 3, 4,  9, 14);
 | 
			
		||||
    }
 | 
			
		||||
    x += input;
 | 
			
		||||
    input.block << x;
 | 
			
		||||
	int i;
 | 
			
		||||
	Chacha20State x;
 | 
			
		||||
	x.Copy(input);
 | 
			
		||||
 | 
			
		||||
	for (i = rounds; i > 0; i -= 2)
 | 
			
		||||
	{
 | 
			
		||||
		quarterround(x.data, 0, 4,  8, 12);
 | 
			
		||||
		quarterround(x.data, 1, 5,  9, 13);
 | 
			
		||||
		quarterround(x.data, 2, 6, 10, 14);
 | 
			
		||||
		quarterround(x.data, 3, 7, 11, 15);
 | 
			
		||||
		quarterround(x.data, 0, 5, 10, 15);
 | 
			
		||||
		quarterround(x.data, 1, 6, 11, 12);
 | 
			
		||||
		quarterround(x.data, 2, 7,  8, 13);
 | 
			
		||||
		quarterround(x.data, 3, 4,  9, 14);
 | 
			
		||||
	}
 | 
			
		||||
	x += input;
 | 
			
		||||
	input.block << x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
 | 
			
		||||
| 
						 | 
				
			
			@ -88,11 +87,11 @@ void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t *
 | 
			
		|||
	state.data[2] = 0x79622d32;
 | 
			
		||||
	state.data[3] = 0x6b206574;
 | 
			
		||||
	for (size_t i = 0; i < 8; i++)
 | 
			
		||||
	    state.data[4 + i] = chacha::u8t32le(key + i * 4);
 | 
			
		||||
		state.data[4 + i] = chacha::u8t32le(key + i * 4);
 | 
			
		||||
 | 
			
		||||
	state.data[12] = htole32 (counter);
 | 
			
		||||
	for (size_t i = 0; i < 3; i++)
 | 
			
		||||
	    state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
 | 
			
		||||
		state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Chacha20SetCounter (Chacha20State& state, uint32_t counter)
 | 
			
		||||
| 
						 | 
				
			
			@ -117,22 +116,22 @@ void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz)
 | 
			
		|||
	}
 | 
			
		||||
	for (size_t i = 0; i < sz; i += chacha::blocksize)
 | 
			
		||||
	{
 | 
			
		||||
	    chacha::block(state, chacha::rounds);
 | 
			
		||||
	    state.data[12]++;
 | 
			
		||||
	    for (size_t j = i; j < i + chacha::blocksize; j++) 
 | 
			
		||||
	    {
 | 
			
		||||
	        if (j >= sz) 
 | 
			
		||||
		chacha::block(state, chacha::rounds);
 | 
			
		||||
		state.data[12]++;
 | 
			
		||||
		for (size_t j = i; j < i + chacha::blocksize; j++)
 | 
			
		||||
		{
 | 
			
		||||
			if (j >= sz)
 | 
			
		||||
			{
 | 
			
		||||
				state.offset = j & 0x3F; // % 64
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
	        buf[j] ^= state.block.data[j - i];
 | 
			
		||||
	    }
 | 
			
		||||
			buf[j] ^= state.block.data[j - i];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace chacha
 | 
			
		||||
} // namespace crypto
 | 
			
		||||
} // namespace i2p
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,8 +21,8 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
namespace crypto
 | 
			
		||||
{
 | 
			
		||||
 	const std::size_t CHACHA20_KEY_BYTES = 32;
 | 
			
		||||
  	const std::size_t CHACHA20_NOUNCE_BYTES = 12;
 | 
			
		||||
	const std::size_t CHACHA20_KEY_BYTES = 32;
 | 
			
		||||
	const std::size_t CHACHA20_NOUNCE_BYTES = 12;
 | 
			
		||||
 | 
			
		||||
namespace chacha
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -32,12 +32,12 @@ namespace chacha
 | 
			
		|||
	struct Chacha20State;
 | 
			
		||||
	struct Chacha20Block
 | 
			
		||||
	{
 | 
			
		||||
	  Chacha20Block () {};
 | 
			
		||||
	  Chacha20Block (Chacha20Block &&) = delete;
 | 
			
		||||
		Chacha20Block () {};
 | 
			
		||||
		Chacha20Block (Chacha20Block &&) = delete;
 | 
			
		||||
 | 
			
		||||
	  uint8_t data[blocksize];
 | 
			
		||||
		uint8_t data[blocksize];
 | 
			
		||||
 | 
			
		||||
	  void operator << (const Chacha20State & st);
 | 
			
		||||
		void operator << (const Chacha20State & st);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct Chacha20State
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ namespace chacha
 | 
			
		|||
 | 
			
		||||
		void Copy(const Chacha20State & other)
 | 
			
		||||
		{
 | 
			
		||||
		   memcpy(data, other.data, sizeof(uint32_t) * 16);
 | 
			
		||||
			memcpy(data, other.data, sizeof(uint32_t) * 16);
 | 
			
		||||
		}
 | 
			
		||||
		uint32_t data[16];
 | 
			
		||||
		Chacha20Block block;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,9 +64,9 @@ namespace chacha
 | 
			
		|||
	void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
 | 
			
		||||
	void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
 | 
			
		||||
	void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
 | 
			
		||||
}
 | 
			
		||||
} 
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
} // namespace chacha
 | 
			
		||||
} // namespace crypto
 | 
			
		||||
} // namespace i2p
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -242,7 +242,7 @@ namespace config {
 | 
			
		|||
				"1.pool.ntp.org,"
 | 
			
		||||
				"2.pool.ntp.org,"
 | 
			
		||||
				"3.pool.ntp.org"
 | 
			
		||||
			),  "Comma separated list of NTCP servers")
 | 
			
		||||
			),                                                             "Comma separated list of NTCP servers")
 | 
			
		||||
			("nettime.ntpsyncinterval", value<int>()->default_value(72),   "NTP sync interval in hours (default: 72)")
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										169
									
								
								libi2pd/Config.h
									
										
									
									
									
								
							
							
						
						
									
										169
									
								
								libi2pd/Config.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -18,98 +18,101 @@
 | 
			
		|||
 | 
			
		||||
namespace i2p {
 | 
			
		||||
namespace config {
 | 
			
		||||
  extern boost::program_options::variables_map m_Options;
 | 
			
		||||
	extern boost::program_options::variables_map m_Options;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief  Initialize list of acceptable parameters
 | 
			
		||||
   *
 | 
			
		||||
   * Should be called before any Parse* functions.
 | 
			
		||||
   */
 | 
			
		||||
  void Init();
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief  Initialize list of acceptable parameters
 | 
			
		||||
	 *
 | 
			
		||||
	 * Should be called before any Parse* functions.
 | 
			
		||||
	 */
 | 
			
		||||
	void Init();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief  Parse cmdline parameters, and show help if requested
 | 
			
		||||
   * @param  argc  Cmdline arguments count, should be passed from main().
 | 
			
		||||
   * @param  argv  Cmdline parameters array, should be passed from main()
 | 
			
		||||
   *
 | 
			
		||||
   * If --help is given in parameters, shows its list with description
 | 
			
		||||
   * and terminates the program with exitcode 0.
 | 
			
		||||
   *
 | 
			
		||||
   * In case of parameter misuse boost throws an exception.
 | 
			
		||||
   * We internally handle type boost::program_options::unknown_option,
 | 
			
		||||
   * and then terminate the program with exitcode 1.
 | 
			
		||||
   *
 | 
			
		||||
   * Other exceptions will be passed to higher level.
 | 
			
		||||
   */
 | 
			
		||||
  void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief  Parse cmdline parameters, and show help if requested
 | 
			
		||||
	 * @param  argc  Cmdline arguments count, should be passed from main().
 | 
			
		||||
	 * @param  argv  Cmdline parameters array, should be passed from main()
 | 
			
		||||
	 *
 | 
			
		||||
	 * If --help is given in parameters, shows its list with description
 | 
			
		||||
	 * and terminates the program with exitcode 0.
 | 
			
		||||
	 *
 | 
			
		||||
	 * In case of parameter misuse boost throws an exception.
 | 
			
		||||
	 * We internally handle type boost::program_options::unknown_option,
 | 
			
		||||
	 * and then terminate the program with exitcode 1.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Other exceptions will be passed to higher level.
 | 
			
		||||
	 */
 | 
			
		||||
	void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief  Load and parse given config file
 | 
			
		||||
   * @param  path  Path to config file
 | 
			
		||||
   *
 | 
			
		||||
   * If error occurred when opening file path is points to,
 | 
			
		||||
   * we show the error message and terminate program.
 | 
			
		||||
   *
 | 
			
		||||
   * In case of parameter misuse boost throws an exception.
 | 
			
		||||
   * We internally handle type boost::program_options::unknown_option,
 | 
			
		||||
   * and then terminate program with exitcode 1.
 | 
			
		||||
   *
 | 
			
		||||
   * Other exceptions will be passed to higher level.
 | 
			
		||||
   */
 | 
			
		||||
  void ParseConfig(const std::string& path);
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief  Load and parse given config file
 | 
			
		||||
	 * @param  path  Path to config file
 | 
			
		||||
	 *
 | 
			
		||||
	 * If error occurred when opening file path is points to,
 | 
			
		||||
	 * we show the error message and terminate program.
 | 
			
		||||
	 *
 | 
			
		||||
	 * In case of parameter misuse boost throws an exception.
 | 
			
		||||
	 * We internally handle type boost::program_options::unknown_option,
 | 
			
		||||
	 * and then terminate program with exitcode 1.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Other exceptions will be passed to higher level.
 | 
			
		||||
	 */
 | 
			
		||||
	void ParseConfig(const std::string& path);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief  Used to combine options from cmdline, config and default values
 | 
			
		||||
   */
 | 
			
		||||
  void Finalize();
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief  Used to combine options from cmdline, config and default values
 | 
			
		||||
	 */
 | 
			
		||||
	void Finalize();
 | 
			
		||||
 | 
			
		||||
  /* @brief  Accessor to parameters by name
 | 
			
		||||
   * @param  name  Name of the requested parameter
 | 
			
		||||
   * @param  value Variable where to store option
 | 
			
		||||
   * @return this function returns false if parameter not found
 | 
			
		||||
   *
 | 
			
		||||
   * Example: uint16_t port; GetOption("sam.port", port);
 | 
			
		||||
   */
 | 
			
		||||
  template<typename T>
 | 
			
		||||
  bool GetOption(const char *name, T& value) {
 | 
			
		||||
    if (!m_Options.count(name))
 | 
			
		||||
      return false;
 | 
			
		||||
    value = m_Options[name].as<T>();
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief  Accessor to parameters by name
 | 
			
		||||
	 * @param  name  Name of the requested parameter
 | 
			
		||||
	 * @param  value Variable where to store option
 | 
			
		||||
	 * @return this function returns false if parameter not found
 | 
			
		||||
	 *
 | 
			
		||||
	 * Example: uint16_t port; GetOption("sam.port", port);
 | 
			
		||||
	 */
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	bool GetOption(const char *name, T& value)
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_Options.count(name))
 | 
			
		||||
			return false;
 | 
			
		||||
		value = m_Options[name].as<T>();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  template<typename T>
 | 
			
		||||
  bool GetOption(const std::string& name, T& value)
 | 
			
		||||
  {
 | 
			
		||||
    return GetOption (name.c_str (), value);
 | 
			
		||||
  }
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	bool GetOption(const std::string& name, T& value)
 | 
			
		||||
	{
 | 
			
		||||
		return GetOption (name.c_str (), value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  bool GetOptionAsAny(const char *name, boost::any& value);
 | 
			
		||||
  bool GetOptionAsAny(const std::string& name, boost::any& value);
 | 
			
		||||
	bool GetOptionAsAny(const char *name, boost::any& value);
 | 
			
		||||
	bool GetOptionAsAny(const std::string& name, boost::any& value);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief  Set value of given parameter
 | 
			
		||||
   * @param  name  Name of settable parameter
 | 
			
		||||
   * @param  value New parameter value
 | 
			
		||||
   * @return true if value set up successful, false otherwise
 | 
			
		||||
   *
 | 
			
		||||
   * Example: uint16_t port = 2827; SetOption("bob.port", port);
 | 
			
		||||
   */
 | 
			
		||||
  template<typename T>
 | 
			
		||||
  bool SetOption(const char *name, const T& value) {
 | 
			
		||||
    if (!m_Options.count(name))
 | 
			
		||||
      return false;
 | 
			
		||||
    m_Options.at(name).value() = value;
 | 
			
		||||
    notify(m_Options);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief  Set value of given parameter
 | 
			
		||||
	 * @param  name  Name of settable parameter
 | 
			
		||||
	 * @param  value New parameter value
 | 
			
		||||
	 * @return true if value set up successful, false otherwise
 | 
			
		||||
	 *
 | 
			
		||||
	 * Example: uint16_t port = 2827; SetOption("bob.port", port);
 | 
			
		||||
	 */
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	bool SetOption(const char *name, const T& value)
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_Options.count(name))
 | 
			
		||||
			return false;
 | 
			
		||||
		m_Options.at(name).value() = value;
 | 
			
		||||
		notify(m_Options);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief  Check is value explicitly given or default
 | 
			
		||||
   * @param  name  Name of checked parameter
 | 
			
		||||
   * @return true if value set to default, false otherwise
 | 
			
		||||
   */
 | 
			
		||||
  bool IsDefault(const char *name);
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief  Check is value explicitly given or default
 | 
			
		||||
	 * @param  name  Name of checked parameter
 | 
			
		||||
	 * @return true if value set to default, false otherwise
 | 
			
		||||
	 */
 | 
			
		||||
	bool IsDefault(const char *name);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -681,12 +681,12 @@ namespace crypto
 | 
			
		|||
 | 
			
		||||
// AES
 | 
			
		||||
#ifdef __AES__
 | 
			
		||||
        #ifdef ARM64AES
 | 
			
		||||
                void init_aesenc(void){
 | 
			
		||||
	#ifdef ARM64AES
 | 
			
		||||
	void init_aesenc(void){
 | 
			
		||||
			// TODO: Implementation
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        #endif
 | 
			
		||||
	#endif
 | 
			
		||||
 | 
			
		||||
	#define KeyExpansion256(round0,round1) \
 | 
			
		||||
		"pshufd	$0xff, %%xmm2, %%xmm2 \n" \
 | 
			
		||||
| 
						 | 
				
			
			@ -884,7 +884,6 @@ namespace crypto
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
 | 
			
		||||
	{
 | 
			
		||||
#ifdef __AES__
 | 
			
		||||
| 
						 | 
				
			
			@ -1364,4 +1363,3 @@ namespace crypto
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,13 +28,13 @@
 | 
			
		|||
#else
 | 
			
		||||
#   define LEGACY_OPENSSL 0
 | 
			
		||||
#   if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
 | 
			
		||||
#	   define OPENSSL_HKDF 1
 | 
			
		||||
#	   define OPENSSL_EDDSA 1
 | 
			
		||||
#	   define OPENSSL_X25519 1
 | 
			
		||||
#	   define OPENSSL_SIPHASH 1
 | 
			
		||||
#       define OPENSSL_HKDF 1
 | 
			
		||||
#       define OPENSSL_EDDSA 1
 | 
			
		||||
#       define OPENSSL_X25519 1
 | 
			
		||||
#       define OPENSSL_SIPHASH 1
 | 
			
		||||
#   endif
 | 
			
		||||
#   if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
 | 
			
		||||
#	   define OPENSSL_AEAD_CHACHA20_POLY1305 1 
 | 
			
		||||
#       define OPENSSL_AEAD_CHACHA20_POLY1305 1
 | 
			
		||||
#   endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -178,4 +178,3 @@ namespace crypto
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -126,7 +126,7 @@ namespace crypto
 | 
			
		|||
			ECIESX25519AEADRatchetEncryptor (const uint8_t * pub);
 | 
			
		||||
			~ECIESX25519AEADRatchetEncryptor () {};
 | 
			
		||||
			void Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool);
 | 
			
		||||
            // copies m_PublicKey to pub
 | 
			
		||||
			// copies m_PublicKey to pub
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -153,4 +153,3 @@ namespace crypto
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,5 +77,4 @@ namespace worker
 | 
			
		|||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,16 +114,15 @@ namespace datagram
 | 
			
		|||
			LogPrint (eLogWarning, "Datagram: decompression failed");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
	std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (
 | 
			
		||||
	    const std::vector<std::pair<const uint8_t *, size_t> >& payloads, 
 | 
			
		||||
	    uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum)
 | 
			
		||||
		const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
 | 
			
		||||
		uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum)
 | 
			
		||||
	{
 | 
			
		||||
		auto msg = NewI2NPMessage ();
 | 
			
		||||
		uint8_t * buf = msg->GetPayload ();
 | 
			
		||||
		buf += 4; // reserve for length
 | 
			
		||||
		size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) :
 | 
			
		||||
			 i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len);
 | 
			
		||||
			i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len);
 | 
			
		||||
		if (size)
 | 
			
		||||
		{
 | 
			
		||||
			htobe32buf (msg->GetPayload (), size); // length
 | 
			
		||||
| 
						 | 
				
			
			@ -186,7 +185,7 @@ namespace datagram
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	DatagramSession::DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination,
 | 
			
		||||
																	 const i2p::data::IdentHash & remoteIdent) :
 | 
			
		||||
		const i2p::data::IdentHash & remoteIdent) :
 | 
			
		||||
		m_LocalDestination(localDestination),
 | 
			
		||||
		m_RemoteIdent(remoteIdent),
 | 
			
		||||
		m_SendQueueTimer(localDestination->GetService()),
 | 
			
		||||
| 
						 | 
				
			
			@ -384,4 +383,3 @@ namespace datagram
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,25 +32,27 @@ namespace datagram
 | 
			
		|||
	const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000;
 | 
			
		||||
	// milliseconds minimum time between path switches
 | 
			
		||||
	const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000;
 | 
			
		||||
  // max 64 messages buffered in send queue for each datagram session
 | 
			
		||||
  const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
 | 
			
		||||
	// max 64 messages buffered in send queue for each datagram session
 | 
			
		||||
	const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
 | 
			
		||||
 | 
			
		||||
	class DatagramSession : public std::enable_shared_from_this<DatagramSession>
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
 | 
			
		||||
 | 
			
		||||
		void Start ();
 | 
			
		||||
		void Stop ();
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
 | 
			
		||||
 | 
			
		||||
			void Start ();
 | 
			
		||||
			void Stop ();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /** @brief ack the garlic routing path */
 | 
			
		||||
    void Ack();
 | 
			
		||||
			/** @brief ack the garlic routing path */
 | 
			
		||||
			void Ack();
 | 
			
		||||
 | 
			
		||||
		/** send an i2np message to remote endpoint for this session */
 | 
			
		||||
		void SendMsg(std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
		/** get the last time in milliseconds for when we used this datagram session */
 | 
			
		||||
		uint64_t LastActivity() const { return m_LastUse; }
 | 
			
		||||
			/** send an i2np message to remote endpoint for this session */
 | 
			
		||||
			void SendMsg(std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
			/** get the last time in milliseconds for when we used this datagram session */
 | 
			
		||||
			uint64_t LastActivity() const { return m_LastUse; }
 | 
			
		||||
 | 
			
		||||
		bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,40 +62,41 @@ namespace datagram
 | 
			
		|||
			std::shared_ptr<const i2p::data::IdentHash> OBEP;
 | 
			
		||||
			const uint64_t activity;
 | 
			
		||||
 | 
			
		||||
			Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {}
 | 
			
		||||
			Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) :
 | 
			
		||||
				activity(a) {
 | 
			
		||||
				if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw);
 | 
			
		||||
				else IBGW = nullptr;
 | 
			
		||||
				if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep);
 | 
			
		||||
				else OBEP = nullptr;
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
				Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {}
 | 
			
		||||
				Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) :
 | 
			
		||||
					activity(a) {
 | 
			
		||||
					if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw);
 | 
			
		||||
					else IBGW = nullptr;
 | 
			
		||||
					if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep);
 | 
			
		||||
					else OBEP = nullptr;
 | 
			
		||||
				}
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
		Info GetSessionInfo() const;
 | 
			
		||||
			Info GetSessionInfo() const;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
    void FlushSendQueue();
 | 
			
		||||
    void ScheduleFlushSendQueue();
 | 
			
		||||
			void FlushSendQueue();
 | 
			
		||||
			void ScheduleFlushSendQueue();
 | 
			
		||||
 | 
			
		||||
    void HandleSend(std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
			void HandleSend(std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath();
 | 
			
		||||
			std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath();
 | 
			
		||||
 | 
			
		||||
    void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
 | 
			
		||||
			void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
 | 
			
		||||
    i2p::data::IdentHash m_RemoteIdent;
 | 
			
		||||
    std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
 | 
			
		||||
    std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
 | 
			
		||||
    std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;
 | 
			
		||||
    std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
 | 
			
		||||
    boost::asio::deadline_timer m_SendQueueTimer;
 | 
			
		||||
    std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
 | 
			
		||||
    uint64_t m_LastUse;
 | 
			
		||||
    bool m_RequestingLS;
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
 | 
			
		||||
			i2p::data::IdentHash m_RemoteIdent;
 | 
			
		||||
			std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
 | 
			
		||||
			std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
 | 
			
		||||
			std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;
 | 
			
		||||
			std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
 | 
			
		||||
			boost::asio::deadline_timer m_SendQueueTimer;
 | 
			
		||||
			std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
 | 
			
		||||
			uint64_t m_LastUse;
 | 
			
		||||
			bool m_RequestingLS;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	typedef std::shared_ptr<DatagramSession> DatagramSession_ptr;
 | 
			
		||||
| 
						 | 
				
			
			@ -104,11 +107,9 @@ namespace datagram
 | 
			
		|||
		typedef std::function<void (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> Receiver;
 | 
			
		||||
		typedef std::function<void (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> RawReceiver;
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    		DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip);
 | 
			
		||||
			DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip);
 | 
			
		||||
			~DatagramDestination ();
 | 
			
		||||
 | 
			
		||||
			void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +132,7 @@ namespace datagram
 | 
			
		|||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
 | 
			
		||||
			std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<I2NPMessage> CreateDataMessage (const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
 | 
			
		||||
				uint16_t fromPort, uint16_t toPort, bool isRaw = false, bool checksum = true);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ namespace i2p
 | 
			
		|||
namespace client
 | 
			
		||||
{
 | 
			
		||||
	LeaseSetDestination::LeaseSetDestination (boost::asio::io_service& service,
 | 
			
		||||
	    bool isPublic, const std::map<std::string, std::string> * params):
 | 
			
		||||
		bool isPublic, const std::map<std::string, std::string> * params):
 | 
			
		||||
		m_Service (service), m_IsPublic (isPublic), m_PublishReplyToken (0),
 | 
			
		||||
		m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
 | 
			
		||||
		m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service),
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +160,6 @@ namespace client
 | 
			
		|||
 | 
			
		||||
	bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
 | 
			
		||||
	{
 | 
			
		||||
		
 | 
			
		||||
		auto itr = params.find("i2cp.dontPublishLeaseSet");
 | 
			
		||||
		if (itr != params.end())
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -565,12 +564,12 @@ namespace client
 | 
			
		|||
				m_PublishReplyToken = 0;
 | 
			
		||||
				if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
 | 
			
		||||
				{
 | 
			
		||||
					LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT,  " seconds, will try again");
 | 
			
		||||
					LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
 | 
			
		||||
					Publish ();
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT,  " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ());
 | 
			
		||||
					LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ());
 | 
			
		||||
					// Java floodfill never sends confirmation back for unknown crypto type
 | 
			
		||||
					// assume it successive and try to verify
 | 
			
		||||
					m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
 | 
			
		||||
| 
						 | 
				
			
			@ -720,7 +719,7 @@ namespace client
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
 | 
			
		||||
		std::shared_ptr<const i2p::data::RouterInfo>  nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
 | 
			
		||||
		std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
 | 
			
		||||
	{
 | 
			
		||||
		if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
 | 
			
		||||
			request->replyTunnel = m_Pool->GetNextInboundTunnel ();
 | 
			
		||||
| 
						 | 
				
			
			@ -783,7 +782,7 @@ namespace client
 | 
			
		|||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ",  MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
 | 
			
		||||
					LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
 | 
			
		||||
					done = true;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -829,7 +828,7 @@ namespace client
 | 
			
		|||
	i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
 | 
			
		||||
	{
 | 
			
		||||
		if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
 | 
			
		||||
		    return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET;
 | 
			
		||||
			return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET;
 | 
			
		||||
		return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -846,7 +845,7 @@ namespace client
 | 
			
		|||
		// extract encryption type params for LS2
 | 
			
		||||
		std::set<i2p::data::CryptoKeyType> encryptionKeyTypes;
 | 
			
		||||
		if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 ||
 | 
			
		||||
		   GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params)
 | 
			
		||||
			GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params)
 | 
			
		||||
		{
 | 
			
		||||
			auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
 | 
			
		||||
			if (it != params->end ())
 | 
			
		||||
| 
						 | 
				
			
			@ -1105,7 +1104,7 @@ namespace client
 | 
			
		|||
		return dest;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
 | 
			
		||||
	i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
 | 
			
		||||
	{
 | 
			
		||||
		if (m_DatagramDestination == nullptr)
 | 
			
		||||
			m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip);
 | 
			
		||||
| 
						 | 
				
			
			@ -1147,7 +1146,7 @@ namespace client
 | 
			
		|||
		// TODO:: persist crypto key type
 | 
			
		||||
		std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
 | 
			
		||||
		if (f1) {
 | 
			
		||||
			f1.write ((char *)keys->pub,  256);
 | 
			
		||||
			f1.write ((char *)keys->pub, 256);
 | 
			
		||||
			f1.write ((char *)keys->priv, 256);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,7 +94,6 @@ namespace client
 | 
			
		|||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +111,7 @@ namespace client
 | 
			
		|||
			bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
 | 
			
		||||
			std::shared_ptr<i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
 | 
			
		||||
			bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
 | 
			
		||||
			bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey>  dest, RequestComplete requestComplete = nullptr); 
 | 
			
		||||
			bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, RequestComplete requestComplete = nullptr);
 | 
			
		||||
			void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true);
 | 
			
		||||
			void CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, bool notify = true);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -155,7 +154,7 @@ namespace client
 | 
			
		|||
			void HandleDeliveryStatusMessage (uint32_t msgID);
 | 
			
		||||
 | 
			
		||||
			void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr);
 | 
			
		||||
			bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo>  nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
 | 
			
		||||
			bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
 | 
			
		||||
			void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
 | 
			
		||||
			void HandleCleanupTimer (const boost::system::error_code& ecode);
 | 
			
		||||
			void CleanupRemoteLeaseSets ();
 | 
			
		||||
| 
						 | 
				
			
			@ -235,8 +234,8 @@ namespace client
 | 
			
		|||
			int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
 | 
			
		||||
 | 
			
		||||
			// datagram
 | 
			
		||||
      		i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
 | 
			
		||||
      		i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
 | 
			
		||||
			i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
 | 
			
		||||
			i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
 | 
			
		||||
 | 
			
		||||
			// implements LocalDestination
 | 
			
		||||
			bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,36 +15,36 @@ namespace i2p
 | 
			
		|||
namespace garlic
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    void RatchetTagSet::DHInitialize (const uint8_t * rootKey, const uint8_t * k)
 | 
			
		||||
    {
 | 
			
		||||
        // DH_INITIALIZE(rootKey, k)
 | 
			
		||||
        uint8_t keydata[64];
 | 
			
		||||
        i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64)
 | 
			
		||||
        memcpy (m_NextRootKey, keydata, 32); // nextRootKey = keydata[0:31]
 | 
			
		||||
        i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf); 
 | 
			
		||||
        // [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64) 
 | 
			
		||||
	void RatchetTagSet::DHInitialize (const uint8_t * rootKey, const uint8_t * k)
 | 
			
		||||
	{
 | 
			
		||||
		// DH_INITIALIZE(rootKey, k)
 | 
			
		||||
		uint8_t keydata[64];
 | 
			
		||||
		i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64)
 | 
			
		||||
		memcpy (m_NextRootKey, keydata, 32); // nextRootKey = keydata[0:31]
 | 
			
		||||
		i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf);
 | 
			
		||||
		// [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64)
 | 
			
		||||
		memcpy (m_SymmKeyCK, m_KeyData.buf + 32, 32);
 | 
			
		||||
		m_NextSymmKeyIndex = 0;
 | 
			
		||||
    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void RatchetTagSet::NextSessionTagRatchet ()
 | 
			
		||||
    {
 | 
			
		||||
        i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), nullptr, 0, "STInitialization", m_KeyData.buf); // [sessTag_ck, sesstag_constant] = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64)
 | 
			
		||||
        memcpy (m_SessTagConstant, m_KeyData.GetSessTagConstant (), 32);
 | 
			
		||||
	void RatchetTagSet::NextSessionTagRatchet ()
 | 
			
		||||
	{
 | 
			
		||||
		i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), nullptr, 0, "STInitialization", m_KeyData.buf); // [sessTag_ck, sesstag_constant] = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64)
 | 
			
		||||
		memcpy (m_SessTagConstant, m_KeyData.GetSessTagConstant (), 32);
 | 
			
		||||
		m_NextIndex = 0;
 | 
			
		||||
    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    uint64_t RatchetTagSet::GetNextSessionTag ()
 | 
			
		||||
    {
 | 
			
		||||
        i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
 | 
			
		||||
	uint64_t RatchetTagSet::GetNextSessionTag ()
 | 
			
		||||
	{
 | 
			
		||||
		i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
 | 
			
		||||
		m_NextIndex++;
 | 
			
		||||
		if (m_NextIndex >= 65535)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogError, "Garlic: Tagset ", GetTagSetID (), " is empty");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
        return m_KeyData.GetTag ();
 | 
			
		||||
    }
 | 
			
		||||
		return m_KeyData.GetTag ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void RatchetTagSet::GetSymmKey (int index, uint8_t * key)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -85,15 +85,15 @@ namespace garlic
 | 
			
		|||
			m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet):
 | 
			
		||||
        GarlicRoutingSession (owner, attachLeaseSet)
 | 
			
		||||
    {
 | 
			
		||||
    	ResetKeys ();
 | 
			
		||||
    }
 | 
			
		||||
	ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet):
 | 
			
		||||
		GarlicRoutingSession (owner, attachLeaseSet)
 | 
			
		||||
	{
 | 
			
		||||
		ResetKeys ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession ()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
	ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession ()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void ECIESX25519AEADRatchetSession::ResetKeys ()
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -111,14 +111,14 @@ namespace garlic
 | 
			
		|||
		memcpy (m_H, hh, 32);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void ECIESX25519AEADRatchetSession::MixHash (const uint8_t * buf, size_t len)
 | 
			
		||||
    {
 | 
			
		||||
        SHA256_CTX ctx;
 | 
			
		||||
	void ECIESX25519AEADRatchetSession::MixHash (const uint8_t * buf, size_t len)
 | 
			
		||||
	{
 | 
			
		||||
		SHA256_CTX ctx;
 | 
			
		||||
		SHA256_Init (&ctx);
 | 
			
		||||
		SHA256_Update (&ctx, m_H, 32);
 | 
			
		||||
		SHA256_Update (&ctx, buf, len);
 | 
			
		||||
		SHA256_Final (m_H, &ctx);
 | 
			
		||||
    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void ECIESX25519AEADRatchetSession::CreateNonce (uint64_t seqn, uint8_t * nonce)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -126,48 +126,48 @@ namespace garlic
 | 
			
		|||
		htole64buf (nonce + 4, seqn);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    bool ECIESX25519AEADRatchetSession::GenerateEphemeralKeysAndEncode (uint8_t * buf)
 | 
			
		||||
    {
 | 
			
		||||
        for (int i = 0; i < 10; i++)
 | 
			
		||||
        {
 | 
			
		||||
            m_EphemeralKeys.GenerateKeys ();    
 | 
			
		||||
            if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), buf))
 | 
			
		||||
		        return true; // success
 | 
			
		||||
        }         
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
	bool ECIESX25519AEADRatchetSession::GenerateEphemeralKeysAndEncode (uint8_t * buf)
 | 
			
		||||
	{
 | 
			
		||||
		for (int i = 0; i < 10; i++)
 | 
			
		||||
		{
 | 
			
		||||
			m_EphemeralKeys.GenerateKeys ();
 | 
			
		||||
			if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), buf))
 | 
			
		||||
				return true; // success
 | 
			
		||||
		}
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<RatchetTagSet> ECIESX25519AEADRatchetSession::CreateNewSessionTagset ()
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t tagsetKey[32];    
 | 
			
		||||
        i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
 | 
			
		||||
         // Session Tag Ratchet
 | 
			
		||||
        auto tagsetNsr = std::make_shared<RatchetTagSet>(shared_from_this ());
 | 
			
		||||
        tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
 | 
			
		||||
        tagsetNsr->NextSessionTagRatchet ();
 | 
			
		||||
        return tagsetNsr;   
 | 
			
		||||
    }
 | 
			
		||||
	std::shared_ptr<RatchetTagSet> ECIESX25519AEADRatchetSession::CreateNewSessionTagset ()
 | 
			
		||||
	{
 | 
			
		||||
		uint8_t tagsetKey[32];
 | 
			
		||||
		i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
 | 
			
		||||
		// Session Tag Ratchet
 | 
			
		||||
		auto tagsetNsr = std::make_shared<RatchetTagSet>(shared_from_this ());
 | 
			
		||||
		tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
 | 
			
		||||
		tagsetNsr->NextSessionTagRatchet ();
 | 
			
		||||
		return tagsetNsr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len)
 | 
			
		||||
    {
 | 
			
		||||
        if (!GetOwner ()) return false;
 | 
			
		||||
        // we are Bob
 | 
			
		||||
        // KDF1
 | 
			
		||||
        MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32); // h = SHA256(h || bpk)    
 | 
			
		||||
	bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len)
 | 
			
		||||
	{
 | 
			
		||||
		if (!GetOwner ()) return false;
 | 
			
		||||
		// we are Bob
 | 
			
		||||
		// KDF1
 | 
			
		||||
		MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32); // h = SHA256(h || bpk)
 | 
			
		||||
 | 
			
		||||
		if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogError, "Garlic: Can't decode elligator");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
        buf += 32; len -= 32;
 | 
			
		||||
        MixHash (m_Aepk, 32); // h = SHA256(h || aepk)  
 | 
			
		||||
		buf += 32; len -= 32;
 | 
			
		||||
		MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
 | 
			
		||||
 | 
			
		||||
        uint8_t sharedSecret[32];
 | 
			
		||||
		uint8_t sharedSecret[32];
 | 
			
		||||
		GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, aepk)
 | 
			
		||||
		i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
 | 
			
		||||
 | 
			
		||||
        // decrypt flags/static    
 | 
			
		||||
		// decrypt flags/static
 | 
			
		||||
		uint8_t nonce[12], fs[32];
 | 
			
		||||
		CreateNonce (0, nonce);
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt
 | 
			
		||||
| 
						 | 
				
			
			@ -183,7 +183,7 @@ namespace garlic
 | 
			
		|||
		if (isStatic)
 | 
			
		||||
		{
 | 
			
		||||
			// static key, fs is apk
 | 
			
		||||
            memcpy (m_RemoteStaticKey, fs, 32);
 | 
			
		||||
			memcpy (m_RemoteStaticKey, fs, 32);
 | 
			
		||||
			GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, apk)
 | 
			
		||||
			i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -198,17 +198,17 @@ namespace garlic
 | 
			
		|||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		if (isStatic) MixHash (buf, len); // h = SHA256(h || ciphertext)
 | 
			
		||||
        m_State = eSessionStateNewSessionReceived;            
 | 
			
		||||
		m_State = eSessionStateNewSessionReceived;
 | 
			
		||||
		GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
 | 
			
		||||
 | 
			
		||||
        HandlePayload (payload.data (), len - 16, nullptr, 0);    
 | 
			
		||||
		HandlePayload (payload.data (), len - 16, nullptr, 0);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index)
 | 
			
		||||
    {
 | 
			
		||||
        size_t offset = 0;
 | 
			
		||||
	void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index)
 | 
			
		||||
	{
 | 
			
		||||
		size_t offset = 0;
 | 
			
		||||
		while (offset < len)
 | 
			
		||||
		{
 | 
			
		||||
			uint8_t blk = buf[offset];
 | 
			
		||||
| 
						 | 
				
			
			@ -269,7 +269,7 @@ namespace garlic
 | 
			
		|||
			}
 | 
			
		||||
			offset += size;
 | 
			
		||||
		}
 | 
			
		||||
    }    
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -279,7 +279,7 @@ namespace garlic
 | 
			
		|||
			if (!m_SendForwardKey || !m_NextSendRatchet) return;
 | 
			
		||||
			uint16_t keyID = bufbe16toh (buf); buf += 2; // keyID
 | 
			
		||||
			if (((!m_NextSendRatchet->newKey || !m_NextSendRatchet->keyID) && keyID == m_NextSendRatchet->keyID) ||
 | 
			
		||||
			    (m_NextSendRatchet->newKey && keyID == m_NextSendRatchet->keyID -1))
 | 
			
		||||
				(m_NextSendRatchet->newKey && keyID == m_NextSendRatchet->keyID -1))
 | 
			
		||||
			{
 | 
			
		||||
				if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG)
 | 
			
		||||
					memcpy (m_NextSendRatchet->remote, buf, 32);
 | 
			
		||||
| 
						 | 
				
			
			@ -359,36 +359,36 @@ namespace garlic
 | 
			
		|||
		LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
 | 
			
		||||
    { 
 | 
			
		||||
	bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
 | 
			
		||||
	{
 | 
			
		||||
		ResetKeys ();
 | 
			
		||||
        // we are Alice, bpk is m_RemoteStaticKey
 | 
			
		||||
        size_t offset = 0;
 | 
			
		||||
        if (!GenerateEphemeralKeysAndEncode (out + offset))
 | 
			
		||||
		// we are Alice, bpk is m_RemoteStaticKey
 | 
			
		||||
		size_t offset = 0;
 | 
			
		||||
		if (!GenerateEphemeralKeysAndEncode (out + offset))
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogError, "Garlic: Can't encode elligator");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
        offset += 32;   
 | 
			
		||||
		offset += 32;
 | 
			
		||||
 | 
			
		||||
        // KDF1
 | 
			
		||||
        MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk) 
 | 
			
		||||
        MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk)          
 | 
			
		||||
        uint8_t sharedSecret[32];
 | 
			
		||||
		// KDF1
 | 
			
		||||
		MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk)
 | 
			
		||||
		MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk)
 | 
			
		||||
		uint8_t sharedSecret[32];
 | 
			
		||||
		m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk)
 | 
			
		||||
		i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
 | 
			
		||||
        // encrypt static key section
 | 
			
		||||
        uint8_t nonce[12];
 | 
			
		||||
		// encrypt static key section
 | 
			
		||||
		uint8_t nonce[12];
 | 
			
		||||
		CreateNonce (0, nonce);
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed ");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
        MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
 | 
			
		||||
        offset += 48;
 | 
			
		||||
        // KDF2 
 | 
			
		||||
        GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bpk)
 | 
			
		||||
		MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
 | 
			
		||||
		offset += 48;
 | 
			
		||||
		// KDF2
 | 
			
		||||
		GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bpk)
 | 
			
		||||
		i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
 | 
			
		||||
		// encrypt payload
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
 | 
			
		||||
| 
						 | 
				
			
			@ -399,80 +399,80 @@ namespace garlic
 | 
			
		|||
		MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext)
 | 
			
		||||
 | 
			
		||||
		m_State = eSessionStateNewSessionSent;
 | 
			
		||||
        if (GetOwner ())
 | 
			
		||||
		if (GetOwner ())
 | 
			
		||||
			GenerateMoreReceiveTags (CreateNewSessionTagset (), ECIESX25519_NSR_NUM_GENERATED_TAGS);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
 | 
			
		||||
    {
 | 
			
		||||
        // we are Bob
 | 
			
		||||
	bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
 | 
			
		||||
	{
 | 
			
		||||
		// we are Bob
 | 
			
		||||
		m_NSRTagset = CreateNewSessionTagset ();
 | 
			
		||||
        uint64_t tag = m_NSRTagset->GetNextSessionTag ();   
 | 
			
		||||
		uint64_t tag = m_NSRTagset->GetNextSessionTag ();
 | 
			
		||||
 | 
			
		||||
        size_t offset = 0;
 | 
			
		||||
        memcpy (out + offset, &tag, 8);
 | 
			
		||||
        offset += 8;
 | 
			
		||||
        if (!GenerateEphemeralKeysAndEncode (out + offset)) // bepk
 | 
			
		||||
		size_t offset = 0;
 | 
			
		||||
		memcpy (out + offset, &tag, 8);
 | 
			
		||||
		offset += 8;
 | 
			
		||||
		if (!GenerateEphemeralKeysAndEncode (out + offset)) // bepk
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogError, "Garlic: Can't encode elligator");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		memcpy (m_NSREncodedKey, out + offset, 56); // for possible next NSR
 | 
			
		||||
		memcpy (m_NSRH, m_H, 32);
 | 
			
		||||
        offset += 32;      
 | 
			
		||||
        // KDF for  Reply Key Section
 | 
			
		||||
        MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
 | 
			
		||||
        MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
 | 
			
		||||
        uint8_t sharedSecret[32];      
 | 
			
		||||
        m_EphemeralKeys.Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk) 
 | 
			
		||||
        i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)       
 | 
			
		||||
		offset += 32;
 | 
			
		||||
		// KDF for Reply Key Section
 | 
			
		||||
		MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
 | 
			
		||||
		MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
 | 
			
		||||
		uint8_t sharedSecret[32];
 | 
			
		||||
		m_EphemeralKeys.Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk)
 | 
			
		||||
		i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
 | 
			
		||||
		m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, apk)
 | 
			
		||||
        i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)       
 | 
			
		||||
		i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
 | 
			
		||||
		uint8_t nonce[12];
 | 
			
		||||
		CreateNonce (0, nonce);
 | 
			
		||||
        // calulate hash for zero length
 | 
			
		||||
		// calculate hash for zero length
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
        MixHash (out + offset, 16); // h = SHA256(h || ciphertext)    
 | 
			
		||||
        offset += 16;
 | 
			
		||||
        // KDF for payload
 | 
			
		||||
        uint8_t keydata[64];
 | 
			
		||||
        i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
 | 
			
		||||
		MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
 | 
			
		||||
		offset += 16;
 | 
			
		||||
		// KDF for payload
 | 
			
		||||
		uint8_t keydata[64];
 | 
			
		||||
		i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
 | 
			
		||||
		// k_ab = keydata[0:31], k_ba = keydata[32:63]
 | 
			
		||||
		auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
 | 
			
		||||
        receiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
 | 
			
		||||
		receiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
 | 
			
		||||
		receiveTagset->NextSessionTagRatchet ();
 | 
			
		||||
		m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
 | 
			
		||||
        m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
 | 
			
		||||
		m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
 | 
			
		||||
		m_SendTagset->NextSessionTagRatchet ();
 | 
			
		||||
		GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS);
 | 
			
		||||
        i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
 | 
			
		||||
        // encrypt payload
 | 
			
		||||
        if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt
 | 
			
		||||
		i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
 | 
			
		||||
		// encrypt payload
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Garlic: NSR payload section AEAD encryption failed");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		m_State = eSessionStateNewSessionReplySent;
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
 | 
			
		||||
    {
 | 
			
		||||
        // we are Bob and sent NSR already
 | 
			
		||||
		uint64_t tag = m_NSRTagset->GetNextSessionTag ();  // next tag
 | 
			
		||||
        memcpy (out, &tag, 8);
 | 
			
		||||
	{
 | 
			
		||||
		// we are Bob and sent NSR already
 | 
			
		||||
		uint64_t tag = m_NSRTagset->GetNextSessionTag (); // next tag
 | 
			
		||||
		memcpy (out, &tag, 8);
 | 
			
		||||
		memcpy (out + 8, m_NSREncodedKey, 32);
 | 
			
		||||
		// recalculte h with new tag
 | 
			
		||||
		// recalculate h with new tag
 | 
			
		||||
		memcpy (m_H, m_NSRH, 32);
 | 
			
		||||
		MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
 | 
			
		||||
        MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
 | 
			
		||||
		MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
 | 
			
		||||
		uint8_t nonce[12];
 | 
			
		||||
		CreateNonce (0, nonce);
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + 40, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
 | 
			
		||||
| 
						 | 
				
			
			@ -482,7 +482,7 @@ namespace garlic
 | 
			
		|||
		}
 | 
			
		||||
		MixHash (out + 40, 16); // h = SHA256(h || ciphertext)
 | 
			
		||||
		// encrypt payload
 | 
			
		||||
        if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Garlic: Next NSR payload section AEAD encryption failed");
 | 
			
		||||
			return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -490,36 +490,36 @@ namespace garlic
 | 
			
		|||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len)
 | 
			
		||||
    {
 | 
			
		||||
	bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len)
 | 
			
		||||
	{
 | 
			
		||||
		// we are Alice
 | 
			
		||||
		LogPrint (eLogDebug, "Garlic: reply received");
 | 
			
		||||
		const uint8_t * tag = buf;
 | 
			
		||||
		buf += 8; len -= 8; // tag
 | 
			
		||||
        uint8_t bepk[32]; // Bob's ephemeral key
 | 
			
		||||
		uint8_t bepk[32]; // Bob's ephemeral key
 | 
			
		||||
		if (!i2p::crypto::GetElligator ()->Decode (buf, bepk))
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogError, "Garlic: Can't decode elligator");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		buf += 32; len -= 32;
 | 
			
		||||
		// KDF for  Reply Key Section
 | 
			
		||||
		// KDF for Reply Key Section
 | 
			
		||||
		uint8_t h[32]; memcpy (h, m_H, 32); // save m_H
 | 
			
		||||
        MixHash (tag, 8); // h = SHA256(h || tag)
 | 
			
		||||
        MixHash (bepk, 32); // h = SHA256(h || bepk)		
 | 
			
		||||
		MixHash (tag, 8); // h = SHA256(h || tag)
 | 
			
		||||
		MixHash (bepk, 32); // h = SHA256(h || bepk)
 | 
			
		||||
		uint8_t sharedSecret[32];
 | 
			
		||||
		if (m_State == eSessionStateNewSessionSent)
 | 
			
		||||
		{
 | 
			
		||||
			// only fist time, we assume ephemeral keys the same
 | 
			
		||||
		    m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)  
 | 
			
		||||
			m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
 | 
			
		||||
			i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
 | 
			
		||||
			GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bepk)
 | 
			
		||||
			i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
 | 
			
		||||
		}
 | 
			
		||||
		uint8_t nonce[12];
 | 
			
		||||
		CreateNonce (0, nonce);
 | 
			
		||||
        // calulate hash for zero length
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anyting */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only
 | 
			
		||||
		// calculate hash for zero length
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anything */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed");
 | 
			
		||||
			return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -527,22 +527,22 @@ namespace garlic
 | 
			
		|||
		MixHash (buf, 16); // h = SHA256(h || ciphertext)
 | 
			
		||||
		buf += 16; len -= 16;
 | 
			
		||||
		// KDF for payload
 | 
			
		||||
        uint8_t keydata[64];
 | 
			
		||||
        i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
 | 
			
		||||
		uint8_t keydata[64];
 | 
			
		||||
		i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
 | 
			
		||||
		if (m_State == eSessionStateNewSessionSent)
 | 
			
		||||
		{
 | 
			
		||||
		    // k_ab = keydata[0:31], k_ba = keydata[32:63]
 | 
			
		||||
			// k_ab = keydata[0:31], k_ba = keydata[32:63]
 | 
			
		||||
			m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
 | 
			
		||||
		    m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
 | 
			
		||||
			m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
 | 
			
		||||
			m_SendTagset->NextSessionTagRatchet ();
 | 
			
		||||
			auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
 | 
			
		||||
		    receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
 | 
			
		||||
			receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
 | 
			
		||||
			receiveTagset->NextSessionTagRatchet ();
 | 
			
		||||
			GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS);
 | 
			
		||||
		}
 | 
			
		||||
        i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)		
 | 
			
		||||
		i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
 | 
			
		||||
		// decrypt payload
 | 
			
		||||
        if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
 | 
			
		||||
			return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -560,8 +560,8 @@ namespace garlic
 | 
			
		|||
		SetLeaseSetUpdateStatus (eLeaseSetUpToDate);
 | 
			
		||||
		SetLeaseSetUpdateMsgID (0);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool ECIESX25519AEADRatchetSession::NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -637,61 +637,61 @@ namespace garlic
 | 
			
		|||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
 | 
			
		||||
    { 
 | 
			
		||||
        auto payload = CreatePayload (msg, m_State != eSessionStateEstablished);  
 | 
			
		||||
        size_t len = payload.size ();
 | 
			
		||||
	std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
 | 
			
		||||
	{
 | 
			
		||||
		auto payload = CreatePayload (msg, m_State != eSessionStateEstablished);
 | 
			
		||||
		size_t len = payload.size ();
 | 
			
		||||
		if (!len) return nullptr;
 | 
			
		||||
		auto m = NewI2NPMessage (len + 100); // 96 + 4
 | 
			
		||||
		m->Align (12); // in order to get buf aligned to 16 (12 + 4)
 | 
			
		||||
		uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
 | 
			
		||||
 | 
			
		||||
        switch (m_State)
 | 
			
		||||
        {
 | 
			
		||||
		switch (m_State)
 | 
			
		||||
		{
 | 
			
		||||
			case eSessionStateEstablished:
 | 
			
		||||
				if (!NewExistingSessionMessage (payload.data (), payload.size (), buf, m->maxLen))
 | 
			
		||||
					return nullptr;
 | 
			
		||||
				len += 24;
 | 
			
		||||
			break;
 | 
			
		||||
            case eSessionStateNew:
 | 
			
		||||
                if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen))
 | 
			
		||||
                    return nullptr;
 | 
			
		||||
                len += 96;
 | 
			
		||||
            break;
 | 
			
		||||
            case eSessionStateNewSessionReceived:
 | 
			
		||||
                 if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
 | 
			
		||||
                    return nullptr;
 | 
			
		||||
                 len += 72;   
 | 
			
		||||
            break;
 | 
			
		||||
			case eSessionStateNew:
 | 
			
		||||
				if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen))
 | 
			
		||||
					return nullptr;
 | 
			
		||||
				len += 96;
 | 
			
		||||
			break;
 | 
			
		||||
			case eSessionStateNewSessionReceived:
 | 
			
		||||
				if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
 | 
			
		||||
					return nullptr;
 | 
			
		||||
				len += 72;
 | 
			
		||||
			break;
 | 
			
		||||
			case eSessionStateNewSessionReplySent:
 | 
			
		||||
				if (!NextNewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
 | 
			
		||||
                    return nullptr;
 | 
			
		||||
                 len += 72;  
 | 
			
		||||
					return nullptr;
 | 
			
		||||
				len += 72;
 | 
			
		||||
			break;
 | 
			
		||||
            default:
 | 
			
		||||
                return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
			default:
 | 
			
		||||
				return nullptr;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        htobe32buf (m->GetPayload (), len);
 | 
			
		||||
		htobe32buf (m->GetPayload (), len);
 | 
			
		||||
		m->len += len + 4;
 | 
			
		||||
		m->FillI2NPMessageHeader (eI2NPGarlic);
 | 
			
		||||
		return m;
 | 
			
		||||
    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::vector<uint8_t> ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first)
 | 
			
		||||
    {
 | 
			
		||||
	std::vector<uint8_t> ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first)
 | 
			
		||||
	{
 | 
			
		||||
		uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
 | 
			
		||||
        size_t payloadLen = 0; 
 | 
			
		||||
		size_t payloadLen = 0;
 | 
			
		||||
		if (first) payloadLen += 7;// datatime
 | 
			
		||||
        if (msg && m_Destination) 
 | 
			
		||||
            payloadLen += msg->GetPayloadLength () + 13 + 32;
 | 
			
		||||
		if (msg && m_Destination)
 | 
			
		||||
			payloadLen += msg->GetPayloadLength () + 13 + 32;
 | 
			
		||||
		auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated ||
 | 
			
		||||
			(GetLeaseSetUpdateStatus () == eLeaseSetSubmitted &&
 | 
			
		||||
		    	ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ?
 | 
			
		||||
				ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ?
 | 
			
		||||
			GetOwner ()->GetLeaseSet () : nullptr;
 | 
			
		||||
		if (leaseSet)
 | 
			
		||||
		{
 | 
			
		||||
            payloadLen += leaseSet->GetBufferLen () + DATABASE_STORE_HEADER_SIZE + 13;   
 | 
			
		||||
			payloadLen += leaseSet->GetBufferLen () + DATABASE_STORE_HEADER_SIZE + 13;
 | 
			
		||||
			if (!first)
 | 
			
		||||
			{
 | 
			
		||||
				// ack request
 | 
			
		||||
| 
						 | 
				
			
			@ -730,19 +730,19 @@ namespace garlic
 | 
			
		|||
				payloadLen += paddingSize + 3;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
        std::vector<uint8_t> v(payloadLen);
 | 
			
		||||
        size_t offset = 0;
 | 
			
		||||
        // DateTime
 | 
			
		||||
		std::vector<uint8_t> v(payloadLen);
 | 
			
		||||
		size_t offset = 0;
 | 
			
		||||
		// DateTime
 | 
			
		||||
		if (first)
 | 
			
		||||
		{
 | 
			
		||||
		    v[offset] = eECIESx25519BlkDateTime; offset++;
 | 
			
		||||
		    htobe16buf (v.data () + offset, 4); offset += 2; 
 | 
			
		||||
		    htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds
 | 
			
		||||
			v[offset] = eECIESx25519BlkDateTime; offset++;
 | 
			
		||||
			htobe16buf (v.data () + offset, 4); offset += 2;
 | 
			
		||||
			htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds
 | 
			
		||||
		}
 | 
			
		||||
        // LeaseSet
 | 
			
		||||
        if (leaseSet)
 | 
			
		||||
		// LeaseSet
 | 
			
		||||
		if (leaseSet)
 | 
			
		||||
		{
 | 
			
		||||
            offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset);
 | 
			
		||||
			offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset);
 | 
			
		||||
			if (!first)
 | 
			
		||||
			{
 | 
			
		||||
				// ack request
 | 
			
		||||
| 
						 | 
				
			
			@ -752,13 +752,13 @@ namespace garlic
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// msg
 | 
			
		||||
        if (msg && m_Destination)    
 | 
			
		||||
            offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true);
 | 
			
		||||
		if (msg && m_Destination)
 | 
			
		||||
			offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true);
 | 
			
		||||
		// ack
 | 
			
		||||
		if (m_AckRequests.size () > 0)
 | 
			
		||||
		{
 | 
			
		||||
			v[offset] = eECIESx25519BlkAck; offset++;
 | 
			
		||||
			htobe16buf (v.data () + offset, m_AckRequests.size ()*4); offset += 2;
 | 
			
		||||
			htobe16buf (v.data () + offset, m_AckRequests.size () * 4); offset += 2;
 | 
			
		||||
			for (auto& it: m_AckRequests)
 | 
			
		||||
			{
 | 
			
		||||
				htobe16buf (v.data () + offset, it.first); offset += 2;
 | 
			
		||||
| 
						 | 
				
			
			@ -801,24 +801,24 @@ namespace garlic
 | 
			
		|||
				offset += 32; // public key
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
        // padding
 | 
			
		||||
		// padding
 | 
			
		||||
		if (paddingSize)
 | 
			
		||||
		{
 | 
			
		||||
		    v[offset] = eECIESx25519BlkPadding; offset++; 
 | 
			
		||||
		    htobe16buf (v.data () + offset, paddingSize); offset += 2;
 | 
			
		||||
		    memset (v.data () + offset, 0, paddingSize); offset += paddingSize;
 | 
			
		||||
			v[offset] = eECIESx25519BlkPadding; offset++;
 | 
			
		||||
			htobe16buf (v.data () + offset, paddingSize); offset += 2;
 | 
			
		||||
			memset (v.data () + offset, 0, paddingSize); offset += paddingSize;
 | 
			
		||||
		}
 | 
			
		||||
        return v;
 | 
			
		||||
    }   
 | 
			
		||||
		return v;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination)
 | 
			
		||||
    {
 | 
			
		||||
        if (!msg) return 0;
 | 
			
		||||
        uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
 | 
			
		||||
	size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination)
 | 
			
		||||
	{
 | 
			
		||||
		if (!msg) return 0;
 | 
			
		||||
		uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
 | 
			
		||||
		if (isDestination) cloveSize += 32;
 | 
			
		||||
        if ((int)len < cloveSize + 3) return 0;
 | 
			
		||||
        buf[0] = eECIESx25519BlkGalicClove; // clove type
 | 
			
		||||
        htobe16buf (buf + 1, cloveSize); // size   
 | 
			
		||||
		if ((int)len < cloveSize + 3) return 0;
 | 
			
		||||
		buf[0] = eECIESx25519BlkGalicClove; // clove type
 | 
			
		||||
		htobe16buf (buf + 1, cloveSize); // size
 | 
			
		||||
		buf += 3;
 | 
			
		||||
		if (isDestination)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -828,15 +828,15 @@ namespace garlic
 | 
			
		|||
		else
 | 
			
		||||
			*buf = 0;
 | 
			
		||||
		buf++;	// flag and delivery instructions
 | 
			
		||||
        *buf = msg->GetTypeID (); // I2NP msg type
 | 
			
		||||
        htobe32buf (buf + 1, msg->GetMsgID ()); // msgID     
 | 
			
		||||
        htobe32buf (buf + 5, msg->GetExpiration ()/1000); // expiration in seconds     
 | 
			
		||||
        memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ());
 | 
			
		||||
        return cloveSize + 3;
 | 
			
		||||
    } 
 | 
			
		||||
		*buf = msg->GetTypeID (); // I2NP msg type
 | 
			
		||||
		htobe32buf (buf + 1, msg->GetMsgID ()); // msgID
 | 
			
		||||
		htobe32buf (buf + 5, msg->GetExpiration () / 1000); // expiration in seconds
 | 
			
		||||
		memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ());
 | 
			
		||||
		return cloveSize + 3;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size_t ECIESX25519AEADRatchetSession::CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len)
 | 
			
		||||
    {
 | 
			
		||||
	{
 | 
			
		||||
		if (!ls || ls->GetStoreType () != i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogError, "Garlic: Incorrect LeasetSet type to send");
 | 
			
		||||
| 
						 | 
				
			
			@ -845,7 +845,7 @@ namespace garlic
 | 
			
		|||
		uint16_t cloveSize = 1 + 9 + DATABASE_STORE_HEADER_SIZE + ls->GetBufferLen (); // to local
 | 
			
		||||
		if ((int)len < cloveSize + 3) return 0;
 | 
			
		||||
		buf[0] = eECIESx25519BlkGalicClove; // clove type
 | 
			
		||||
        htobe16buf (buf + 1, cloveSize); // size   
 | 
			
		||||
		htobe16buf (buf + 1, cloveSize); // size
 | 
			
		||||
		buf += 3;
 | 
			
		||||
		*buf = 0; buf++; // flag and delivery instructions
 | 
			
		||||
		*buf = eI2NPDatabaseStore; buf++; // I2NP msg type
 | 
			
		||||
| 
						 | 
				
			
			@ -885,14 +885,14 @@ namespace garlic
 | 
			
		|||
		auto payload = buf + offset;
 | 
			
		||||
		uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
 | 
			
		||||
		size_t len = cloveSize + 3;
 | 
			
		||||
        payload[0] = eECIESx25519BlkGalicClove; // clove type
 | 
			
		||||
        htobe16buf (payload + 1, cloveSize); // size   
 | 
			
		||||
		payload[0] = eECIESx25519BlkGalicClove; // clove type
 | 
			
		||||
		htobe16buf (payload + 1, cloveSize); // size
 | 
			
		||||
		payload += 3;
 | 
			
		||||
		*payload = 0; payload++;	// flag and delivery instructions
 | 
			
		||||
        *payload = msg->GetTypeID (); // I2NP msg type
 | 
			
		||||
        htobe32buf (payload + 1, msg->GetMsgID ()); // msgID     
 | 
			
		||||
        htobe32buf (payload + 5, msg->GetExpiration ()/1000); // expiration in seconds     
 | 
			
		||||
        memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ());
 | 
			
		||||
		*payload = 0; payload++; // flag and delivery instructions
 | 
			
		||||
		*payload = msg->GetTypeID (); // I2NP msg type
 | 
			
		||||
		htobe32buf (payload + 1, msg->GetMsgID ()); // msgID
 | 
			
		||||
		htobe32buf (payload + 5, msg->GetExpiration () / 1000); // expiration in seconds
 | 
			
		||||
		memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ());
 | 
			
		||||
 | 
			
		||||
		if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len, buf, 8, key, nonce, buf + offset, len + 16, true)) // encrypt
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -909,5 +909,3 @@ namespace garlic
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,19 +26,19 @@ namespace garlic
 | 
			
		|||
	const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 160;
 | 
			
		||||
	const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12;
 | 
			
		||||
 | 
			
		||||
	const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912;  // 1912 = 1956 /* to fit 2 tunnel messages */ 
 | 
			
		||||
	const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */
 | 
			
		||||
	// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
 | 
			
		||||
 | 
			
		||||
	class ECIESX25519AEADRatchetSession;
 | 
			
		||||
    class RatchetTagSet
 | 
			
		||||
    {
 | 
			
		||||
        public:
 | 
			
		||||
	class RatchetTagSet
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			RatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session): m_Session (session) {};
 | 
			
		||||
 | 
			
		||||
            void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
 | 
			
		||||
            void NextSessionTagRatchet ();
 | 
			
		||||
            uint64_t GetNextSessionTag ();
 | 
			
		||||
			void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
 | 
			
		||||
			void NextSessionTagRatchet ();
 | 
			
		||||
			uint64_t GetNextSessionTag ();
 | 
			
		||||
			const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
 | 
			
		||||
			int GetNextIndex () const { return m_NextIndex; };
 | 
			
		||||
			void GetSymmKey (int index, uint8_t * key);
 | 
			
		||||
| 
						 | 
				
			
			@ -52,51 +52,51 @@ namespace garlic
 | 
			
		|||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
           union
 | 
			
		||||
           {
 | 
			
		||||
               uint64_t ll[8]; 
 | 
			
		||||
               uint8_t buf[64];
 | 
			
		||||
			union
 | 
			
		||||
			{
 | 
			
		||||
				uint64_t ll[8];
 | 
			
		||||
				uint8_t buf[64];
 | 
			
		||||
 | 
			
		||||
               const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31]
 | 
			
		||||
               const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63] 
 | 
			
		||||
               uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]            
 | 
			
		||||
				const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31]
 | 
			
		||||
				const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63]
 | 
			
		||||
				uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
 | 
			
		||||
 | 
			
		||||
           } m_KeyData;  
 | 
			
		||||
           uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];   
 | 
			
		||||
		   int m_NextIndex, m_NextSymmKeyIndex;
 | 
			
		||||
		   std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
 | 
			
		||||
		   std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
 | 
			
		||||
		   int m_TagSetID = 0;	
 | 
			
		||||
		   uint64_t m_ExpirationTimestamp = 0;	
 | 
			
		||||
    };       
 | 
			
		||||
			} m_KeyData;
 | 
			
		||||
			uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
 | 
			
		||||
			int m_NextIndex, m_NextSymmKeyIndex;
 | 
			
		||||
			std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
 | 
			
		||||
			std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
 | 
			
		||||
			int m_TagSetID = 0;
 | 
			
		||||
			uint64_t m_ExpirationTimestamp = 0;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
    enum ECIESx25519BlockType
 | 
			
		||||
	enum ECIESx25519BlockType
 | 
			
		||||
	{
 | 
			
		||||
		eECIESx25519BlkDateTime = 0,
 | 
			
		||||
		eECIESx25519BlkSessionID = 1, 
 | 
			
		||||
		eECIESx25519BlkDateTime    = 0,
 | 
			
		||||
		eECIESx25519BlkSessionID   = 1,
 | 
			
		||||
		eECIESx25519BlkTermination = 4,
 | 
			
		||||
		eECIESx25519BlkOptions = 5,
 | 
			
		||||
		eECIESx25519BlkNextKey = 7,
 | 
			
		||||
		eECIESx25519BlkAck = 8,
 | 
			
		||||
		eECIESx25519BlkAckRequest = 9,
 | 
			
		||||
		eECIESx25519BlkGalicClove = 11,
 | 
			
		||||
		eECIESx25519BlkPadding = 254	
 | 
			
		||||
		eECIESx25519BlkOptions     = 5,
 | 
			
		||||
		eECIESx25519BlkNextKey     = 7,
 | 
			
		||||
		eECIESx25519BlkAck         = 8,
 | 
			
		||||
		eECIESx25519BlkAckRequest  = 9,
 | 
			
		||||
		eECIESx25519BlkGalicClove  = 11,
 | 
			
		||||
		eECIESx25519BlkPadding     = 254
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	const uint8_t ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG = 0x01;
 | 
			
		||||
	const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02;
 | 
			
		||||
	const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04;
 | 
			
		||||
 | 
			
		||||
    class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
 | 
			
		||||
    {
 | 
			
		||||
        enum SessionState
 | 
			
		||||
        {
 | 
			
		||||
            eSessionStateNew =0,
 | 
			
		||||
            eSessionStateNewSessionReceived,
 | 
			
		||||
	class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
 | 
			
		||||
	{
 | 
			
		||||
		enum SessionState
 | 
			
		||||
		{
 | 
			
		||||
			eSessionStateNew = 0,
 | 
			
		||||
			eSessionStateNewSessionReceived,
 | 
			
		||||
			eSessionStateNewSessionSent,
 | 
			
		||||
			eSessionStateNewSessionReplySent,
 | 
			
		||||
			eSessionStateEstablished
 | 
			
		||||
        };
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		struct DHRatchet
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -106,15 +106,15 @@ namespace garlic
 | 
			
		|||
			bool newKey = true;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
            ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet);
 | 
			
		||||
            ~ECIESX25519AEADRatchetSession ();
 | 
			
		||||
			ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet);
 | 
			
		||||
			~ECIESX25519AEADRatchetSession ();
 | 
			
		||||
 | 
			
		||||
			bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index = 0);
 | 
			
		||||
            std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
 | 
			
		||||
			std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
 | 
			
		||||
 | 
			
		||||
            const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
 | 
			
		||||
			const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
 | 
			
		||||
			void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
 | 
			
		||||
 | 
			
		||||
			void SetDestination (const i2p::data::IdentHash& dest) // TODO:
 | 
			
		||||
| 
						 | 
				
			
			@ -127,41 +127,41 @@ namespace garlic
 | 
			
		|||
 | 
			
		||||
			bool IsRatchets () const { return true; };
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			void ResetKeys ();
 | 
			
		||||
            void MixHash (const uint8_t * buf, size_t len);
 | 
			
		||||
			void MixHash (const uint8_t * buf, size_t len);
 | 
			
		||||
			void CreateNonce (uint64_t seqn, uint8_t * nonce);
 | 
			
		||||
            bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
 | 
			
		||||
			bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
 | 
			
		||||
			std::shared_ptr<RatchetTagSet> CreateNewSessionTagset ();
 | 
			
		||||
 | 
			
		||||
			bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
 | 
			
		||||
            bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
 | 
			
		||||
			bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
 | 
			
		||||
			bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index);
 | 
			
		||||
            void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index);
 | 
			
		||||
			void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index);
 | 
			
		||||
			void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset);
 | 
			
		||||
 | 
			
		||||
            bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
 | 
			
		||||
            bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
 | 
			
		||||
			bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
 | 
			
		||||
			bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
 | 
			
		||||
			bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
 | 
			
		||||
			bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
 | 
			
		||||
 | 
			
		||||
            std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
 | 
			
		||||
            size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false);
 | 
			
		||||
			std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
 | 
			
		||||
			size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false);
 | 
			
		||||
			size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);
 | 
			
		||||
 | 
			
		||||
			void GenerateMoreReceiveTags (std::shared_ptr<RatchetTagSet> receiveTagset, int numTags);
 | 
			
		||||
			void NewNextSendRatchet ();
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
            uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
 | 
			
		||||
			uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
 | 
			
		||||
			uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
 | 
			
		||||
			uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
 | 
			
		||||
            i2p::crypto::X25519Keys m_EphemeralKeys;
 | 
			
		||||
            SessionState m_State = eSessionStateNew;
 | 
			
		||||
			i2p::crypto::X25519Keys m_EphemeralKeys;
 | 
			
		||||
			SessionState m_State = eSessionStateNew;
 | 
			
		||||
			uint64_t m_LastActivityTimestamp = 0; // incoming
 | 
			
		||||
            std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRTagset;
 | 
			
		||||
			std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRTagset;
 | 
			
		||||
			std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
 | 
			
		||||
			std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index)
 | 
			
		||||
			bool m_SendReverseKey = false, m_SendForwardKey = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -175,7 +175,7 @@ namespace garlic
 | 
			
		|||
			{
 | 
			
		||||
				return m_Destination ? *m_Destination : i2p::data::IdentHash ();
 | 
			
		||||
			}
 | 
			
		||||
     };
 | 
			
		||||
	 };
 | 
			
		||||
 | 
			
		||||
	std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -597,4 +597,3 @@ namespace crypto
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,6 +128,4 @@ namespace crypto
 | 
			
		|||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ namespace crypto
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY, bool random) const
 | 
			
		||||
    {
 | 
			
		||||
	{
 | 
			
		||||
		bool ret = true;
 | 
			
		||||
		BN_CTX * ctx = BN_CTX_new ();
 | 
			
		||||
		BN_CTX_start (ctx);
 | 
			
		||||
| 
						 | 
				
			
			@ -63,11 +63,11 @@ namespace crypto
 | 
			
		|||
 | 
			
		||||
		if (Legendre (uxxA, ctx) != -1)
 | 
			
		||||
		{
 | 
			
		||||
            uint8_t randByte = 0; // random highest bits and high y
 | 
			
		||||
			uint8_t randByte = 0; // random highest bits and high y
 | 
			
		||||
			if (random)
 | 
			
		||||
			{
 | 
			
		||||
            	RAND_bytes (&randByte, 1);
 | 
			
		||||
            	highY = randByte & 0x01;
 | 
			
		||||
				RAND_bytes (&randByte, 1);
 | 
			
		||||
				highY = randByte & 0x01;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			BIGNUM * r = BN_CTX_get (ctx);
 | 
			
		||||
| 
						 | 
				
			
			@ -87,7 +87,7 @@ namespace crypto
 | 
			
		|||
			bn2buf (r, encoded, 32);
 | 
			
		||||
 | 
			
		||||
			if (random)
 | 
			
		||||
            	encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte
 | 
			
		||||
				encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte
 | 
			
		||||
			for (size_t i = 0; i < 16; i++) // To Little Endian
 | 
			
		||||
			{
 | 
			
		||||
				uint8_t tmp = encoded[i];
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +115,7 @@ namespace crypto
 | 
			
		|||
			encoded1[i] = encoded[31 - i];
 | 
			
		||||
			encoded1[31 - i] = encoded[i];
 | 
			
		||||
		}
 | 
			
		||||
        encoded1[0] &= 0x3F; // drop two highest bits
 | 
			
		||||
		encoded1[0] &= 0x3F; // drop two highest bits
 | 
			
		||||
 | 
			
		||||
		BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -184,7 +184,7 @@ namespace crypto
 | 
			
		|||
		BN_mod_exp (r, a, p12, p, ctx); // 	r = a^((p-1)/2) mod p
 | 
			
		||||
		if (BN_is_word(r, 1))
 | 
			
		||||
			return 1;
 | 
			
		||||
        else if (BN_is_zero(r)) 
 | 
			
		||||
		else if (BN_is_zero(r))
 | 
			
		||||
			return 0;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -204,4 +204,3 @@ namespace crypto
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,5 +35,3 @@ namespace crypto
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										221
									
								
								libi2pd/FS.h
									
										
									
									
									
								
							
							
						
						
									
										221
									
								
								libi2pd/FS.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -17,133 +17,136 @@
 | 
			
		|||
 | 
			
		||||
namespace i2p {
 | 
			
		||||
namespace fs {
 | 
			
		||||
  extern std::string dirSep;
 | 
			
		||||
	extern std::string dirSep;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief Class to work with NetDb & Router profiles
 | 
			
		||||
   *
 | 
			
		||||
   * Usage:
 | 
			
		||||
   *
 | 
			
		||||
   * const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
 | 
			
		||||
   * auto h = HashedStorage("name", "y", "z-", ".txt");
 | 
			
		||||
   * h.SetPlace("/tmp/hs-test");
 | 
			
		||||
   * h.GetName()          -> gives "name"
 | 
			
		||||
   * h.GetRoot()          -> gives "/tmp/hs-test/name"
 | 
			
		||||
   * h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet
 | 
			
		||||
   * h.Path("abcd");      <- returns /tmp/hs-test/name/ya/z-abcd.txt
 | 
			
		||||
   * h.Remove("abcd");    <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists
 | 
			
		||||
   * std::vector<std::string> files;
 | 
			
		||||
   * h.Traverse(files);   <- finds all files in storage and saves in given vector
 | 
			
		||||
   */
 | 
			
		||||
  class HashedStorage {
 | 
			
		||||
    protected:
 | 
			
		||||
      std::string root;    /**< path to storage with it's name included */
 | 
			
		||||
      std::string name;    /**< name of the storage */
 | 
			
		||||
      std::string prefix1; /**< hashed directory prefix */
 | 
			
		||||
      std::string prefix2; /**< prefix of file in storage */
 | 
			
		||||
      std::string suffix;  /**< suffix of file in storage (extension) */
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief Class to work with NetDb & Router profiles
 | 
			
		||||
	 *
 | 
			
		||||
	 * Usage:
 | 
			
		||||
	 *
 | 
			
		||||
	 * const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
 | 
			
		||||
	 * auto h = HashedStorage("name", "y", "z-", ".txt");
 | 
			
		||||
	 * h.SetPlace("/tmp/hs-test");
 | 
			
		||||
	 * h.GetName()          -> gives "name"
 | 
			
		||||
	 * h.GetRoot()          -> gives "/tmp/hs-test/name"
 | 
			
		||||
	 * h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet
 | 
			
		||||
	 * h.Path("abcd");      <- returns /tmp/hs-test/name/ya/z-abcd.txt
 | 
			
		||||
	 * h.Remove("abcd");    <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists
 | 
			
		||||
	 * std::vector<std::string> files;
 | 
			
		||||
	 * h.Traverse(files);   <- finds all files in storage and saves in given vector
 | 
			
		||||
	 */
 | 
			
		||||
	class HashedStorage
 | 
			
		||||
	{
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      typedef std::function<void(const std::string &)> FilenameVisitor;
 | 
			
		||||
      HashedStorage(const char *n, const char *p1, const char *p2, const char *s):
 | 
			
		||||
        name(n), prefix1(p1), prefix2(p2), suffix(s) {};
 | 
			
		||||
			std::string root;    /**< path to storage with it's name included */
 | 
			
		||||
			std::string name;    /**< name of the storage */
 | 
			
		||||
			std::string prefix1; /**< hashed directory prefix */
 | 
			
		||||
			std::string prefix2; /**< prefix of file in storage */
 | 
			
		||||
			std::string suffix;  /**< suffix of file in storage (extension) */
 | 
			
		||||
 | 
			
		||||
      /** create subdirs in storage */
 | 
			
		||||
      bool Init(const char* chars, size_t cnt);
 | 
			
		||||
      const std::string & GetRoot() const { return root; }
 | 
			
		||||
      const std::string & GetName() const { return name; }
 | 
			
		||||
      /** set directory where to place storage directory */
 | 
			
		||||
      void SetPlace(const std::string & path);
 | 
			
		||||
      /** path to file with given ident */
 | 
			
		||||
      std::string Path(const std::string & ident) const;
 | 
			
		||||
      /** remove file by ident */
 | 
			
		||||
      void Remove(const std::string & ident);
 | 
			
		||||
      /** find all files in storage and store list in provided vector */
 | 
			
		||||
      void Traverse(std::vector<std::string> & files);
 | 
			
		||||
      /** visit every file in this storage with a visitor */
 | 
			
		||||
      void Iterate(FilenameVisitor v);
 | 
			
		||||
  };
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
  /** @brief Returns current application name, default 'i2pd' */
 | 
			
		||||
			typedef std::function<void(const std::string &)> FilenameVisitor;
 | 
			
		||||
			HashedStorage(const char *n, const char *p1, const char *p2, const char *s):
 | 
			
		||||
				name(n), prefix1(p1), prefix2(p2), suffix(s) {};
 | 
			
		||||
 | 
			
		||||
			/** create subdirs in storage */
 | 
			
		||||
			bool Init(const char* chars, size_t cnt);
 | 
			
		||||
			const std::string & GetRoot() const { return root; }
 | 
			
		||||
			const std::string & GetName() const { return name; }
 | 
			
		||||
			/** set directory where to place storage directory */
 | 
			
		||||
			void SetPlace(const std::string & path);
 | 
			
		||||
			/** path to file with given ident */
 | 
			
		||||
			std::string Path(const std::string & ident) const;
 | 
			
		||||
			/** remove file by ident */
 | 
			
		||||
			void Remove(const std::string & ident);
 | 
			
		||||
			/** find all files in storage and store list in provided vector */
 | 
			
		||||
			void Traverse(std::vector<std::string> & files);
 | 
			
		||||
			/** visit every file in this storage with a visitor */
 | 
			
		||||
			void Iterate(FilenameVisitor v);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	/** @brief Returns current application name, default 'i2pd' */
 | 
			
		||||
	const std::string & GetAppName ();
 | 
			
		||||
  /** @brief Set application name, affects autodetection of datadir */
 | 
			
		||||
	/** @brief Set application name, affects autodetection of datadir */
 | 
			
		||||
	void SetAppName (const std::string& name);
 | 
			
		||||
 | 
			
		||||
  /** @brief Returns datadir path */
 | 
			
		||||
  const std::string & GetDataDir();
 | 
			
		||||
	/** @brief Returns datadir path */
 | 
			
		||||
	const std::string & GetDataDir();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief Set datadir either from cmdline option or using autodetection
 | 
			
		||||
   * @param cmdline_param  Value of cmdline parameter --datadir=<something>
 | 
			
		||||
   * @param isService      Value of cmdline parameter --service
 | 
			
		||||
   *
 | 
			
		||||
   * Examples of autodetected paths:
 | 
			
		||||
   *
 | 
			
		||||
   *   Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\
 | 
			
		||||
   *   Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\
 | 
			
		||||
   *   Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
 | 
			
		||||
   *   Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
 | 
			
		||||
   */
 | 
			
		||||
  void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief Set datadir either from cmdline option or using autodetection
 | 
			
		||||
	 * @param cmdline_param  Value of cmdline parameter --datadir=<something>
 | 
			
		||||
	 * @param isService      Value of cmdline parameter --service
 | 
			
		||||
	 *
 | 
			
		||||
	 * Examples of autodetected paths:
 | 
			
		||||
	 *
 | 
			
		||||
	 *   Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\
 | 
			
		||||
	 *   Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\
 | 
			
		||||
	 *   Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
 | 
			
		||||
	 *   Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
 | 
			
		||||
	 */
 | 
			
		||||
	void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief Create subdirectories inside datadir
 | 
			
		||||
   */
 | 
			
		||||
  bool Init();
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief Create subdirectories inside datadir
 | 
			
		||||
	 */
 | 
			
		||||
	bool Init();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief Get list of files in directory
 | 
			
		||||
   * @param path  Path to directory
 | 
			
		||||
   * @param files Vector to store found files
 | 
			
		||||
   * @return true on success and false if directory not exists
 | 
			
		||||
   */
 | 
			
		||||
  bool ReadDir(const std::string & path, std::vector<std::string> & files);
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief Get list of files in directory
 | 
			
		||||
	 * @param path  Path to directory
 | 
			
		||||
	 * @param files Vector to store found files
 | 
			
		||||
	 * @return true on success and false if directory not exists
 | 
			
		||||
	 */
 | 
			
		||||
	bool ReadDir(const std::string & path, std::vector<std::string> & files);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief Remove file with given path
 | 
			
		||||
   * @param path Absolute path to file
 | 
			
		||||
   * @return true on success, false if file not exists, throws exception on error
 | 
			
		||||
   */
 | 
			
		||||
  bool Remove(const std::string & path);
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief Remove file with given path
 | 
			
		||||
	 * @param path Absolute path to file
 | 
			
		||||
	 * @return true on success, false if file not exists, throws exception on error
 | 
			
		||||
	 */
 | 
			
		||||
	bool Remove(const std::string & path);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief Check existence of file
 | 
			
		||||
   * @param path Absolute path to file
 | 
			
		||||
   * @return true if file exists, false otherwise
 | 
			
		||||
   */
 | 
			
		||||
  bool Exists(const std::string & path);
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief Check existence of file
 | 
			
		||||
	 * @param path Absolute path to file
 | 
			
		||||
	 * @return true if file exists, false otherwise
 | 
			
		||||
	 */
 | 
			
		||||
	bool Exists(const std::string & path);
 | 
			
		||||
 | 
			
		||||
  uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch
 | 
			
		||||
	uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch
 | 
			
		||||
 | 
			
		||||
  bool CreateDirectory (const std::string& path);
 | 
			
		||||
	bool CreateDirectory (const std::string& path);
 | 
			
		||||
 | 
			
		||||
  template<typename T>
 | 
			
		||||
  void _ExpandPath(std::stringstream & path, T c) {
 | 
			
		||||
    path << i2p::fs::dirSep << c;
 | 
			
		||||
  }
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	void _ExpandPath(std::stringstream & path, T c) {
 | 
			
		||||
		path << i2p::fs::dirSep << c;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  template<typename T, typename ... Other>
 | 
			
		||||
  void _ExpandPath(std::stringstream & path, T c, Other ... other) {
 | 
			
		||||
    _ExpandPath(path, c);
 | 
			
		||||
    _ExpandPath(path, other ...);
 | 
			
		||||
  }
 | 
			
		||||
	template<typename T, typename ... Other>
 | 
			
		||||
	void _ExpandPath(std::stringstream & path, T c, Other ... other) {
 | 
			
		||||
		_ExpandPath(path, c);
 | 
			
		||||
		_ExpandPath(path, other ...);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief Get path relative to datadir
 | 
			
		||||
   *
 | 
			
		||||
   * Examples (with datadir = "/tmp/i2pd"):
 | 
			
		||||
   *
 | 
			
		||||
   * i2p::fs::Path("test")             -> '/tmp/i2pd/test'
 | 
			
		||||
   * i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt'
 | 
			
		||||
   */
 | 
			
		||||
  template<typename ... Other>
 | 
			
		||||
  std::string DataDirPath(Other ... components) {
 | 
			
		||||
    std::stringstream s("");
 | 
			
		||||
    s << i2p::fs::GetDataDir();
 | 
			
		||||
    _ExpandPath(s, components ...);
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief Get path relative to datadir
 | 
			
		||||
	 *
 | 
			
		||||
	 * Examples (with datadir = "/tmp/i2pd"):
 | 
			
		||||
	 *
 | 
			
		||||
	 * i2p::fs::Path("test")             -> '/tmp/i2pd/test'
 | 
			
		||||
	 * i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt'
 | 
			
		||||
	 */
 | 
			
		||||
	template<typename ... Other>
 | 
			
		||||
	std::string DataDirPath(Other ... components) {
 | 
			
		||||
		std::stringstream s("");
 | 
			
		||||
		s << i2p::fs::GetDataDir();
 | 
			
		||||
		_ExpandPath(s, components ...);
 | 
			
		||||
 | 
			
		||||
    return s.str();
 | 
			
		||||
  }
 | 
			
		||||
		return s.str();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template<typename Storage, typename... Filename>
 | 
			
		||||
	std::string StorageRootPath (const Storage& storage, Filename... filenames)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -179,4 +179,3 @@ namespace data
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,9 +38,9 @@ namespace garlic
 | 
			
		|||
		if (!m_SharedRoutingPath) return nullptr;
 | 
			
		||||
		uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
 | 
			
		||||
		if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED ||
 | 
			
		||||
		    !m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
 | 
			
		||||
			!m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
 | 
			
		||||
			ts*1000LL > m_SharedRoutingPath->remoteLease->endDate ||
 | 
			
		||||
		    ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
 | 
			
		||||
			ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
 | 
			
		||||
				m_SharedRoutingPath = nullptr;
 | 
			
		||||
		if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++;
 | 
			
		||||
		return m_SharedRoutingPath;
 | 
			
		||||
| 
						 | 
				
			
			@ -96,10 +96,10 @@ namespace garlic
 | 
			
		|||
		return msg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner,
 | 
			
		||||
	    std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet):
 | 
			
		||||
        GarlicRoutingSession (owner, attachLeaseSet), 
 | 
			
		||||
        m_Destination (destination), m_NumTags (numTags)
 | 
			
		||||
	ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner,
 | 
			
		||||
		std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet):
 | 
			
		||||
		GarlicRoutingSession (owner, attachLeaseSet),
 | 
			
		||||
		m_Destination (destination), m_NumTags (numTags)
 | 
			
		||||
	{
 | 
			
		||||
		// create new session tags and session key
 | 
			
		||||
		RAND_bytes (m_SessionKey, 32);
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +115,7 @@ namespace garlic
 | 
			
		|||
		m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
 | 
			
		||||
	std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
 | 
			
		||||
	{
 | 
			
		||||
		auto m = NewI2NPMessage ();
 | 
			
		||||
		m->Align (12); // in order to get buf aligned to 16 (12 + 4)
 | 
			
		||||
| 
						 | 
				
			
			@ -181,7 +181,7 @@ namespace garlic
 | 
			
		|||
		return m;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg)
 | 
			
		||||
	size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg)
 | 
			
		||||
	{
 | 
			
		||||
		size_t blockSize = 0;
 | 
			
		||||
		bool createNewTags = GetOwner () && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags*2/3);
 | 
			
		||||
| 
						 | 
				
			
			@ -353,7 +353,7 @@ namespace garlic
 | 
			
		|||
		return size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags ()
 | 
			
		||||
	ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags ()
 | 
			
		||||
	{
 | 
			
		||||
		auto tags = new UnconfirmedTags (m_NumTags);
 | 
			
		||||
		tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch ();
 | 
			
		||||
| 
						 | 
				
			
			@ -525,7 +525,7 @@ namespace garlic
 | 
			
		|||
					// otherwise ECIESx25519
 | 
			
		||||
					auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
 | 
			
		||||
					if (!session->HandleNextMessage (buf, length, nullptr, 0))
 | 
			
		||||
        				LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
 | 
			
		||||
						LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					LogPrint (eLogError, "Garlic: Failed to decrypt message");
 | 
			
		||||
| 
						 | 
				
			
			@ -703,41 +703,41 @@ namespace garlic
 | 
			
		|||
	std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
 | 
			
		||||
		std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
 | 
			
		||||
	{
 | 
			
		||||
        if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET &&
 | 
			
		||||
            SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
 | 
			
		||||
        {
 | 
			
		||||
            ECIESX25519AEADRatchetSessionPtr session;
 | 
			
		||||
            uint8_t staticKey[32];
 | 
			
		||||
            destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key 
 | 
			
		||||
            auto it = m_ECIESx25519Sessions.find (staticKey);
 | 
			
		||||
		if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET &&
 | 
			
		||||
			SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
 | 
			
		||||
		{
 | 
			
		||||
			ECIESX25519AEADRatchetSessionPtr session;
 | 
			
		||||
			uint8_t staticKey[32];
 | 
			
		||||
			destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key
 | 
			
		||||
			auto it = m_ECIESx25519Sessions.find (staticKey);
 | 
			
		||||
			if (it != m_ECIESx25519Sessions.end ())
 | 
			
		||||
		        session = it->second;
 | 
			
		||||
            if (!session)
 | 
			
		||||
				session = it->second;
 | 
			
		||||
			if (!session)
 | 
			
		||||
			{
 | 
			
		||||
				session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
 | 
			
		||||
				session->SetRemoteStaticKey (staticKey);
 | 
			
		||||
			}
 | 
			
		||||
			session->SetDestination (destination->GetIdentHash ()); // TODO: remove
 | 
			
		||||
            return session;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {    
 | 
			
		||||
		    ElGamalAESSessionPtr session;
 | 
			
		||||
		    {
 | 
			
		||||
			    std::unique_lock<std::mutex> l(m_SessionsMutex);
 | 
			
		||||
			    auto it = m_Sessions.find (destination->GetIdentHash ());
 | 
			
		||||
			    if (it != m_Sessions.end ())
 | 
			
		||||
				    session = it->second;
 | 
			
		||||
		    }
 | 
			
		||||
		    if (!session)
 | 
			
		||||
		    {
 | 
			
		||||
			    session = std::make_shared<ElGamalAESSession> (this, destination,
 | 
			
		||||
				    attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests
 | 
			
		||||
			    std::unique_lock<std::mutex> l(m_SessionsMutex);
 | 
			
		||||
			    m_Sessions[destination->GetIdentHash ()] = session;
 | 
			
		||||
		    }
 | 
			
		||||
		    return session;
 | 
			
		||||
        }
 | 
			
		||||
			return session;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			ElGamalAESSessionPtr session;
 | 
			
		||||
			{
 | 
			
		||||
				std::unique_lock<std::mutex> l(m_SessionsMutex);
 | 
			
		||||
				auto it = m_Sessions.find (destination->GetIdentHash ());
 | 
			
		||||
				if (it != m_Sessions.end ())
 | 
			
		||||
					session = it->second;
 | 
			
		||||
			}
 | 
			
		||||
			if (!session)
 | 
			
		||||
			{
 | 
			
		||||
				session = std::make_shared<ElGamalAESSession> (this, destination,
 | 
			
		||||
					attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests
 | 
			
		||||
				std::unique_lock<std::mutex> l(m_SessionsMutex);
 | 
			
		||||
				m_Sessions[destination->GetIdentHash ()] = session;
 | 
			
		||||
			}
 | 
			
		||||
			return session;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void GarlicDestination::CleanupExpiredTags ()
 | 
			
		||||
| 
						 | 
				
			
			@ -925,20 +925,20 @@ namespace garlic
 | 
			
		|||
		std::vector<std::string> files;
 | 
			
		||||
		i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files);
 | 
			
		||||
		uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
 | 
			
		||||
		for (auto  it: files)
 | 
			
		||||
		for (auto it: files)
 | 
			
		||||
			if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
 | 
			
		||||
				 i2p::fs::Remove (it);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
 | 
			
		||||
    {   
 | 
			
		||||
        const uint8_t * buf1 = buf;	
 | 
			
		||||
	void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
 | 
			
		||||
	{
 | 
			
		||||
		const uint8_t * buf1 = buf;
 | 
			
		||||
		uint8_t flag = buf[0]; buf++; // flag
 | 
			
		||||
		GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03);
 | 
			
		||||
		switch (deliveryType)
 | 
			
		||||
		{
 | 
			
		||||
			case eGarlicDeliveryTypeDestination:
 | 
			
		||||
                LogPrint (eLogDebug, "Garlic: type destination");
 | 
			
		||||
				LogPrint (eLogDebug, "Garlic: type destination");
 | 
			
		||||
				buf += 32; // TODO: check destination
 | 
			
		||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
 | 
			
		||||
				[[fallthrough]];
 | 
			
		||||
| 
						 | 
				
			
			@ -946,7 +946,7 @@ namespace garlic
 | 
			
		|||
				// no break here
 | 
			
		||||
			case eGarlicDeliveryTypeLocal:
 | 
			
		||||
			{
 | 
			
		||||
                LogPrint (eLogDebug, "Garlic: type local");
 | 
			
		||||
				LogPrint (eLogDebug, "Garlic: type local");
 | 
			
		||||
				I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
 | 
			
		||||
				buf += (4 + 4); // msgID + expiration
 | 
			
		||||
				ptrdiff_t offset = buf - buf1;
 | 
			
		||||
| 
						 | 
				
			
			@ -957,8 +957,8 @@ namespace garlic
 | 
			
		|||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			case eGarlicDeliveryTypeTunnel:
 | 
			
		||||
            {
 | 
			
		||||
                LogPrint (eLogDebug, "Garlic: type tunnel");
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogDebug, "Garlic: type tunnel");
 | 
			
		||||
				// gwHash and gwTunnel sequence is reverted
 | 
			
		||||
				const uint8_t * gwHash = buf;
 | 
			
		||||
				buf += 32;
 | 
			
		||||
| 
						 | 
				
			
			@ -969,32 +969,32 @@ namespace garlic
 | 
			
		|||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				uint32_t gwTunnel = bufbe32toh (buf); buf += 4;
 | 
			
		||||
                I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
 | 
			
		||||
				I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
 | 
			
		||||
				buf += (4 + 4); // msgID + expiration
 | 
			
		||||
                offset += 13;
 | 
			
		||||
				offset += 13;
 | 
			
		||||
				if (GetTunnelPool ())
 | 
			
		||||
                {
 | 
			
		||||
                    auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
 | 
			
		||||
                    if (tunnel)
 | 
			
		||||
					    tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset));
 | 
			
		||||
				{
 | 
			
		||||
					auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
 | 
			
		||||
					if (tunnel)
 | 
			
		||||
						tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset));
 | 
			
		||||
					else
 | 
			
		||||
					    LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
 | 
			
		||||
                }
 | 
			
		||||
						LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel");
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			default:
 | 
			
		||||
				LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType);
 | 
			
		||||
		}
 | 
			
		||||
    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
 | 
			
		||||
    {
 | 
			
		||||
	void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
 | 
			
		||||
	{
 | 
			
		||||
		auto index = tagset->GetNextIndex ();
 | 
			
		||||
		uint64_t tag = tagset->GetNextSessionTag ();
 | 
			
		||||
        m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()});
 | 
			
		||||
    }
 | 
			
		||||
		m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,7 +87,7 @@ namespace garlic
 | 
			
		|||
	class GarlicDestination;
 | 
			
		||||
	class GarlicRoutingSession
 | 
			
		||||
	{
 | 
			
		||||
        protected:
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			enum LeaseSetUpdateStatus
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ namespace garlic
 | 
			
		|||
			GarlicRoutingSession ();
 | 
			
		||||
			virtual ~GarlicRoutingSession ();
 | 
			
		||||
			virtual std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) = 0;
 | 
			
		||||
            virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession
 | 
			
		||||
			virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession
 | 
			
		||||
			virtual bool MessageConfirmed (uint32_t msgID);
 | 
			
		||||
			virtual bool IsRatchets () const { return false; };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -122,13 +122,13 @@ namespace garlic
 | 
			
		|||
			GarlicDestination * GetOwner () const { return m_Owner; }
 | 
			
		||||
			void SetOwner (GarlicDestination * owner) { m_Owner = owner; }
 | 
			
		||||
 | 
			
		||||
        protected:
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
            LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; }
 | 
			
		||||
            void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; }
 | 
			
		||||
            uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; }
 | 
			
		||||
            void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; }
 | 
			
		||||
            void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; }    
 | 
			
		||||
			LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; }
 | 
			
		||||
			void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; }
 | 
			
		||||
			uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; }
 | 
			
		||||
			void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; }
 | 
			
		||||
			void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; }
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<I2NPMessage> CreateEncryptedDeliveryStatusMsg (uint32_t msgID);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -143,38 +143,39 @@ namespace garlic
 | 
			
		|||
			std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			// for HTTP only
 | 
			
		||||
			virtual size_t GetNumOutgoingTags () const { return 0; };
 | 
			
		||||
	};
 | 
			
		||||
    //using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
 | 
			
		||||
	//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
 | 
			
		||||
	typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8
 | 
			
		||||
 | 
			
		||||
    class ElGamalAESSession: public GarlicRoutingSession,  public std::enable_shared_from_this<ElGamalAESSession>
 | 
			
		||||
    {
 | 
			
		||||
            struct UnconfirmedTags
 | 
			
		||||
			{
 | 
			
		||||
				UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; };
 | 
			
		||||
				~UnconfirmedTags () { delete[] sessionTags; };
 | 
			
		||||
				uint32_t msgID;
 | 
			
		||||
				int numTags;
 | 
			
		||||
				SessionTag * sessionTags;
 | 
			
		||||
				uint32_t tagsCreationTime;
 | 
			
		||||
			};
 | 
			
		||||
	class ElGamalAESSession: public GarlicRoutingSession,  public std::enable_shared_from_this<ElGamalAESSession>
 | 
			
		||||
	{
 | 
			
		||||
		struct UnconfirmedTags
 | 
			
		||||
		{
 | 
			
		||||
			UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; };
 | 
			
		||||
			~UnconfirmedTags () { delete[] sessionTags; };
 | 
			
		||||
			uint32_t msgID;
 | 
			
		||||
			int numTags;
 | 
			
		||||
			SessionTag * sessionTags;
 | 
			
		||||
			uint32_t tagsCreationTime;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
            ElGamalAESSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination,
 | 
			
		||||
			ElGamalAESSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination,
 | 
			
		||||
				int numTags, bool attachLeaseSet);
 | 
			
		||||
			ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption
 | 
			
		||||
			~ElGamalAESSession () {};
 | 
			
		||||
 | 
			
		||||
            std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
 | 
			
		||||
			std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
 | 
			
		||||
 | 
			
		||||
            bool MessageConfirmed (uint32_t msgID);
 | 
			
		||||
			bool MessageConfirmed (uint32_t msgID);
 | 
			
		||||
			bool CleanupExpiredTags (); // returns true if something left
 | 
			
		||||
			bool CleanupUnconfirmedTags (); // returns true if something has been deleted
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			size_t CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg);
 | 
			
		||||
			size_t CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags);
 | 
			
		||||
| 
						 | 
				
			
			@ -184,25 +185,26 @@ namespace garlic
 | 
			
		|||
			void TagsConfirmed (uint32_t msgID);
 | 
			
		||||
			UnconfirmedTags * GenerateSessionTags ();
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
            std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
 | 
			
		||||
			std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
 | 
			
		||||
 | 
			
		||||
            i2p::crypto::AESKey m_SessionKey;
 | 
			
		||||
			i2p::crypto::AESKey m_SessionKey;
 | 
			
		||||
			std::list<SessionTag> m_SessionTags;
 | 
			
		||||
			int m_NumTags;
 | 
			
		||||
			std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
 | 
			
		||||
 | 
			
		||||
            i2p::crypto::CBCEncryption m_Encryption;
 | 
			
		||||
			i2p::crypto::CBCEncryption m_Encryption;
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
			// for HTTP only
 | 
			
		||||
			size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
 | 
			
		||||
    };
 | 
			
		||||
	};
 | 
			
		||||
	typedef std::shared_ptr<ElGamalAESSession> ElGamalAESSessionPtr;
 | 
			
		||||
 | 
			
		||||
    class ECIESX25519AEADRatchetSession;
 | 
			
		||||
    typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr;  
 | 
			
		||||
	class ECIESX25519AEADRatchetSession;
 | 
			
		||||
	typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr;
 | 
			
		||||
	class RatchetTagSet;
 | 
			
		||||
	typedef std::shared_ptr<RatchetTagSet> RatchetTagSetPtr;
 | 
			
		||||
	struct ECIESX25519AEADRatchetIndexTagset
 | 
			
		||||
| 
						 | 
				
			
			@ -226,12 +228,12 @@ namespace garlic
 | 
			
		|||
			void CleanupExpiredTags ();
 | 
			
		||||
			void RemoveDeliveryStatusSession (uint32_t msgID);
 | 
			
		||||
			std::shared_ptr<I2NPMessage> WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
 | 
			
		||||
			    std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
 | 
			
		||||
				std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
 | 
			
		||||
 | 
			
		||||
			void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
 | 
			
		||||
			virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
 | 
			
		||||
			void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
 | 
			
		||||
            void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
 | 
			
		||||
			void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
 | 
			
		||||
			void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
 | 
			
		||||
			void RemoveECIESx25519Session (const uint8_t * staticKey);
 | 
			
		||||
			void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
 | 
			
		||||
| 
						 | 
				
			
			@ -266,10 +268,10 @@ namespace garlic
 | 
			
		|||
			int m_NumTags;
 | 
			
		||||
			std::mutex m_SessionsMutex;
 | 
			
		||||
			std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
 | 
			
		||||
            std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
 | 
			
		||||
			std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
 | 
			
		||||
			// incoming
 | 
			
		||||
			std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;
 | 
			
		||||
            std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexTagset> m_ECIESx25519Tags; // session tag -> session
 | 
			
		||||
			std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexTagset> m_ECIESx25519Tags; // session tag -> session
 | 
			
		||||
			// DeliveryStatus
 | 
			
		||||
			std::mutex m_DeliveryStatusSessionsMutex;
 | 
			
		||||
			std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,11 +13,11 @@ namespace crypto
 | 
			
		|||
 | 
			
		||||
	enum GOSTR3410ParamSet
 | 
			
		||||
	{
 | 
			
		||||
		eGOSTR3410CryptoProA = 0,   // 1.2.643.2.2.35.1
 | 
			
		||||
		eGOSTR3410CryptoProA = 0,  // 1.2.643.2.2.35.1
 | 
			
		||||
		// XchA = A, XchB = C
 | 
			
		||||
		//eGOSTR3410CryptoProXchA,    // 1.2.643.2.2.36.0
 | 
			
		||||
		//eGOSTR3410CryptoProXchB,	// 1.2.643.2.2.36.1
 | 
			
		||||
		eGOSTR3410TC26A512,		// 1.2.643.7.1.2.1.2.1
 | 
			
		||||
		//eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0
 | 
			
		||||
		//eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1
 | 
			
		||||
		eGOSTR3410TC26A512,        // 1.2.643.7.1.2.1.2.1
 | 
			
		||||
		eGOSTR3410NumParamSets
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,6 @@ namespace data
 | 
			
		|||
 | 
			
		||||
	size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen); // for < 64K
 | 
			
		||||
	size_t GzipNoCompression (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen); // for total size < 64K
 | 
			
		||||
		
 | 
			
		||||
} // data
 | 
			
		||||
} // i2p
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -180,7 +180,7 @@ namespace i2p
 | 
			
		|||
		// excluded
 | 
			
		||||
		if (cnt > 512)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogWarning,  "I2NP: Too many peers to exclude ", cnt, " for DatabaseLookup");
 | 
			
		||||
			LogPrint (eLogWarning, "I2NP: Too many peers to exclude ", cnt, " for DatabaseLookup");
 | 
			
		||||
			cnt = 0;
 | 
			
		||||
		}
 | 
			
		||||
		htobe16buf (buf, cnt);
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +205,7 @@ namespace i2p
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident,
 | 
			
		||||
		 std::vector<i2p::data::IdentHash> routers)
 | 
			
		||||
		std::vector<i2p::data::IdentHash> routers)
 | 
			
		||||
	{
 | 
			
		||||
		auto m = NewI2NPShortMessage ();
 | 
			
		||||
		uint8_t * buf = m->GetPayload ();
 | 
			
		||||
| 
						 | 
				
			
			@ -268,7 +268,7 @@ namespace i2p
 | 
			
		|||
		auto m = NewI2NPShortMessage ();
 | 
			
		||||
		uint8_t * payload = m->GetPayload ();
 | 
			
		||||
		memcpy (payload + DATABASE_STORE_KEY_OFFSET, storeHash, 32);
 | 
			
		||||
		payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); //  1 for LeaseSet
 | 
			
		||||
		payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet
 | 
			
		||||
		htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0);
 | 
			
		||||
		size_t size = DATABASE_STORE_HEADER_SIZE;
 | 
			
		||||
		memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ());
 | 
			
		||||
| 
						 | 
				
			
			@ -278,7 +278,7 @@ namespace i2p
 | 
			
		|||
		return m;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet,  uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
 | 
			
		||||
	std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet, uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
 | 
			
		||||
	{
 | 
			
		||||
		if (!leaseSet) return nullptr;
 | 
			
		||||
		auto m = NewI2NPShortMessage ();
 | 
			
		||||
| 
						 | 
				
			
			@ -347,11 +347,11 @@ namespace i2p
 | 
			
		|||
					auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
 | 
			
		||||
							bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
 | 
			
		||||
							clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
 | 
			
		||||
						    bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
 | 
			
		||||
							bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
 | 
			
		||||
							clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
 | 
			
		||||
						    clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
 | 
			
		||||
							clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
 | 
			
		||||
							clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80,
 | 
			
		||||
						    clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40);
 | 
			
		||||
							clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40);
 | 
			
		||||
					i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
 | 
			
		||||
					record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 0;
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -386,7 +386,7 @@ namespace i2p
 | 
			
		|||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		auto tunnel =  i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID);
 | 
			
		||||
		auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID);
 | 
			
		||||
		if (tunnel)
 | 
			
		||||
		{
 | 
			
		||||
			// endpoint of inbound tunnel
 | 
			
		||||
| 
						 | 
				
			
			@ -414,7 +414,7 @@ namespace i2p
 | 
			
		|||
					transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
 | 
			
		||||
						CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
 | 
			
		||||
							eI2NPVariableTunnelBuildReply, buf, len,
 | 
			
		||||
						    bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
 | 
			
		||||
							bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
 | 
			
		||||
| 
						 | 
				
			
			@ -440,7 +440,7 @@ namespace i2p
 | 
			
		|||
				transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
 | 
			
		||||
					CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
 | 
			
		||||
						eI2NPTunnelBuildReply, buf, len,
 | 
			
		||||
					    bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
 | 
			
		||||
						bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
				transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
 | 
			
		||||
| 
						 | 
				
			
			@ -592,13 +592,13 @@ namespace i2p
 | 
			
		|||
		switch (typeID)
 | 
			
		||||
		{
 | 
			
		||||
			case eI2NPVariableTunnelBuild:
 | 
			
		||||
				HandleVariableTunnelBuildMsg  (msgID, buf, size);
 | 
			
		||||
				HandleVariableTunnelBuildMsg (msgID, buf, size);
 | 
			
		||||
			break;
 | 
			
		||||
			case eI2NPVariableTunnelBuildReply:
 | 
			
		||||
				HandleVariableTunnelBuildReplyMsg (msgID, buf, size);
 | 
			
		||||
			break;
 | 
			
		||||
			case eI2NPTunnelBuild:
 | 
			
		||||
				HandleTunnelBuildMsg  (buf, size);
 | 
			
		||||
				HandleTunnelBuildMsg (buf, size);
 | 
			
		||||
			break;
 | 
			
		||||
			case eI2NPTunnelBuildReply:
 | 
			
		||||
				// TODO:
 | 
			
		||||
| 
						 | 
				
			
			@ -667,7 +667,7 @@ namespace i2p
 | 
			
		|||
		Flush ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage>  msg)
 | 
			
		||||
	void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage> msg)
 | 
			
		||||
	{
 | 
			
		||||
		if (msg)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -148,7 +148,7 @@ namespace data
 | 
			
		|||
			const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; };
 | 
			
		||||
			size_t GetSignatureLen () const; // might not match identity
 | 
			
		||||
			bool IsOfflineSignature () const { return m_TransientSignatureLen > 0; };
 | 
			
		||||
    		uint8_t * GetPadding();
 | 
			
		||||
			uint8_t * GetPadding();
 | 
			
		||||
			void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); }
 | 
			
		||||
			void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -204,7 +204,7 @@ namespace data
 | 
			
		|||
	IdentHash CreateRoutingKey (const IdentHash& ident);
 | 
			
		||||
	XORMetric operator^(const IdentHash& key1, const IdentHash& key2);
 | 
			
		||||
 | 
			
		||||
	// destination for delivery instuctions
 | 
			
		||||
	// destination for delivery instructions
 | 
			
		||||
	class RoutingDestination
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
| 
						 | 
				
			
			@ -235,5 +235,4 @@ namespace data
 | 
			
		|||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,6 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
namespace data
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	LeaseSet::LeaseSet (bool storeLeases):
 | 
			
		||||
		m_IsValid (false), m_StoreLeases (storeLeases), m_ExpirationTime (0), m_EncryptionKey (nullptr),
 | 
			
		||||
		m_Buffer (nullptr), m_BufferLen (0)
 | 
			
		||||
| 
						 | 
				
			
			@ -191,10 +190,10 @@ namespace data
 | 
			
		|||
		return	m_ExpirationTime - now <= dlt;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
 | 
			
		||||
  {
 | 
			
		||||
    return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold);
 | 
			
		||||
  }
 | 
			
		||||
	const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
 | 
			
		||||
	{
 | 
			
		||||
		return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -423,7 +422,7 @@ namespace data
 | 
			
		|||
			if (offset + 40 >= len) return 0;
 | 
			
		||||
			offset += 32; // hash
 | 
			
		||||
			offset += 3; // flags
 | 
			
		||||
 			offset += 1; // cost
 | 
			
		||||
			offset += 1; // cost
 | 
			
		||||
			offset += 4; // expires
 | 
			
		||||
		}
 | 
			
		||||
		// revocations
 | 
			
		||||
| 
						 | 
				
			
			@ -771,8 +770,7 @@ namespace data
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys,
 | 
			
		||||
		const KeySections& encryptionKeys, 
 | 
			
		||||
		std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels, 
 | 
			
		||||
		const KeySections& encryptionKeys, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels,
 | 
			
		||||
		bool isPublic, bool isPublishedEncrypted):
 | 
			
		||||
		LocalLeaseSet (keys.GetPublic (), nullptr, 0)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ namespace data
 | 
			
		|||
		};
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
  typedef std::function<bool(const Lease & l)> LeaseInspectFunc;
 | 
			
		||||
	typedef std::function<bool(const Lease & l)> LeaseInspectFunc;
 | 
			
		||||
 | 
			
		||||
	const size_t MAX_LS_BUFFER_SIZE = 3072;
 | 
			
		||||
	const size_t LEASE_SIZE = 44; // 32 + 4 + 8
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +70,7 @@ namespace data
 | 
			
		|||
			size_t GetBufferLen () const { return m_BufferLen; };
 | 
			
		||||
			bool IsValid () const { return m_IsValid; };
 | 
			
		||||
			const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeases (bool withThreshold = true) const;
 | 
			
		||||
      		const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true)  const;
 | 
			
		||||
			const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const;
 | 
			
		||||
			bool HasExpiredLeases () const;
 | 
			
		||||
			bool IsExpired () const;
 | 
			
		||||
			bool IsEmpty () const { return m_Leases.empty (); };
 | 
			
		||||
| 
						 | 
				
			
			@ -97,7 +97,7 @@ namespace data
 | 
			
		|||
			// called from LeaseSet2
 | 
			
		||||
			LeaseSet (bool storeLeases);
 | 
			
		||||
			void SetBuffer (const uint8_t * buf, size_t len);
 | 
			
		||||
		  	void SetBufferLen (size_t len);
 | 
			
		||||
			void SetBufferLen (size_t len);
 | 
			
		||||
			void SetIdentity (std::shared_ptr<const IdentityEx> identity) { m_Identity = identity; };
 | 
			
		||||
			void SetExpirationTime (uint64_t t) { m_ExpirationTime = t; };
 | 
			
		||||
			void SetIsValid (bool isValid) { m_IsValid = isValid; };
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +245,8 @@ namespace data
 | 
			
		|||
				const KeySections& encryptionKeys,
 | 
			
		||||
				std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels,
 | 
			
		||||
				bool isPublic, bool isPublishedEncrypted = false);
 | 
			
		||||
			LocalLeaseSet2 (uint8_t storeType, std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len);	// from I2CP
 | 
			
		||||
 | 
			
		||||
			LocalLeaseSet2 (uint8_t storeType, std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len); // from I2CP
 | 
			
		||||
 | 
			
		||||
			virtual ~LocalLeaseSet2 () { delete[] m_Buffer; };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,35 +29,35 @@ struct BigEndian;
 | 
			
		|||
template<typename T>
 | 
			
		||||
struct LittleEndian
 | 
			
		||||
{
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        unsigned char bytes[sizeof(T)];
 | 
			
		||||
        T raw_value;
 | 
			
		||||
    };
 | 
			
		||||
	union
 | 
			
		||||
	{
 | 
			
		||||
		unsigned char bytes[sizeof(T)];
 | 
			
		||||
		T raw_value;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
    LittleEndian(T t = T())
 | 
			
		||||
    {
 | 
			
		||||
        operator =(t);
 | 
			
		||||
    }
 | 
			
		||||
	LittleEndian(T t = T())
 | 
			
		||||
	{
 | 
			
		||||
		operator =(t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    LittleEndian(const LittleEndian<T> & t)
 | 
			
		||||
    {
 | 
			
		||||
        raw_value = t.raw_value;
 | 
			
		||||
    }
 | 
			
		||||
	LittleEndian(const LittleEndian<T> & t)
 | 
			
		||||
	{
 | 
			
		||||
		raw_value = t.raw_value;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    LittleEndian(const BigEndian<T> & t)
 | 
			
		||||
    {
 | 
			
		||||
        for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
            bytes[i] = t.bytes[sizeof(T)-1-i];
 | 
			
		||||
    }
 | 
			
		||||
	LittleEndian(const BigEndian<T> & t)
 | 
			
		||||
	{
 | 
			
		||||
		for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
			bytes[i] = t.bytes[sizeof(T)-1-i];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    operator const T() const
 | 
			
		||||
    {
 | 
			
		||||
        T t = T();
 | 
			
		||||
        for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
            t |= T(bytes[i]) << (i << 3);
 | 
			
		||||
        return t;
 | 
			
		||||
    }
 | 
			
		||||
	operator const T() const
 | 
			
		||||
	{
 | 
			
		||||
		T t = T();
 | 
			
		||||
		for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
			t |= T(bytes[i]) << (i << 3);
 | 
			
		||||
		return t;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const T operator = (const T t)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -66,68 +66,68 @@ struct LittleEndian
 | 
			
		|||
		return t;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    // operators
 | 
			
		||||
	// operators
 | 
			
		||||
 | 
			
		||||
    const T operator += (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this + t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator += (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this + t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    const T operator -= (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this - t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator -= (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this - t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    const T operator *= (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this * t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator *= (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this * t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    const T operator /= (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this / t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator /= (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this / t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    const T operator %= (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this % t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator %= (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this % t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    LittleEndian<T> operator ++ (int)
 | 
			
		||||
    {
 | 
			
		||||
        LittleEndian<T> tmp(*this);
 | 
			
		||||
        operator ++ ();
 | 
			
		||||
        return tmp;
 | 
			
		||||
    }
 | 
			
		||||
	LittleEndian<T> operator ++ (int)
 | 
			
		||||
	{
 | 
			
		||||
		LittleEndian<T> tmp(*this);
 | 
			
		||||
		operator ++ ();
 | 
			
		||||
		return tmp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    LittleEndian<T> & operator ++ ()
 | 
			
		||||
    {
 | 
			
		||||
        for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
        {
 | 
			
		||||
            ++bytes[i];
 | 
			
		||||
            if (bytes[i] != 0)
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return (*this);
 | 
			
		||||
    }
 | 
			
		||||
	LittleEndian<T> & operator ++ ()
 | 
			
		||||
	{
 | 
			
		||||
		for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
		{
 | 
			
		||||
			++bytes[i];
 | 
			
		||||
			if (bytes[i] != 0)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		return (*this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    LittleEndian<T> operator -- (int)
 | 
			
		||||
    {
 | 
			
		||||
        LittleEndian<T> tmp(*this);
 | 
			
		||||
        operator -- ();
 | 
			
		||||
        return tmp;
 | 
			
		||||
    }
 | 
			
		||||
	LittleEndian<T> operator -- (int)
 | 
			
		||||
	{
 | 
			
		||||
		LittleEndian<T> tmp(*this);
 | 
			
		||||
		operator -- ();
 | 
			
		||||
		return tmp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    LittleEndian<T> & operator -- ()
 | 
			
		||||
    {
 | 
			
		||||
        for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
        {
 | 
			
		||||
            --bytes[i];
 | 
			
		||||
            if (bytes[i] != (T)(-1))
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return (*this);
 | 
			
		||||
    }
 | 
			
		||||
	LittleEndian<T> & operator -- ()
 | 
			
		||||
	{
 | 
			
		||||
		for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
		{
 | 
			
		||||
			--bytes[i];
 | 
			
		||||
			if (bytes[i] != (T)(-1))
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		return (*this);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
#pragma pack(pop)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -137,105 +137,105 @@ struct LittleEndian
 | 
			
		|||
template<typename T>
 | 
			
		||||
struct BigEndian
 | 
			
		||||
{
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        unsigned char bytes[sizeof(T)];
 | 
			
		||||
        T raw_value;
 | 
			
		||||
    };
 | 
			
		||||
	union
 | 
			
		||||
	{
 | 
			
		||||
		unsigned char bytes[sizeof(T)];
 | 
			
		||||
		T raw_value;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
    BigEndian(T t = T())
 | 
			
		||||
    {
 | 
			
		||||
        operator =(t);
 | 
			
		||||
    }
 | 
			
		||||
	BigEndian(T t = T())
 | 
			
		||||
	{
 | 
			
		||||
		operator =(t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    BigEndian(const BigEndian<T> & t)
 | 
			
		||||
    {
 | 
			
		||||
        raw_value = t.raw_value;
 | 
			
		||||
    }
 | 
			
		||||
	BigEndian(const BigEndian<T> & t)
 | 
			
		||||
	{
 | 
			
		||||
		raw_value = t.raw_value;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    BigEndian(const LittleEndian<T> & t)
 | 
			
		||||
    {
 | 
			
		||||
        for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
            bytes[i] = t.bytes[sizeof(T)-1-i];
 | 
			
		||||
    }
 | 
			
		||||
	BigEndian(const LittleEndian<T> & t)
 | 
			
		||||
	{
 | 
			
		||||
		for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
			bytes[i] = t.bytes[sizeof(T)-1-i];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    operator const T() const
 | 
			
		||||
    {
 | 
			
		||||
        T t = T();
 | 
			
		||||
        for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
            t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3);
 | 
			
		||||
        return t;
 | 
			
		||||
    }
 | 
			
		||||
	operator const T() const
 | 
			
		||||
	{
 | 
			
		||||
		T t = T();
 | 
			
		||||
		for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
			t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3);
 | 
			
		||||
		return t;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    const T operator = (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
            bytes[sizeof(T) - 1 - i] = t >> (i << 3);
 | 
			
		||||
        return t;
 | 
			
		||||
    }
 | 
			
		||||
	const T operator = (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
			bytes[sizeof(T) - 1 - i] = t >> (i << 3);
 | 
			
		||||
		return t;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    // operators
 | 
			
		||||
	// operators
 | 
			
		||||
 | 
			
		||||
    const T operator += (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this + t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator += (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this + t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    const T operator -= (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this - t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator -= (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this - t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    const T operator *= (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this * t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator *= (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this * t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    const T operator /= (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this / t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator /= (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this / t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    const T operator %= (const T t)
 | 
			
		||||
    {
 | 
			
		||||
        return (*this = *this % t);
 | 
			
		||||
    }
 | 
			
		||||
	const T operator %= (const T t)
 | 
			
		||||
	{
 | 
			
		||||
		return (*this = *this % t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    BigEndian<T> operator ++ (int)
 | 
			
		||||
    {
 | 
			
		||||
        BigEndian<T> tmp(*this);
 | 
			
		||||
        operator ++ ();
 | 
			
		||||
        return tmp;
 | 
			
		||||
    }
 | 
			
		||||
	BigEndian<T> operator ++ (int)
 | 
			
		||||
	{
 | 
			
		||||
		BigEndian<T> tmp(*this);
 | 
			
		||||
		operator ++ ();
 | 
			
		||||
		return tmp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    BigEndian<T> & operator ++ ()
 | 
			
		||||
    {
 | 
			
		||||
        for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
        {
 | 
			
		||||
            ++bytes[sizeof(T) - 1 - i];
 | 
			
		||||
            if (bytes[sizeof(T) - 1 - i] != 0)
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return (*this);
 | 
			
		||||
    }
 | 
			
		||||
	BigEndian<T> & operator ++ ()
 | 
			
		||||
	{
 | 
			
		||||
		for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
		{
 | 
			
		||||
			++bytes[sizeof(T) - 1 - i];
 | 
			
		||||
			if (bytes[sizeof(T) - 1 - i] != 0)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		return (*this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    BigEndian<T> operator -- (int)
 | 
			
		||||
    {
 | 
			
		||||
        BigEndian<T> tmp(*this);
 | 
			
		||||
        operator -- ();
 | 
			
		||||
        return tmp;
 | 
			
		||||
    }
 | 
			
		||||
	BigEndian<T> operator -- (int)
 | 
			
		||||
	{
 | 
			
		||||
		BigEndian<T> tmp(*this);
 | 
			
		||||
		operator -- ();
 | 
			
		||||
		return tmp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    BigEndian<T> & operator -- ()
 | 
			
		||||
    {
 | 
			
		||||
        for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
        {
 | 
			
		||||
            --bytes[sizeof(T) - 1 - i];
 | 
			
		||||
            if (bytes[sizeof(T) - 1 - i] != (T)(-1))
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return (*this);
 | 
			
		||||
    }
 | 
			
		||||
	BigEndian<T> & operator -- ()
 | 
			
		||||
	{
 | 
			
		||||
		for (unsigned i = 0; i < sizeof(T); i++)
 | 
			
		||||
		{
 | 
			
		||||
			--bytes[sizeof(T) - 1 - i];
 | 
			
		||||
			if (bytes[sizeof(T) - 1 - i] != (T)(-1))
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		return (*this);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
#pragma pack(pop)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,18 +110,18 @@ namespace log {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::string str_tolower(std::string s) {
 | 
			
		||||
        std::transform(s.begin(), s.end(), s.begin(),
 | 
			
		||||
                    // static_cast<int(*)(int)>(std::tolower)         // wrong
 | 
			
		||||
                    // [](int c){ return std::tolower(c); }           // wrong
 | 
			
		||||
                    // [](char c){ return std::tolower(c); }          // wrong
 | 
			
		||||
                       [](unsigned char c){ return std::tolower(c); } // correct
 | 
			
		||||
                      );
 | 
			
		||||
        return s;
 | 
			
		||||
    }
 | 
			
		||||
	std::string str_tolower(std::string s) {
 | 
			
		||||
		std::transform(s.begin(), s.end(), s.begin(),
 | 
			
		||||
					// static_cast<int(*)(int)>(std::tolower)         // wrong
 | 
			
		||||
					// [](int c){ return std::tolower(c); }           // wrong
 | 
			
		||||
					// [](char c){ return std::tolower(c); }          // wrong
 | 
			
		||||
					   [](unsigned char c){ return std::tolower(c); } // correct
 | 
			
		||||
					);
 | 
			
		||||
		return s;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    void Log::SetLogLevel (const std::string& level_) {
 | 
			
		||||
        std::string level=str_tolower(level_);
 | 
			
		||||
	void Log::SetLogLevel (const std::string& level_) {
 | 
			
		||||
		std::string level=str_tolower(level_);
 | 
			
		||||
		if      (level == "none")  { m_MinLevel = eLogNone; }
 | 
			
		||||
		else if (level == "error") { m_MinLevel = eLogError; }
 | 
			
		||||
		else if (level == "warn")  { m_MinLevel = eLogWarning; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,7 +157,7 @@ namespace log {
 | 
			
		|||
	ThrowFunction GetThrowFunction ();
 | 
			
		||||
	void SetThrowFunction (ThrowFunction f);
 | 
			
		||||
} // log
 | 
			
		||||
}
 | 
			
		||||
} // i2p
 | 
			
		||||
 | 
			
		||||
/** internal usage only -- folding args array to single string */
 | 
			
		||||
template<typename TValue>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ namespace transport
 | 
			
		|||
 | 
			
		||||
	void NTCP2Establisher::KDF2Bob ()
 | 
			
		||||
	{
 | 
			
		||||
		 KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ());
 | 
			
		||||
		KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void NTCP2Establisher::KDF3Alice ()
 | 
			
		||||
| 
						 | 
				
			
			@ -1200,7 +1200,7 @@ namespace transport
 | 
			
		|||
								continue;
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port);
 | 
			
		||||
							LogPrint (eLogInfo, "NTCP2: Start listening v4 TCP port ", address->port);
 | 
			
		||||
							auto conn = std::make_shared<NTCP2Session>(*this);
 | 
			
		||||
							m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1));
 | 
			
		||||
						}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -126,7 +126,6 @@ namespace transport
 | 
			
		|||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
 | 
			
		||||
			~NTCP2Session ();
 | 
			
		||||
			void Terminate ();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -468,7 +468,7 @@ namespace transport
 | 
			
		|||
			LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock");
 | 
			
		||||
			if (ecode != boost::asio::error::operation_aborted)
 | 
			
		||||
			{
 | 
			
		||||
				 // this router doesn't like us
 | 
			
		||||
				// this router doesn't like us
 | 
			
		||||
				i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true);
 | 
			
		||||
				Terminate ();
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -736,13 +736,11 @@ namespace transport
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	void NTCPSession::SendTimeSyncMessage ()
 | 
			
		||||
	{
 | 
			
		||||
		Send (nullptr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	void NTCPSession::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
 | 
			
		||||
	{
 | 
			
		||||
		m_Server.GetService ().post (std::bind (&NTCPSession::PostI2NPMessages, shared_from_this (), msgs));
 | 
			
		||||
| 
						 | 
				
			
			@ -904,7 +902,6 @@ namespace transport
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	void NTCPServer::Run ()
 | 
			
		||||
	{
 | 
			
		||||
		while (m_IsRunning)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -390,7 +390,7 @@ namespace data
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
                m_Reseeder->Bootstrap ();
 | 
			
		||||
		m_Reseeder->Bootstrap ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
 | 
			
		||||
| 
						 | 
				
			
			@ -537,7 +537,7 @@ namespace data
 | 
			
		|||
		bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes
 | 
			
		||||
		if (checkForExpiration && uptime > 3600) // 1 hour
 | 
			
		||||
			expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL :
 | 
			
		||||
					NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
 | 
			
		||||
				NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
 | 
			
		||||
 | 
			
		||||
		for (auto& it: m_RouterInfos)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -555,7 +555,7 @@ namespace data
 | 
			
		|||
			// find & mark expired routers
 | 
			
		||||
			if (it.second->UsesIntroducer ())
 | 
			
		||||
			{
 | 
			
		||||
				 if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL)
 | 
			
		||||
				if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL)
 | 
			
		||||
				// RouterInfo expires after 1 hour if uses introducer
 | 
			
		||||
					it.second->SetUnreachable (true);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -873,7 +873,7 @@ namespace data
 | 
			
		|||
		std::shared_ptr<I2NPMessage> replyMsg;
 | 
			
		||||
		if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogInfo, "NetDb: exploratory close to  ", key, " ", numExcluded, " excluded");
 | 
			
		||||
			LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded");
 | 
			
		||||
			std::set<IdentHash> excludedRouters;
 | 
			
		||||
			for (int i = 0; i < numExcluded; i++)
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -894,7 +894,7 @@ namespace data
 | 
			
		|||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP  ||
 | 
			
		||||
			if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
 | 
			
		||||
			    lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
 | 
			
		||||
			{
 | 
			
		||||
				auto router = FindRouter (ident);
 | 
			
		||||
| 
						 | 
				
			
			@ -907,7 +907,7 @@ namespace data
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP  ||
 | 
			
		||||
			if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP ||
 | 
			
		||||
				lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP))
 | 
			
		||||
			{
 | 
			
		||||
				auto leaseSet = FindLeaseSet (ident);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,12 +28,12 @@ namespace i2p
 | 
			
		|||
namespace data
 | 
			
		||||
{
 | 
			
		||||
	const int NETDB_MIN_ROUTERS = 90;
 | 
			
		||||
	const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds
 | 
			
		||||
	const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60;
 | 
			
		||||
	const int NETDB_MIN_EXPIRATION_TIMEOUT = 90*60; // 1.5 hours
 | 
			
		||||
	const int NETDB_MAX_EXPIRATION_TIMEOUT = 27*60*60; // 27 hours
 | 
			
		||||
	const int NETDB_PUBLISH_INTERVAL = 60*40;
 | 
			
		||||
	const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0,9,36); // 0.9.36
 | 
			
		||||
	const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds
 | 
			
		||||
	const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60;
 | 
			
		||||
	const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
 | 
			
		||||
	const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
 | 
			
		||||
	const int NETDB_PUBLISH_INTERVAL = 60 * 40;
 | 
			
		||||
	const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 36); // 0.9.36
 | 
			
		||||
 | 
			
		||||
	/** function for visiting a leaseset stored in a floodfill */
 | 
			
		||||
	typedef std::function<void(const IdentHash, std::shared_ptr<LeaseSet>)> LeaseSetVisitor;
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ namespace data
 | 
			
		|||
			std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
 | 
			
		||||
 | 
			
		||||
			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 HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
			
		||||
| 
						 | 
				
			
			@ -80,13 +80,13 @@ namespace data
 | 
			
		|||
			std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
 | 
			
		||||
				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> 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 PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
 | 
			
		||||
 | 
			
		||||
      /** set hidden mode, aka don't publish our RI to netdb and don't explore */
 | 
			
		||||
      void SetHidden(bool hide);
 | 
			
		||||
			/** set hidden mode, aka don't publish our RI to netdb and don't explore */
 | 
			
		||||
			void SetHidden(bool hide);
 | 
			
		||||
 | 
			
		||||
			void Reseed ();
 | 
			
		||||
			Families& GetFamilies () { return m_Families; };
 | 
			
		||||
| 
						 | 
				
			
			@ -119,12 +119,13 @@ namespace data
 | 
			
		|||
			void ManageLeaseSets ();
 | 
			
		||||
			void ManageRequests ();
 | 
			
		||||
 | 
			
		||||
			void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20);
 | 
			
		||||
			void ReseedFromFloodfill(const RouterInfo & ri, int numRouters = 40, int numFloodfills = 20);
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<const RouterInfo> AddRouterInfo (const uint8_t * buf, int len, bool& updated);
 | 
			
		||||
			std::shared_ptr<const RouterInfo> AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated);
 | 
			
		||||
    		template<typename Filter>
 | 
			
		||||
        	std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
 | 
			
		||||
 | 
			
		||||
			template<typename Filter>
 | 
			
		||||
			std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -150,12 +151,12 @@ namespace data
 | 
			
		|||
 | 
			
		||||
			bool m_PersistProfiles;
 | 
			
		||||
 | 
			
		||||
		/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
 | 
			
		||||
		std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
 | 
			
		||||
			/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
 | 
			
		||||
			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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,8 +14,8 @@ namespace data
 | 
			
		|||
		std::shared_ptr<I2NPMessage> msg;
 | 
			
		||||
		if(replyTunnel)
 | 
			
		||||
			msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
 | 
			
		||||
			replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory,
 | 
			
		||||
		    &m_ExcludedPeers);
 | 
			
		||||
				replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory,
 | 
			
		||||
				&m_ExcludedPeers);
 | 
			
		||||
		else
 | 
			
		||||
			msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers);
 | 
			
		||||
		if(router)
 | 
			
		||||
| 
						 | 
				
			
			@ -158,4 +158,3 @@ namespace data
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,4 +66,3 @@ namespace data
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,6 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
namespace crypto
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz)
 | 
			
		||||
	{
 | 
			
		||||
		Poly1305 p(key);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
/**
 | 
			
		||||
   This code is licensed under the MCGSI Public License
 | 
			
		||||
   Copyright 2018 Jeff Becker
 | 
			
		||||
 | 
			
		||||
   Kovri go write your own code
 | 
			
		||||
 | 
			
		||||
 * This code is licensed under the MCGSI Public License
 | 
			
		||||
 * Copyright 2018 Jeff Becker
 | 
			
		||||
 *
 | 
			
		||||
 * Kovri go write your own code
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef LIBI2PD_POLY1305_H
 | 
			
		||||
#define LIBI2PD_POLY1305_H
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +24,6 @@ namespace crypto
 | 
			
		|||
 | 
			
		||||
	namespace poly1305
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
		struct LongBlock
 | 
			
		||||
		{
 | 
			
		||||
			unsigned long data[17];
 | 
			
		||||
| 
						 | 
				
			
			@ -252,8 +251,8 @@ namespace crypto
 | 
			
		|||
		poly1305::LongBlock m_HR;
 | 
			
		||||
		uint8_t m_Final;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,73 +32,76 @@ namespace data
 | 
			
		|||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        /** @brief tries to bootstrap into I2P network (from local files and servers, with respect of options)
 | 
			
		||||
         */
 | 
			
		||||
        void Reseeder::Bootstrap ()
 | 
			
		||||
        {
 | 
			
		||||
            std::string su3FileName; i2p::config::GetOption("reseed.file", su3FileName);
 | 
			
		||||
            std::string zipFileName; i2p::config::GetOption("reseed.zipfile", zipFileName);
 | 
			
		||||
	/**
 | 
			
		||||
	 @brief tries to bootstrap into I2P network (from local files and servers, with respect of options)
 | 
			
		||||
	 */
 | 
			
		||||
	void Reseeder::Bootstrap ()
 | 
			
		||||
	{
 | 
			
		||||
		std::string su3FileName; i2p::config::GetOption("reseed.file", su3FileName);
 | 
			
		||||
		std::string zipFileName; i2p::config::GetOption("reseed.zipfile", zipFileName);
 | 
			
		||||
 | 
			
		||||
            if (su3FileName.length() > 0) // bootstrap from SU3 file or URL
 | 
			
		||||
            {
 | 
			
		||||
                int num;
 | 
			
		||||
                if (su3FileName.length() > 8 && su3FileName.substr(0, 8) == "https://")
 | 
			
		||||
                {
 | 
			
		||||
                    num = ReseedFromSU3Url (su3FileName); // from https URL
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    num = ProcessSU3File (su3FileName.c_str ());
 | 
			
		||||
                }
 | 
			
		||||
                if (num == 0)
 | 
			
		||||
                    LogPrint (eLogWarning, "Reseed: failed to reseed from ", su3FileName);
 | 
			
		||||
            }
 | 
			
		||||
            else if (zipFileName.length() > 0) // bootstrap from ZIP file
 | 
			
		||||
            {
 | 
			
		||||
                int num = ProcessZIPFile (zipFileName.c_str ());
 | 
			
		||||
                if (num == 0)
 | 
			
		||||
                    LogPrint (eLogWarning, "Reseed: failed to reseed from ", zipFileName);
 | 
			
		||||
            }
 | 
			
		||||
            else // bootstrap from reseed servers
 | 
			
		||||
            {
 | 
			
		||||
                int num = ReseedFromServers ();
 | 
			
		||||
                if (num == 0)
 | 
			
		||||
                    LogPrint (eLogWarning, "Reseed: failed to reseed from servers");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
		if (su3FileName.length() > 0) // bootstrap from SU3 file or URL
 | 
			
		||||
		{
 | 
			
		||||
			int num;
 | 
			
		||||
			if (su3FileName.length() > 8 && su3FileName.substr(0, 8) == "https://")
 | 
			
		||||
			{
 | 
			
		||||
				num = ReseedFromSU3Url (su3FileName); // from https URL
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				num = ProcessSU3File (su3FileName.c_str ());
 | 
			
		||||
			}
 | 
			
		||||
			if (num == 0)
 | 
			
		||||
				LogPrint (eLogWarning, "Reseed: failed to reseed from ", su3FileName);
 | 
			
		||||
		}
 | 
			
		||||
		else if (zipFileName.length() > 0) // bootstrap from ZIP file
 | 
			
		||||
		{
 | 
			
		||||
			int num = ProcessZIPFile (zipFileName.c_str ());
 | 
			
		||||
			if (num == 0)
 | 
			
		||||
				LogPrint (eLogWarning, "Reseed: failed to reseed from ", zipFileName);
 | 
			
		||||
		}
 | 
			
		||||
		else // bootstrap from reseed servers
 | 
			
		||||
		{
 | 
			
		||||
			int num = ReseedFromServers ();
 | 
			
		||||
			if (num == 0)
 | 
			
		||||
				LogPrint (eLogWarning, "Reseed: failed to reseed from servers");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        /** @brief bootstrap from random server, retry 10 times
 | 
			
		||||
         *  @return number of entries added to netDb
 | 
			
		||||
         */
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief bootstrap from random server, retry 10 times
 | 
			
		||||
	 * @return number of entries added to netDb
 | 
			
		||||
	 */
 | 
			
		||||
	int Reseeder::ReseedFromServers ()
 | 
			
		||||
	{
 | 
			
		||||
		std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs);
 | 
			
		||||
                std::vector<std::string> httpsReseedHostList;
 | 
			
		||||
                boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on);
 | 
			
		||||
		std::vector<std::string> httpsReseedHostList;
 | 
			
		||||
		boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on);
 | 
			
		||||
 | 
			
		||||
                if (reseedURLs.length () == 0)
 | 
			
		||||
                {
 | 
			
		||||
                    LogPrint (eLogWarning, "Reseed: No reseed servers specified");
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
		if (reseedURLs.length () == 0)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Reseed: No reseed servers specified");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
                int reseedRetries = 0;
 | 
			
		||||
                while (reseedRetries < 10)
 | 
			
		||||
                {
 | 
			
		||||
                    auto ind = rand () % httpsReseedHostList.size ();
 | 
			
		||||
                    std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3";
 | 
			
		||||
                    auto num = ReseedFromSU3Url (reseedUrl);
 | 
			
		||||
                    if (num > 0) return num; // success
 | 
			
		||||
                    reseedRetries++;
 | 
			
		||||
                }
 | 
			
		||||
                LogPrint (eLogWarning, "Reseed: failed to reseed from servers after 10 attempts");
 | 
			
		||||
                return 0;
 | 
			
		||||
		int reseedRetries = 0;
 | 
			
		||||
		while (reseedRetries < 10)
 | 
			
		||||
		{
 | 
			
		||||
			auto ind = rand () % httpsReseedHostList.size ();
 | 
			
		||||
			std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3";
 | 
			
		||||
			auto num = ReseedFromSU3Url (reseedUrl);
 | 
			
		||||
			if (num > 0) return num; // success
 | 
			
		||||
			reseedRetries++;
 | 
			
		||||
		}
 | 
			
		||||
		LogPrint (eLogWarning, "Reseed: failed to reseed from servers after 10 attempts");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        /** @brief bootstrap from HTTPS URL with SU3 file
 | 
			
		||||
         *  @param url
 | 
			
		||||
         *  @return number of entries added to netDb
 | 
			
		||||
         */
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief bootstrap from HTTPS URL with SU3 file
 | 
			
		||||
	 * @param url
 | 
			
		||||
	 * @return number of entries added to netDb
 | 
			
		||||
	 */
 | 
			
		||||
	int Reseeder::ReseedFromSU3Url (const std::string& url)
 | 
			
		||||
	{
 | 
			
		||||
		LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url);
 | 
			
		||||
| 
						 | 
				
			
			@ -702,4 +705,3 @@ namespace data
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ namespace data
 | 
			
		|||
 | 
			
		||||
			Reseeder();
 | 
			
		||||
			~Reseeder();
 | 
			
		||||
                        void Bootstrap ();
 | 
			
		||||
			void Bootstrap ();
 | 
			
		||||
			int ReseedFromServers ();
 | 
			
		||||
			int ReseedFromSU3Url (const std::string& url);
 | 
			
		||||
			int ProcessSU3File (const char * filename);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -339,9 +339,9 @@ namespace i2p
 | 
			
		|||
			case low   : /* not set */; break;
 | 
			
		||||
			case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P'
 | 
			
		||||
			case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth;
 | 
			
		||||
	#if (__cplusplus >= 201703L) // C++ 17 or higher		
 | 
			
		||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
 | 
			
		||||
			[[fallthrough]];
 | 
			
		||||
	#endif		
 | 
			
		||||
#endif
 | 
			
		||||
			//  no break here, extra + high means 'X'
 | 
			
		||||
			case high  : caps |= i2p::data::RouterInfo::eHighBandwidth;  break;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -173,7 +173,6 @@ namespace data
 | 
			
		|||
			LogPrint (eLogError, "RouterInfo: malformed message");
 | 
			
		||||
			m_IsUnreachable = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void RouterInfo::ReadFromStream (std::istream& s)
 | 
			
		||||
| 
						 | 
				
			
			@ -384,9 +383,10 @@ namespace data
 | 
			
		|||
			SetUnreachable (true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  bool RouterInfo::IsFamily(const std::string & fam) const {
 | 
			
		||||
    return m_Family == fam;
 | 
			
		||||
  }
 | 
			
		||||
	bool RouterInfo::IsFamily(const std::string & fam) const
 | 
			
		||||
	{
 | 
			
		||||
		return m_Family == fam;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void RouterInfo::ExtractCaps (const char * value)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -854,7 +854,7 @@ namespace data
 | 
			
		|||
			m_SupportedTransports |= eNTCPV6 | eSSUV6 | eNTCP2V6;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  void RouterInfo::EnableV4 ()
 | 
			
		||||
	void RouterInfo::EnableV4 ()
 | 
			
		||||
	{
 | 
			
		||||
		if (!IsV4 ())
 | 
			
		||||
			m_SupportedTransports |= eNTCPV4 | eSSUV4 | eNTCP2V4;
 | 
			
		||||
| 
						 | 
				
			
			@ -877,7 +877,7 @@ namespace data
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  void RouterInfo::DisableV4 ()
 | 
			
		||||
	void RouterInfo::DisableV4 ()
 | 
			
		||||
	{
 | 
			
		||||
		if (IsV4 ())
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -203,8 +203,8 @@ namespace data
 | 
			
		|||
			void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; };
 | 
			
		||||
			bool IsNewer (const uint8_t * buf, size_t len) const;
 | 
			
		||||
 | 
			
		||||
		/** return true if we are in a router family and the signature is valid */
 | 
			
		||||
		bool IsFamily(const std::string & fam) const;
 | 
			
		||||
			/** return true if we are in a router family and the signature is valid */
 | 
			
		||||
			bool IsFamily(const std::string & fam) const;
 | 
			
		||||
 | 
			
		||||
			// implements RoutingDestination
 | 
			
		||||
			std::shared_ptr<const IdentityEx> GetIdentity () const { return m_RouterIdentity; };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -826,4 +826,3 @@ namespace transport
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ namespace transport
 | 
			
		|||
		public:
 | 
			
		||||
 | 
			
		||||
			SSUServer (int port);
 | 
			
		||||
			SSUServer (const boost::asio::ip::address & addr, int port);			// ipv6 only constructor
 | 
			
		||||
			SSUServer (const boost::asio::ip::address & addr, int port); // ipv6 only constructor
 | 
			
		||||
			~SSUServer ();
 | 
			
		||||
			void Start ();
 | 
			
		||||
			void Stop ();
 | 
			
		||||
| 
						 | 
				
			
			@ -135,4 +135,3 @@ namespace transport
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -496,7 +496,7 @@ namespace transport
 | 
			
		|||
			}
 | 
			
		||||
			// decay
 | 
			
		||||
			if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES ||
 | 
			
		||||
			    i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL)
 | 
			
		||||
				i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL)
 | 
			
		||||
				m_ReceivedMessages.clear ();
 | 
			
		||||
 | 
			
		||||
			ScheduleIncompleteMessagesCleanup ();
 | 
			
		||||
| 
						 | 
				
			
			@ -504,4 +504,3 @@ namespace transport
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,4 +128,3 @@ namespace transport
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -336,7 +336,7 @@ namespace transport
 | 
			
		|||
			m_SignedData->Insert (payload, 4); // insert Alice's signed on time
 | 
			
		||||
		payload += 4; // signed-on time
 | 
			
		||||
		size_t paddingSize = (payload - buf) + m_RemoteIdentity->GetSignatureLen ();
 | 
			
		||||
		paddingSize &= 0x0F;  // %16
 | 
			
		||||
		paddingSize &= 0x0F; // %16
 | 
			
		||||
		if (paddingSize > 0) paddingSize = 16 - paddingSize;
 | 
			
		||||
		payload += paddingSize;
 | 
			
		||||
		// verify signature
 | 
			
		||||
| 
						 | 
				
			
			@ -1206,4 +1206,3 @@ namespace transport
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,7 +86,7 @@ namespace transport
 | 
			
		|||
			void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
 | 
			
		||||
			void SendPeerTest (); // Alice
 | 
			
		||||
 | 
			
		||||
			SessionState GetState () const  { return m_State; };
 | 
			
		||||
			SessionState GetState () const { return m_State; };
 | 
			
		||||
			size_t GetNumSentBytes () const { return m_NumSentBytes; };
 | 
			
		||||
			size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -158,10 +158,7 @@ namespace transport
 | 
			
		|||
			std::unique_ptr<SignedData> m_SignedData; // we need it for SessionConfirmed only
 | 
			
		||||
			std::map<uint32_t, std::shared_ptr<const i2p::data::RouterInfo> > m_RelayRequests; // nonce->Charlie
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -135,5 +135,3 @@ namespace crypto
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -527,4 +527,3 @@ namespace crypto
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
/**
 | 
			
		||||
   This code is licensed under the MCGSI Public License
 | 
			
		||||
   Copyright 2018 Jeff Becker
 | 
			
		||||
 | 
			
		||||
   Kovri go write your own code
 | 
			
		||||
 | 
			
		||||
 * This code is licensed under the MCGSI Public License
 | 
			
		||||
 * Copyright 2018 Jeff Becker
 | 
			
		||||
 *
 | 
			
		||||
 * Kovri go write your own code
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef SIPHASH_H
 | 
			
		||||
#define SIPHASH_H
 | 
			
		||||
| 
						 | 
				
			
			@ -16,138 +16,138 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
namespace crypto
 | 
			
		||||
{
 | 
			
		||||
    namespace siphash
 | 
			
		||||
    {
 | 
			
		||||
        constexpr int crounds = 2;
 | 
			
		||||
        constexpr int drounds = 4;
 | 
			
		||||
	namespace siphash
 | 
			
		||||
	{
 | 
			
		||||
		constexpr int crounds = 2;
 | 
			
		||||
		constexpr int drounds = 4;
 | 
			
		||||
 | 
			
		||||
        inline uint64_t rotl(const uint64_t & x, int b)
 | 
			
		||||
        {
 | 
			
		||||
            uint64_t ret = x << b;
 | 
			
		||||
            ret |= x >> (64 - b);
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
		inline uint64_t rotl(const uint64_t & x, int b)
 | 
			
		||||
		{
 | 
			
		||||
			uint64_t ret = x << b;
 | 
			
		||||
			ret |= x >> (64 - b);
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        inline void u32to8le(const uint32_t & v, uint8_t * p)
 | 
			
		||||
        {
 | 
			
		||||
            p[0] = (uint8_t) v;
 | 
			
		||||
            p[1] = (uint8_t) (v >> 8);
 | 
			
		||||
            p[2] = (uint8_t) (v >> 16);
 | 
			
		||||
            p[3] = (uint8_t) (v >> 24);
 | 
			
		||||
        }
 | 
			
		||||
		inline void u32to8le(const uint32_t & v, uint8_t * p)
 | 
			
		||||
		{
 | 
			
		||||
			p[0] = (uint8_t) v;
 | 
			
		||||
			p[1] = (uint8_t) (v >> 8);
 | 
			
		||||
			p[2] = (uint8_t) (v >> 16);
 | 
			
		||||
			p[3] = (uint8_t) (v >> 24);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        inline void u64to8le(const uint64_t & v, uint8_t * p)
 | 
			
		||||
        {
 | 
			
		||||
            p[0] = v & 0xff;
 | 
			
		||||
            p[1] = (v >> 8)  & 0xff;
 | 
			
		||||
            p[2] = (v >> 16) & 0xff;
 | 
			
		||||
            p[3] = (v >> 24) & 0xff;
 | 
			
		||||
            p[4] = (v >> 32) & 0xff;
 | 
			
		||||
            p[5] = (v >> 40) & 0xff;
 | 
			
		||||
            p[6] = (v >> 48) & 0xff;
 | 
			
		||||
            p[7] = (v >> 56) & 0xff;
 | 
			
		||||
        }
 | 
			
		||||
		inline void u64to8le(const uint64_t & v, uint8_t * p)
 | 
			
		||||
		{
 | 
			
		||||
			p[0] = v & 0xff;
 | 
			
		||||
			p[1] = (v >> 8)  & 0xff;
 | 
			
		||||
			p[2] = (v >> 16) & 0xff;
 | 
			
		||||
			p[3] = (v >> 24) & 0xff;
 | 
			
		||||
			p[4] = (v >> 32) & 0xff;
 | 
			
		||||
			p[5] = (v >> 40) & 0xff;
 | 
			
		||||
			p[6] = (v >> 48) & 0xff;
 | 
			
		||||
			p[7] = (v >> 56) & 0xff;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        inline uint64_t u8to64le(const uint8_t * p)
 | 
			
		||||
        {
 | 
			
		||||
            uint64_t i = 0;
 | 
			
		||||
            int idx = 0;
 | 
			
		||||
            while(idx < 8)
 | 
			
		||||
            {
 | 
			
		||||
                i |= ((uint64_t) p[idx]) << (idx * 8);
 | 
			
		||||
                ++idx;
 | 
			
		||||
            }
 | 
			
		||||
            return i;
 | 
			
		||||
        }
 | 
			
		||||
		inline uint64_t u8to64le(const uint8_t * p)
 | 
			
		||||
		{
 | 
			
		||||
			uint64_t i = 0;
 | 
			
		||||
			int idx = 0;
 | 
			
		||||
			while(idx < 8)
 | 
			
		||||
			{
 | 
			
		||||
				i |= ((uint64_t) p[idx]) << (idx * 8);
 | 
			
		||||
				++idx;
 | 
			
		||||
			}
 | 
			
		||||
			return i;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        inline void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3)
 | 
			
		||||
        {
 | 
			
		||||
            _v0 += _v1; 
 | 
			
		||||
            _v1 = rotl(_v1, 13); 
 | 
			
		||||
            _v1 ^= _v0;  
 | 
			
		||||
            _v0 = rotl(_v0, 32); 
 | 
			
		||||
            _v2 += _v3;  
 | 
			
		||||
            _v3 = rotl(_v3, 16);  
 | 
			
		||||
            _v3 ^= _v2;         
 | 
			
		||||
            _v0 += _v3;                                                              
 | 
			
		||||
            _v3 = rotl(_v3, 21);                                                     
 | 
			
		||||
            _v3 ^= _v0;                                                              
 | 
			
		||||
            _v2 += _v1;                                                              
 | 
			
		||||
            _v1 = rotl(_v1, 17);                                                     
 | 
			
		||||
            _v1 ^= _v2;                                                              
 | 
			
		||||
            _v2 = rotl(_v2, 32); 
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
		inline void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3)
 | 
			
		||||
		{
 | 
			
		||||
			_v0 += _v1;
 | 
			
		||||
			_v1 = rotl(_v1, 13);
 | 
			
		||||
			_v1 ^= _v0;
 | 
			
		||||
			_v0 = rotl(_v0, 32);
 | 
			
		||||
			_v2 += _v3;
 | 
			
		||||
			_v3 = rotl(_v3, 16);
 | 
			
		||||
			_v3 ^= _v2;
 | 
			
		||||
			_v0 += _v3;
 | 
			
		||||
			_v3 = rotl(_v3, 21);
 | 
			
		||||
			_v3 ^= _v0;
 | 
			
		||||
			_v2 += _v1;
 | 
			
		||||
			_v1 = rotl(_v1, 17);
 | 
			
		||||
			_v1 ^= _v2;
 | 
			
		||||
			_v2 = rotl(_v2, 32);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    /** hashsz must be 8 or 16 */
 | 
			
		||||
    template<std::size_t hashsz>
 | 
			
		||||
    inline void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key)
 | 
			
		||||
    {
 | 
			
		||||
        uint64_t v0 = 0x736f6d6570736575ULL;
 | 
			
		||||
        uint64_t v1 = 0x646f72616e646f6dULL;
 | 
			
		||||
        uint64_t v2 = 0x6c7967656e657261ULL;
 | 
			
		||||
        uint64_t v3 = 0x7465646279746573ULL;
 | 
			
		||||
        const uint64_t k0 = siphash::u8to64le(key);
 | 
			
		||||
        const uint64_t k1 = siphash::u8to64le(key + 8);
 | 
			
		||||
        uint64_t msg;
 | 
			
		||||
        int i;
 | 
			
		||||
        const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t));
 | 
			
		||||
        auto left = bufsz & 7;
 | 
			
		||||
        uint64_t b = ((uint64_t)bufsz) << 56;
 | 
			
		||||
        v3 ^= k1;
 | 
			
		||||
        v2 ^= k0;
 | 
			
		||||
        v1 ^= k1;
 | 
			
		||||
        v0 ^= k0;
 | 
			
		||||
	/** hashsz must be 8 or 16 */
 | 
			
		||||
	template<std::size_t hashsz>
 | 
			
		||||
	inline void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key)
 | 
			
		||||
	{
 | 
			
		||||
		uint64_t v0 = 0x736f6d6570736575ULL;
 | 
			
		||||
		uint64_t v1 = 0x646f72616e646f6dULL;
 | 
			
		||||
		uint64_t v2 = 0x6c7967656e657261ULL;
 | 
			
		||||
		uint64_t v3 = 0x7465646279746573ULL;
 | 
			
		||||
		const uint64_t k0 = siphash::u8to64le(key);
 | 
			
		||||
		const uint64_t k1 = siphash::u8to64le(key + 8);
 | 
			
		||||
		uint64_t msg;
 | 
			
		||||
		int i;
 | 
			
		||||
		const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t));
 | 
			
		||||
		auto left = bufsz & 7;
 | 
			
		||||
		uint64_t b = ((uint64_t)bufsz) << 56;
 | 
			
		||||
		v3 ^= k1;
 | 
			
		||||
		v2 ^= k0;
 | 
			
		||||
		v1 ^= k1;
 | 
			
		||||
		v0 ^= k0;
 | 
			
		||||
 | 
			
		||||
        if(hashsz == 16) v1 ^= 0xee;
 | 
			
		||||
		if(hashsz == 16) v1 ^= 0xee;
 | 
			
		||||
 | 
			
		||||
        while(buf != end)
 | 
			
		||||
        {
 | 
			
		||||
            msg = siphash::u8to64le(buf);
 | 
			
		||||
            v3 ^= msg;
 | 
			
		||||
            for(i = 0; i < siphash::crounds; ++i)
 | 
			
		||||
                siphash::round(v0, v1, v2, v3);
 | 
			
		||||
		while(buf != end)
 | 
			
		||||
		{
 | 
			
		||||
			msg = siphash::u8to64le(buf);
 | 
			
		||||
			v3 ^= msg;
 | 
			
		||||
			for(i = 0; i < siphash::crounds; ++i)
 | 
			
		||||
				siphash::round(v0, v1, v2, v3);
 | 
			
		||||
 | 
			
		||||
            v0 ^= msg;
 | 
			
		||||
            buf += 8;
 | 
			
		||||
        }
 | 
			
		||||
			v0 ^= msg;
 | 
			
		||||
			buf += 8;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        while(left)
 | 
			
		||||
        {
 | 
			
		||||
            --left;
 | 
			
		||||
            b |= ((uint64_t)(buf[left])) << (left  * 8);
 | 
			
		||||
        }
 | 
			
		||||
		while(left)
 | 
			
		||||
		{
 | 
			
		||||
			--left;
 | 
			
		||||
			b |= ((uint64_t)(buf[left])) << (left * 8);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        v3 ^= b;
 | 
			
		||||
		v3 ^= b;
 | 
			
		||||
 | 
			
		||||
        for(i = 0; i < siphash::crounds; ++i)
 | 
			
		||||
            siphash::round(v0, v1, v2, v3);
 | 
			
		||||
		for(i = 0; i < siphash::crounds; ++i)
 | 
			
		||||
			siphash::round(v0, v1, v2, v3);
 | 
			
		||||
 | 
			
		||||
        v0 ^= b;
 | 
			
		||||
		v0 ^= b;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if(hashsz == 16)
 | 
			
		||||
            v2 ^= 0xee;
 | 
			
		||||
        else
 | 
			
		||||
            v2 ^= 0xff;
 | 
			
		||||
		if(hashsz == 16)
 | 
			
		||||
			v2 ^= 0xee;
 | 
			
		||||
		else
 | 
			
		||||
			v2 ^= 0xff;
 | 
			
		||||
 | 
			
		||||
        for(i = 0; i  < siphash::drounds; ++i)
 | 
			
		||||
            siphash::round(v0, v1, v2, v3);
 | 
			
		||||
		for(i = 0; i < siphash::drounds; ++i)
 | 
			
		||||
			siphash::round(v0, v1, v2, v3);
 | 
			
		||||
 | 
			
		||||
        b = v0 ^ v1 ^ v2 ^ v3;
 | 
			
		||||
		b = v0 ^ v1 ^ v2 ^ v3;
 | 
			
		||||
 | 
			
		||||
        siphash::u64to8le(b, h);
 | 
			
		||||
		siphash::u64to8le(b, h);
 | 
			
		||||
 | 
			
		||||
        if(hashsz == 8) return;
 | 
			
		||||
		if(hashsz == 8) return;
 | 
			
		||||
 | 
			
		||||
        v1 ^= 0xdd;
 | 
			
		||||
		v1 ^= 0xdd;
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < siphash::drounds; ++i)
 | 
			
		||||
            siphash::round(v0, v1, v2, v3);
 | 
			
		||||
		for (i = 0; i < siphash::drounds; ++i)
 | 
			
		||||
			siphash::round(v0, v1, v2, v3);
 | 
			
		||||
 | 
			
		||||
        b = v0 ^ v1 ^ v2 ^ v3;
 | 
			
		||||
        siphash::u64to8le(b, h + 8);
 | 
			
		||||
    }
 | 
			
		||||
		b = v0 ^ v1 ^ v2 ^ v3;
 | 
			
		||||
		siphash::u64to8le(b, h + 8);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ namespace stream
 | 
			
		|||
			else
 | 
			
		||||
			{
 | 
			
		||||
				// partially
 | 
			
		||||
				rem =  len - offset;
 | 
			
		||||
				rem = len - offset;
 | 
			
		||||
				memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), len - offset);
 | 
			
		||||
				nextBuffer->offset += (len - offset);
 | 
			
		||||
				offset = len; // break
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +60,7 @@ namespace stream
 | 
			
		|||
		m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
 | 
			
		||||
		m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
 | 
			
		||||
		m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service),
 | 
			
		||||
		m_AckSendTimer (m_Service),  m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port),
 | 
			
		||||
		m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port),
 | 
			
		||||
		m_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO),
 | 
			
		||||
		m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
 | 
			
		||||
		m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +73,7 @@ namespace stream
 | 
			
		|||
		m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
 | 
			
		||||
		m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
 | 
			
		||||
		m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service),
 | 
			
		||||
		m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0),  m_WindowSize (MIN_WINDOW_SIZE),
 | 
			
		||||
		m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE),
 | 
			
		||||
		m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
 | 
			
		||||
		m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -269,7 +269,7 @@ namespace stream
 | 
			
		|||
				m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, optionSize);
 | 
			
		||||
			if (m_RemoteIdentity->IsRSA ())
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), "  Discarded");
 | 
			
		||||
				LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded");
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
			optionData += m_RemoteIdentity->GetFullLen ();
 | 
			
		||||
| 
						 | 
				
			
			@ -435,7 +435,7 @@ namespace stream
 | 
			
		|||
			m_SendBuffer.Add (buf, len, handler);
 | 
			
		||||
		}
 | 
			
		||||
		else if (handler)
 | 
			
		||||
			 handler(boost::system::error_code ());
 | 
			
		||||
			handler(boost::system::error_code ());
 | 
			
		||||
		m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ()));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -471,7 +471,7 @@ namespace stream
 | 
			
		|||
				size++; // resend delay
 | 
			
		||||
				if (m_Status == eStreamStatusNew)
 | 
			
		||||
				{
 | 
			
		||||
					//  initial packet
 | 
			
		||||
					// initial packet
 | 
			
		||||
					m_Status = eStreamStatusOpen;
 | 
			
		||||
					if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());;
 | 
			
		||||
					if (m_RemoteLeaseSet)
 | 
			
		||||
| 
						 | 
				
			
			@ -654,7 +654,7 @@ namespace stream
 | 
			
		|||
		size += 4; // receiveStreamID
 | 
			
		||||
		htobe32buf (packet + size, m_SequenceNumber++);
 | 
			
		||||
		size += 4; // sequenceNum
 | 
			
		||||
		htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ?  m_LastReceivedSequenceNumber : 0);
 | 
			
		||||
		htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0);
 | 
			
		||||
		size += 4; // ack Through
 | 
			
		||||
		packet[size] = 0;
 | 
			
		||||
		size++; // NACK count
 | 
			
		||||
| 
						 | 
				
			
			@ -748,7 +748,7 @@ namespace stream
 | 
			
		|||
 | 
			
		||||
		auto ts = i2p::util::GetMillisecondsSinceEpoch ();
 | 
			
		||||
		if (!m_CurrentRemoteLease || !m_CurrentRemoteLease->endDate || // excluded from LeaseSet
 | 
			
		||||
		    ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD)
 | 
			
		||||
			ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD)
 | 
			
		||||
			UpdateCurrentRemoteLease (true);
 | 
			
		||||
		if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -785,7 +785,7 @@ namespace stream
 | 
			
		|||
				if (ts > m_RoutingSession->GetLeaseSetSubmissionTime () + i2p::garlic::LEASET_CONFIRMATION_TIMEOUT)
 | 
			
		||||
				{
 | 
			
		||||
					// LeaseSet was not confirmed, should try other tunnels
 | 
			
		||||
					LogPrint (eLogWarning, "Streaming: LeaseSet was not confirmed in ", i2p::garlic::LEASET_CONFIRMATION_TIMEOUT,  " milliseconds. Trying to resubmit");
 | 
			
		||||
					LogPrint (eLogWarning, "Streaming: LeaseSet was not confirmed in ", i2p::garlic::LEASET_CONFIRMATION_TIMEOUT, " milliseconds. Trying to resubmit");
 | 
			
		||||
					m_RoutingSession->SetSharedRoutingPath (nullptr);
 | 
			
		||||
					m_CurrentOutboundTunnel = nullptr;
 | 
			
		||||
					m_CurrentRemoteLease = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			@ -1164,7 +1164,7 @@ namespace stream
 | 
			
		|||
		m_Owner->GetService ().post([acceptor, this](void)
 | 
			
		||||
			{
 | 
			
		||||
				if (!m_PendingIncomingStreams.empty ())
 | 
			
		||||
                {
 | 
			
		||||
				{
 | 
			
		||||
					acceptor (m_PendingIncomingStreams.front ());
 | 
			
		||||
					m_PendingIncomingStreams.pop_front ();
 | 
			
		||||
					if (m_PendingIncomingStreams.empty ())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										142
									
								
								libi2pd/Tag.h
									
										
									
									
									
								
							
							
						
						
									
										142
									
								
								libi2pd/Tag.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -16,93 +16,91 @@
 | 
			
		|||
 | 
			
		||||
namespace i2p {
 | 
			
		||||
namespace data {
 | 
			
		||||
 | 
			
		||||
template<size_t sz>
 | 
			
		||||
class Tag
 | 
			
		||||
{
 | 
			
		||||
	BOOST_STATIC_ASSERT_MSG(sz % 8 == 0, "Tag size must be multiple of 8 bytes");
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
	Tag () = default;
 | 
			
		||||
	Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }
 | 
			
		||||
 | 
			
		||||
	bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); }
 | 
			
		||||
	bool operator!= (const Tag& other) const { return !(*this == other); }
 | 
			
		||||
	bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; }
 | 
			
		||||
 | 
			
		||||
	uint8_t * operator()() { return m_Buf; }
 | 
			
		||||
	const uint8_t * operator()() const { return m_Buf; }
 | 
			
		||||
 | 
			
		||||
	operator uint8_t * () { return m_Buf; }
 | 
			
		||||
	operator const uint8_t * () const { return m_Buf; }
 | 
			
		||||
 | 
			
		||||
	const uint8_t * data() const { return m_Buf; }
 | 
			
		||||
	const uint64_t * GetLL () const { return ll; }
 | 
			
		||||
 | 
			
		||||
	bool IsZero () const
 | 
			
		||||
	template<size_t sz>
 | 
			
		||||
	class Tag
 | 
			
		||||
	{
 | 
			
		||||
		for (size_t i = 0; i < sz/8; ++i)
 | 
			
		||||
			if (ll[i]) return false;
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
		BOOST_STATIC_ASSERT_MSG(sz % 8 == 0, "Tag size must be multiple of 8 bytes");
 | 
			
		||||
 | 
			
		||||
	void Fill(uint8_t c)
 | 
			
		||||
	{
 | 
			
		||||
		memset(m_Buf, c, sz);
 | 
			
		||||
	}
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
	void Randomize()
 | 
			
		||||
	{
 | 
			
		||||
		RAND_bytes(m_Buf, sz);
 | 
			
		||||
	}
 | 
			
		||||
			Tag () = default;
 | 
			
		||||
			Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }
 | 
			
		||||
 | 
			
		||||
	std::string ToBase64 () const
 | 
			
		||||
	{
 | 
			
		||||
		char str[sz*2];
 | 
			
		||||
		size_t l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2);
 | 
			
		||||
		return std::string (str, str + l);
 | 
			
		||||
	}
 | 
			
		||||
			bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); }
 | 
			
		||||
			bool operator!= (const Tag& other) const { return !(*this == other); }
 | 
			
		||||
			bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; }
 | 
			
		||||
 | 
			
		||||
	std::string ToBase32 () const
 | 
			
		||||
	{
 | 
			
		||||
		char str[sz*2];
 | 
			
		||||
		size_t l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2);
 | 
			
		||||
		return std::string (str, str + l);
 | 
			
		||||
	}
 | 
			
		||||
			uint8_t * operator()() { return m_Buf; }
 | 
			
		||||
			const uint8_t * operator()() const { return m_Buf; }
 | 
			
		||||
 | 
			
		||||
	size_t FromBase32 (const std::string& s)
 | 
			
		||||
	{
 | 
			
		||||
		return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz);
 | 
			
		||||
	}
 | 
			
		||||
			operator uint8_t * () { return m_Buf; }
 | 
			
		||||
			operator const uint8_t * () const { return m_Buf; }
 | 
			
		||||
 | 
			
		||||
	size_t FromBase64 (const std::string& s)
 | 
			
		||||
	{
 | 
			
		||||
		return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz);
 | 
			
		||||
	}
 | 
			
		||||
			const uint8_t * data() const { return m_Buf; }
 | 
			
		||||
			const uint64_t * GetLL () const { return ll; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
			bool IsZero () const
 | 
			
		||||
			{
 | 
			
		||||
				for (size_t i = 0; i < sz/8; ++i)
 | 
			
		||||
					if (ll[i]) return false;
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
	union // 8 bytes aligned
 | 
			
		||||
	{
 | 
			
		||||
		uint8_t m_Buf[sz];
 | 
			
		||||
		uint64_t ll[sz/8];
 | 
			
		||||
			void Fill(uint8_t c)
 | 
			
		||||
			{
 | 
			
		||||
				memset(m_Buf, c, sz);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			void Randomize()
 | 
			
		||||
			{
 | 
			
		||||
				RAND_bytes(m_Buf, sz);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			std::string ToBase64 () const
 | 
			
		||||
			{
 | 
			
		||||
				char str[sz*2];
 | 
			
		||||
				size_t l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2);
 | 
			
		||||
				return std::string (str, str + l);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			std::string ToBase32 () const
 | 
			
		||||
			{
 | 
			
		||||
				char str[sz*2];
 | 
			
		||||
				size_t l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2);
 | 
			
		||||
				return std::string (str, str + l);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			size_t FromBase32 (const std::string& s)
 | 
			
		||||
			{
 | 
			
		||||
				return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			size_t FromBase64 (const std::string& s)
 | 
			
		||||
			{
 | 
			
		||||
				return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			union // 8 bytes aligned
 | 
			
		||||
			{
 | 
			
		||||
				uint8_t m_Buf[sz];
 | 
			
		||||
				uint64_t ll[sz/8];
 | 
			
		||||
			};
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // data
 | 
			
		||||
} // i2p
 | 
			
		||||
 | 
			
		||||
namespace std
 | 
			
		||||
{
 | 
			
		||||
    // hash for std::unordered_map
 | 
			
		||||
    template<size_t sz> struct hash<i2p::data::Tag<sz> >
 | 
			
		||||
    {
 | 
			
		||||
        size_t operator()(const i2p::data::Tag<sz>& s) const 
 | 
			
		||||
        {
 | 
			
		||||
            return s.GetLL ()[0];
 | 
			
		||||
        }
 | 
			
		||||
    };    
 | 
			
		||||
	// hash for std::unordered_map
 | 
			
		||||
	template<size_t sz> struct hash<i2p::data::Tag<sz> >
 | 
			
		||||
	{
 | 
			
		||||
		size_t operator()(const i2p::data::Tag<sz>& s) const
 | 
			
		||||
		{
 | 
			
		||||
			return s.GetLL ()[0];
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* TAG_H__ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,26 +24,26 @@ namespace util
 | 
			
		|||
	static uint64_t GetLocalMillisecondsSinceEpoch ()
 | 
			
		||||
	{
 | 
			
		||||
		return std::chrono::duration_cast<std::chrono::milliseconds>(
 | 
			
		||||
				 std::chrono::system_clock::now().time_since_epoch()).count ();
 | 
			
		||||
			std::chrono::system_clock::now().time_since_epoch()).count ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static uint32_t GetLocalHoursSinceEpoch ()
 | 
			
		||||
	{
 | 
			
		||||
		return std::chrono::duration_cast<std::chrono::hours>(
 | 
			
		||||
				 std::chrono::system_clock::now().time_since_epoch()).count ();
 | 
			
		||||
			std::chrono::system_clock::now().time_since_epoch()).count ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static uint64_t GetLocalSecondsSinceEpoch ()
 | 
			
		||||
	{
 | 
			
		||||
		return std::chrono::duration_cast<std::chrono::seconds>(
 | 
			
		||||
				 std::chrono::system_clock::now().time_since_epoch()).count ();
 | 
			
		||||
			std::chrono::system_clock::now().time_since_epoch()).count ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static int64_t g_TimeOffset = 0; // in seconds
 | 
			
		||||
 | 
			
		||||
	static void SyncTimeWithNTP (const std::string& address)
 | 
			
		||||
	{
 | 
			
		||||
		LogPrint (eLogInfo,  "Timestamp: NTP request to ", address);
 | 
			
		||||
		LogPrint (eLogInfo, "Timestamp: NTP request to ", address);
 | 
			
		||||
		boost::asio::io_service service;
 | 
			
		||||
		boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp");
 | 
			
		||||
		boost::system::error_code ec;
 | 
			
		||||
| 
						 | 
				
			
			@ -200,4 +200,3 @@ namespace util
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ namespace util
 | 
			
		|||
			~NTPTimeSync ();
 | 
			
		||||
 | 
			
		||||
			void Start ();
 | 
			
		||||
        	void Stop ();
 | 
			
		||||
			void Stop ();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +36,7 @@ namespace util
 | 
			
		|||
		private:
 | 
			
		||||
 | 
			
		||||
			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::deadline_timer m_Timer;
 | 
			
		||||
			int m_SyncInterval;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,4 +46,3 @@ namespace util
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ namespace i2p
 | 
			
		|||
namespace tunnel
 | 
			
		||||
{
 | 
			
		||||
	TransitTunnel::TransitTunnel (uint32_t receiveTunnelID,
 | 
			
		||||
	    const uint8_t * nextIdent, uint32_t nextTunnelID,
 | 
			
		||||
		const uint8_t * nextIdent, uint32_t nextTunnelID,
 | 
			
		||||
		const uint8_t * layerKey,const uint8_t * ivKey):
 | 
			
		||||
			TunnelBase (receiveTunnelID, nextTunnelID, nextIdent)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ namespace tunnel
 | 
			
		|||
 | 
			
		||||
	std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID,
 | 
			
		||||
		const uint8_t * nextIdent, uint32_t nextTunnelID,
 | 
			
		||||
	    const uint8_t * layerKey,const uint8_t * ivKey,
 | 
			
		||||
		const uint8_t * layerKey,const uint8_t * ivKey,
 | 
			
		||||
		bool isGateway, bool isEndpoint)
 | 
			
		||||
	{
 | 
			
		||||
		if (isEndpoint)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -390,7 +390,7 @@ namespace transport
 | 
			
		|||
			{
 | 
			
		||||
				auto r = netdb.FindRouter (ident);
 | 
			
		||||
				{
 | 
			
		||||
					std::unique_lock<std::mutex>	l(m_PeersMutex);
 | 
			
		||||
					std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
					it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, {},
 | 
			
		||||
						i2p::util::GetSecondsSinceEpoch (), {} })).first;
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -553,13 +553,13 @@ namespace transport
 | 
			
		|||
			{
 | 
			
		||||
				auto router = i2p::data::netdb.GetRandomPeerTestRouter (isv4); // v4 only if v4
 | 
			
		||||
				if (router)
 | 
			
		||||
					m_SSUServer->CreateSession (router, true, isv4);	// peer test
 | 
			
		||||
					m_SSUServer->CreateSession (router, true, isv4); // peer test
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					// if not peer test capable routers found pick any
 | 
			
		||||
					router = i2p::data::netdb.GetRandomRouter ();
 | 
			
		||||
					if (router && router->IsSSU ())
 | 
			
		||||
						m_SSUServer->CreateSession (router);		// no peer test
 | 
			
		||||
						m_SSUServer->CreateSession (router); // no peer test
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (i2p::context.SupportsV6 ())
 | 
			
		||||
| 
						 | 
				
			
			@ -713,7 +713,7 @@ namespace transport
 | 
			
		|||
					{
 | 
			
		||||
						profile->TunnelNonReplied();
 | 
			
		||||
					}
 | 
			
		||||
					std::unique_lock<std::mutex>	l(m_PeersMutex);
 | 
			
		||||
					std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
					it = m_Peers.erase (it);
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ namespace transport
 | 
			
		|||
			uint64_t GetTotalReceivedBytes () const { return m_TotalReceivedBytes; };
 | 
			
		||||
			uint64_t GetTotalTransitTransmittedBytes () const { return m_TotalTransitTransmittedBytes; }
 | 
			
		||||
			void UpdateTotalTransitTransmittedBytes (uint32_t add) { m_TotalTransitTransmittedBytes += add; };
 | 
			
		||||
			uint32_t GetInBandwidth  () const { return m_InBandwidth; };
 | 
			
		||||
			uint32_t GetInBandwidth () const { return m_InBandwidth; };
 | 
			
		||||
			uint32_t GetOutBandwidth () const { return m_OutBandwidth; };
 | 
			
		||||
			uint32_t GetTransitBandwidth () const { return m_TransitBandwidth; };
 | 
			
		||||
			bool IsBandwidthExceeded () const;
 | 
			
		||||
| 
						 | 
				
			
			@ -111,16 +111,16 @@ namespace transport
 | 
			
		|||
			size_t GetNumPeers () const { return m_Peers.size (); };
 | 
			
		||||
			std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer () const;
 | 
			
		||||
 | 
			
		||||
    /** get a trusted first hop for restricted routes */
 | 
			
		||||
    std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
 | 
			
		||||
    /** do we want to use restricted routes? */
 | 
			
		||||
    bool RoutesRestricted() const;
 | 
			
		||||
    /** restrict routes to use only these router families for first hops */
 | 
			
		||||
    void RestrictRoutesToFamilies(std::set<std::string> families);
 | 
			
		||||
    /** restrict routes to use only these routers for first hops */
 | 
			
		||||
    void RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers);
 | 
			
		||||
			/** get a trusted first hop for restricted routes */
 | 
			
		||||
			std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
 | 
			
		||||
			/** do we want to use restricted routes? */
 | 
			
		||||
			bool RoutesRestricted() const;
 | 
			
		||||
			/** restrict routes to use only these router families for first hops */
 | 
			
		||||
			void RestrictRoutesToFamilies(std::set<std::string> families);
 | 
			
		||||
			/** restrict routes to use only these routers for first hops */
 | 
			
		||||
			void RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers);
 | 
			
		||||
 | 
			
		||||
    bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const;
 | 
			
		||||
			bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const;
 | 
			
		||||
 | 
			
		||||
			void PeerTest ();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,8 +64,7 @@ namespace tunnel
 | 
			
		|||
							m.hash = i2p::data::IdentHash (fragment);
 | 
			
		||||
							fragment += 32; // to hash
 | 
			
		||||
						break;
 | 
			
		||||
						default:
 | 
			
		||||
							;
 | 
			
		||||
						default: ;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					bool isFragmented = flag & 0x08;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -172,7 +172,7 @@ namespace tunnel
 | 
			
		|||
		SHA256(payload, size+16, hash);
 | 
			
		||||
		memcpy (buf+20, hash, 4); // checksum
 | 
			
		||||
		payload[-1] = 0; // zero
 | 
			
		||||
		ptrdiff_t paddingSize = payload - buf - 25; // 25  = 24 + 1
 | 
			
		||||
		ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1
 | 
			
		||||
		if (paddingSize > 0)
 | 
			
		||||
		{
 | 
			
		||||
			// non-zero padding
 | 
			
		||||
| 
						 | 
				
			
			@ -219,4 +219,3 @@ namespace tunnel
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,6 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
namespace tunnel
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels):
 | 
			
		||||
		m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
 | 
			
		||||
		m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true),
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +66,8 @@ namespace tunnel
 | 
			
		|||
		m_Tests.clear ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant)	{
 | 
			
		||||
	bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant)
 | 
			
		||||
	{
 | 
			
		||||
		if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0)
 | 
			
		||||
		{
 | 
			
		||||
			m_NumInboundHops = inHops;
 | 
			
		||||
| 
						 | 
				
			
			@ -180,8 +180,8 @@ namespace tunnel
 | 
			
		|||
			{
 | 
			
		||||
				if (it->IsEstablished () && it != excluded)
 | 
			
		||||
				{
 | 
			
		||||
						tunnel = it;
 | 
			
		||||
						i++;
 | 
			
		||||
					tunnel = it;
 | 
			
		||||
					i++;
 | 
			
		||||
				}
 | 
			
		||||
				if (i > ind && tunnel) break;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -411,7 +411,7 @@ namespace tunnel
 | 
			
		|||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
 | 
			
		||||
			if (m_CustomPeerSelector)
 | 
			
		||||
					return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound);
 | 
			
		||||
				return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound);
 | 
			
		||||
		}
 | 
			
		||||
		// explicit peers in use
 | 
			
		||||
		if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,18 +80,18 @@ namespace tunnel
 | 
			
		|||
			void UnsetCustomPeerSelector();
 | 
			
		||||
			bool HasCustomPeerSelector();
 | 
			
		||||
 | 
			
		||||
		/** @brief make this tunnel pool yield tunnels that fit latency range [min, max] */
 | 
			
		||||
		void RequireLatency(uint64_t min, uint64_t max) { m_MinLatency = min; m_MaxLatency = max; }
 | 
			
		||||
			/** @brief make this tunnel pool yield tunnels that fit latency range [min, max] */
 | 
			
		||||
			void RequireLatency(uint64_t min, uint64_t max) { m_MinLatency = min; m_MaxLatency = max; }
 | 
			
		||||
 | 
			
		||||
		/** @brief return true if this tunnel pool has a latency requirement */
 | 
			
		||||
		bool HasLatencyRequirement() const { return m_MinLatency > 0 && m_MaxLatency > 0; }
 | 
			
		||||
			/** @brief return true if this tunnel pool has a latency requirement */
 | 
			
		||||
			bool HasLatencyRequirement() const { return m_MinLatency > 0 && m_MaxLatency > 0; }
 | 
			
		||||
 | 
			
		||||
		/** @brief get the lowest latency tunnel in this tunnel pool regardless of latency requirements */
 | 
			
		||||
		std::shared_ptr<InboundTunnel> GetLowestLatencyInboundTunnel(std::shared_ptr<InboundTunnel> exclude=nullptr) const;
 | 
			
		||||
		std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude=nullptr) const;
 | 
			
		||||
			/** @brief get the lowest latency tunnel in this tunnel pool regardless of latency requirements */
 | 
			
		||||
			std::shared_ptr<InboundTunnel> GetLowestLatencyInboundTunnel(std::shared_ptr<InboundTunnel> exclude = nullptr) const;
 | 
			
		||||
			std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude = nullptr) const;
 | 
			
		||||
 | 
			
		||||
		// for overriding tunnel peer selection
 | 
			
		||||
		std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
 | 
			
		||||
			// for overriding tunnel peer selection
 | 
			
		||||
			std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -118,8 +118,8 @@ namespace tunnel
 | 
			
		|||
			std::mutex m_CustomPeerSelectorMutex;
 | 
			
		||||
			ITunnelPeerSelector * m_CustomPeerSelector;
 | 
			
		||||
 | 
			
		||||
		uint64_t m_MinLatency=0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
 | 
			
		||||
		uint64_t m_MaxLatency=0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
 | 
			
		||||
			uint64_t m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
 | 
			
		||||
			uint64_t m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,8 +31,8 @@ namespace api
 | 
			
		|||
		bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
 | 
			
		||||
		i2p::crypto::InitCrypto (precomputation);
 | 
			
		||||
 | 
			
		||||
        int netID; i2p::config::GetOption("netid", netID);
 | 
			
		||||
        i2p::context.SetNetID (netID);
 | 
			
		||||
		int netID; i2p::config::GetOption("netid", netID);
 | 
			
		||||
		i2p::context.SetNetID (netID);
 | 
			
		||||
 | 
			
		||||
		i2p::context.Init ();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -133,4 +133,3 @@ namespace api
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,4 +35,3 @@ namespace api
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -101,21 +101,21 @@ namespace net
 | 
			
		|||
#ifdef WIN32
 | 
			
		||||
	bool IsWindowsXPorLater()
 | 
			
		||||
	{
 | 
			
		||||
	    static bool isRequested = false;
 | 
			
		||||
	    static bool isXP = false;
 | 
			
		||||
	    if (!isRequested)
 | 
			
		||||
	    {
 | 
			
		||||
	        // request
 | 
			
		||||
            OSVERSIONINFO osvi;
 | 
			
		||||
		static bool isRequested = false;
 | 
			
		||||
		static bool isXP = false;
 | 
			
		||||
		if (!isRequested)
 | 
			
		||||
		{
 | 
			
		||||
			// request
 | 
			
		||||
			OSVERSIONINFO osvi;
 | 
			
		||||
 | 
			
		||||
            ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
 | 
			
		||||
            osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 | 
			
		||||
            GetVersionEx(&osvi);
 | 
			
		||||
			ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
 | 
			
		||||
			osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 | 
			
		||||
			GetVersionEx(&osvi);
 | 
			
		||||
 | 
			
		||||
            isXP = osvi.dwMajorVersion <= 5;
 | 
			
		||||
            isRequested = true;
 | 
			
		||||
        }
 | 
			
		||||
        return isXP;
 | 
			
		||||
			isXP = osvi.dwMajorVersion <= 5;
 | 
			
		||||
			isRequested = true;
 | 
			
		||||
		}
 | 
			
		||||
		return isXP;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback)
 | 
			
		||||
| 
						 | 
				
			
			@ -246,22 +246,24 @@ namespace net
 | 
			
		|||
		std::string localAddressUniversal = localAddress.to_string();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        typedef int (* IPN)(int af, const char *src, void *dst);
 | 
			
		||||
		typedef int (* IPN)(int af, const char *src, void *dst);
 | 
			
		||||
		IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
 | 
			
		||||
        if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found
 | 
			
		||||
		if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found
 | 
			
		||||
 | 
			
		||||
		if(localAddress.is_v4())
 | 
			
		||||
		{
 | 
			
		||||
			sockaddr_in inputAddress;
 | 
			
		||||
            inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
 | 
			
		||||
			inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
 | 
			
		||||
			return GetMTUWindowsIpv4(inputAddress, fallback);
 | 
			
		||||
		}
 | 
			
		||||
		else if(localAddress.is_v6())
 | 
			
		||||
		{
 | 
			
		||||
			sockaddr_in6 inputAddress;
 | 
			
		||||
            inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
 | 
			
		||||
			inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
 | 
			
		||||
			return GetMTUWindowsIpv6(inputAddress, fallback);
 | 
			
		||||
		} else {
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported");
 | 
			
		||||
			return fallback;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -355,7 +357,7 @@ namespace net
 | 
			
		|||
				if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af)
 | 
			
		||||
				{
 | 
			
		||||
					// match
 | 
			
		||||
					char  addr[INET6_ADDRSTRLEN];
 | 
			
		||||
					char addr[INET6_ADDRSTRLEN];
 | 
			
		||||
					memset (addr, 0, INET6_ADDRSTRLEN);
 | 
			
		||||
					if(af == AF_INET)
 | 
			
		||||
						inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN);
 | 
			
		||||
| 
						 | 
				
			
			@ -379,7 +381,6 @@ namespace net
 | 
			
		|||
			LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
 | 
			
		||||
		}
 | 
			
		||||
		return boost::asio::ip::address::from_string(fallback);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -487,18 +487,18 @@ namespace client
 | 
			
		|||
				LogPrint (eLogWarning, "Addressbook: subscriptions.txt usage is deprecated, use config file instead");
 | 
			
		||||
			}
 | 
			
		||||
			else if (!i2p::config::IsDefault("addressbook.subscriptions"))
 | 
			
		||||
                        {
 | 
			
		||||
                            // using config file items
 | 
			
		||||
                            std::string subscriptionURLs; i2p::config::GetOption("addressbook.subscriptions", subscriptionURLs);
 | 
			
		||||
                            std::vector<std::string> subsList;
 | 
			
		||||
                            boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on);
 | 
			
		||||
			{
 | 
			
		||||
				// using config file items
 | 
			
		||||
				std::string subscriptionURLs; i2p::config::GetOption("addressbook.subscriptions", subscriptionURLs);
 | 
			
		||||
				std::vector<std::string> subsList;
 | 
			
		||||
				boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on);
 | 
			
		||||
 | 
			
		||||
                            for (size_t i = 0; i < subsList.size (); i++)
 | 
			
		||||
                            {
 | 
			
		||||
                                    m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, subsList[i]));
 | 
			
		||||
                            }
 | 
			
		||||
                            LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
 | 
			
		||||
                        }
 | 
			
		||||
				for (size_t i = 0; i < subsList.size (); i++)
 | 
			
		||||
				{
 | 
			
		||||
					m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, subsList[i]));
 | 
			
		||||
				}
 | 
			
		||||
				LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint (eLogError, "Addressbook: subscriptions already loaded");
 | 
			
		||||
| 
						 | 
				
			
			@ -515,7 +515,7 @@ namespace client
 | 
			
		|||
			if (dot != std::string::npos)
 | 
			
		||||
			{
 | 
			
		||||
				auto domain = it.first.substr (dot + 1);
 | 
			
		||||
				auto it1 = m_Addresses.find (domain);  // find domain in our addressbook
 | 
			
		||||
				auto it1 = m_Addresses.find (domain); // find domain in our addressbook
 | 
			
		||||
				if (it1 != m_Addresses.end () && it1->second->IsIdentHash ())
 | 
			
		||||
				{
 | 
			
		||||
					auto dest = context.FindLocalDestination (it1->second->identHash);
 | 
			
		||||
| 
						 | 
				
			
			@ -610,7 +610,7 @@ namespace client
 | 
			
		|||
				{
 | 
			
		||||
					// download it from default subscription
 | 
			
		||||
					LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription.");
 | 
			
		||||
                                        std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL);
 | 
			
		||||
					std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL);
 | 
			
		||||
					if (!m_DefaultSubscription)
 | 
			
		||||
						m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, defaultSubURL);
 | 
			
		||||
					m_IsDownloading = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -802,7 +802,7 @@ namespace client
 | 
			
		|||
		/* convert url to relative */
 | 
			
		||||
		url.schema = "";
 | 
			
		||||
		url.host   = "";
 | 
			
		||||
		req.uri  = url.to_string();
 | 
			
		||||
		req.uri    = url.to_string();
 | 
			
		||||
		auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port);
 | 
			
		||||
		std::string request = req.to_string();
 | 
			
		||||
		stream->Send ((const uint8_t *) request.data(), request.length());
 | 
			
		||||
| 
						 | 
				
			
			@ -920,7 +920,7 @@ namespace client
 | 
			
		|||
		{
 | 
			
		||||
			auto datagram = m_LocalDestination->GetDatagramDestination ();
 | 
			
		||||
			if (datagram)
 | 
			
		||||
			    datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT);
 | 
			
		||||
				datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -160,5 +160,3 @@ namespace client
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,10 +50,10 @@ namespace client
 | 
			
		|||
	void BOBI2PInboundTunnel::ReceiveAddress (std::shared_ptr<AddressReceiver> receiver)
 | 
			
		||||
	{
 | 
			
		||||
		receiver->socket->async_read_some (boost::asio::buffer(
 | 
			
		||||
				receiver->buffer + receiver->bufferOffset,
 | 
			
		||||
				BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset),
 | 
			
		||||
			receiver->buffer + receiver->bufferOffset,
 | 
			
		||||
			BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset),
 | 
			
		||||
			std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this,
 | 
			
		||||
				std::placeholders::_1, std::placeholders::_2, receiver));
 | 
			
		||||
			std::placeholders::_1, std::placeholders::_2, receiver));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void BOBI2PInboundTunnel::HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred,
 | 
			
		||||
| 
						 | 
				
			
			@ -437,7 +437,7 @@ namespace client
 | 
			
		|||
		if (!m_CurrentDestination)
 | 
			
		||||
		{
 | 
			
		||||
			m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command
 | 
			
		||||
													   m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet);
 | 
			
		||||
				m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet);
 | 
			
		||||
			m_Owner.AddDestination (m_Nickname, m_CurrentDestination);
 | 
			
		||||
		}
 | 
			
		||||
		if (m_InPort)
 | 
			
		||||
| 
						 | 
				
			
			@ -624,14 +624,13 @@ namespace client
 | 
			
		|||
		}
 | 
			
		||||
		// trying to request
 | 
			
		||||
		auto s = shared_from_this ();
 | 
			
		||||
		auto requstCallback = 
 | 
			
		||||
			[s](std::shared_ptr<i2p::data::LeaseSet> ls)
 | 
			
		||||
				{
 | 
			
		||||
					if (ls)
 | 
			
		||||
						s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ());
 | 
			
		||||
					else
 | 
			
		||||
						s->SendReplyError ("LeaseSet Not found");
 | 
			
		||||
				};
 | 
			
		||||
		auto requstCallback = [s](std::shared_ptr<i2p::data::LeaseSet> ls)
 | 
			
		||||
			{
 | 
			
		||||
				if (ls)
 | 
			
		||||
					s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ());
 | 
			
		||||
				else
 | 
			
		||||
					s->SendReplyError ("LeaseSet Not found");
 | 
			
		||||
			};
 | 
			
		||||
		if (addr->IsIdentHash ())
 | 
			
		||||
			localDestination->RequestDestination (addr->identHash, requstCallback);
 | 
			
		||||
		else
 | 
			
		||||
| 
						 | 
				
			
			@ -856,8 +855,7 @@ namespace client
 | 
			
		|||
			session->SendVersion ();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint (eLogError, "BOB: accept error: ",  ecode.message ());
 | 
			
		||||
			LogPrint (eLogError, "BOB: accept error: ", ecode.message ());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,15 +75,15 @@ namespace client
 | 
			
		|||
 | 
			
		||||
	class BOBI2PInboundTunnel: public BOBI2PTunnel
 | 
			
		||||
	{
 | 
			
		||||
			struct AddressReceiver
 | 
			
		||||
			{
 | 
			
		||||
				std::shared_ptr<boost::asio::ip::tcp::socket> socket;
 | 
			
		||||
				char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address
 | 
			
		||||
				uint8_t * data; // pointer to buffer
 | 
			
		||||
				size_t dataLen, bufferOffset;
 | 
			
		||||
		struct AddressReceiver
 | 
			
		||||
		{
 | 
			
		||||
			std::shared_ptr<boost::asio::ip::tcp::socket> socket;
 | 
			
		||||
			char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address
 | 
			
		||||
			uint8_t * data; // pointer to buffer
 | 
			
		||||
			size_t dataLen, bufferOffset;
 | 
			
		||||
 | 
			
		||||
				AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {};
 | 
			
		||||
			};
 | 
			
		||||
			AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {};
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +115,7 @@ namespace client
 | 
			
		|||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			 BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr<ClientDestination> localDestination, bool quiet);
 | 
			
		||||
			BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr<ClientDestination> localDestination, bool quiet);
 | 
			
		||||
 | 
			
		||||
			void Start ();
 | 
			
		||||
			void Stop ();
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +222,7 @@ namespace client
 | 
			
		|||
 | 
			
		||||
			BOBCommandChannel& m_Owner;
 | 
			
		||||
			boost::asio::ip::tcp::socket m_Socket;
 | 
			
		||||
            boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer;
 | 
			
		||||
			boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer;
 | 
			
		||||
			bool m_IsOpen, m_IsQuiet, m_IsActive;
 | 
			
		||||
			std::string m_Nickname, m_InHost, m_OutHost;
 | 
			
		||||
			int m_InPort, m_OutPort;
 | 
			
		||||
| 
						 | 
				
			
			@ -269,4 +269,3 @@ namespace client
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ namespace client
 | 
			
		|||
		{
 | 
			
		||||
			std::string samAddr; i2p::config::GetOption("sam.address", samAddr);
 | 
			
		||||
			uint16_t    samPort; i2p::config::GetOption("sam.port",    samPort);
 | 
			
		||||
			bool singleThread; i2p::config::GetOption("sam.singlethread",  singleThread);
 | 
			
		||||
			bool singleThread; i2p::config::GetOption("sam.singlethread", singleThread);
 | 
			
		||||
			LogPrint(eLogInfo, "Clients: starting SAM bridge at ", samAddr, ":", samPort);
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -407,13 +407,13 @@ namespace client
 | 
			
		|||
	template<typename Section, typename Type>
 | 
			
		||||
	std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
 | 
			
		||||
	{
 | 
			
		||||
        return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value));
 | 
			
		||||
		return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template<typename Section>
 | 
			
		||||
	std::string ClientContext::GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const
 | 
			
		||||
	{
 | 
			
		||||
        return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value);
 | 
			
		||||
		return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template<typename Section>
 | 
			
		||||
| 
						 | 
				
			
			@ -429,7 +429,7 @@ namespace client
 | 
			
		|||
	template<typename Section>
 | 
			
		||||
	void ClientContext::ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const
 | 
			
		||||
	{
 | 
			
		||||
		options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH,  DEFAULT_INBOUND_TUNNEL_LENGTH);
 | 
			
		||||
		options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH);
 | 
			
		||||
		options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH);
 | 
			
		||||
		options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, DEFAULT_INBOUND_TUNNELS_QUANTITY);
 | 
			
		||||
		options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, DEFAULT_OUTBOUND_TUNNELS_QUANTITY);
 | 
			
		||||
| 
						 | 
				
			
			@ -528,10 +528,10 @@ namespace client
 | 
			
		|||
			{
 | 
			
		||||
				std::string type = section.second.get<std::string> (I2P_TUNNELS_SECTION_TYPE);
 | 
			
		||||
				if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT
 | 
			
		||||
						|| type == I2P_TUNNELS_SECTION_TYPE_SOCKS
 | 
			
		||||
						|| type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS
 | 
			
		||||
						|| type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY
 | 
			
		||||
						|| type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT)
 | 
			
		||||
					|| type == I2P_TUNNELS_SECTION_TYPE_SOCKS
 | 
			
		||||
					|| type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS
 | 
			
		||||
					|| type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY
 | 
			
		||||
					|| type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT)
 | 
			
		||||
				{
 | 
			
		||||
					// mandatory params
 | 
			
		||||
					std::string dest;
 | 
			
		||||
| 
						 | 
				
			
			@ -640,9 +640,9 @@ namespace client
 | 
			
		|||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER
 | 
			
		||||
								 || type == I2P_TUNNELS_SECTION_TYPE_HTTP
 | 
			
		||||
								 || type == I2P_TUNNELS_SECTION_TYPE_IRC
 | 
			
		||||
								 || type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER)
 | 
			
		||||
					|| type == I2P_TUNNELS_SECTION_TYPE_HTTP
 | 
			
		||||
					|| type == I2P_TUNNELS_SECTION_TYPE_IRC
 | 
			
		||||
					|| type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER)
 | 
			
		||||
				{
 | 
			
		||||
					// mandatory params
 | 
			
		||||
					std::string host = section.second.get<std::string> (I2P_SERVER_TUNNEL_HOST);
 | 
			
		||||
| 
						 | 
				
			
			@ -699,7 +699,7 @@ namespace client
 | 
			
		|||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					std::shared_ptr<I2PServerTunnel>  serverTunnel;
 | 
			
		||||
					std::shared_ptr<I2PServerTunnel> serverTunnel;
 | 
			
		||||
					if (type == I2P_TUNNELS_SECTION_TYPE_HTTP)
 | 
			
		||||
						serverTunnel = std::make_shared<I2PServerTunnelHTTP> (name, host, port, localDestination, hostOverride, inPort, gzip);
 | 
			
		||||
					else if (type == I2P_TUNNELS_SECTION_TYPE_IRC)
 | 
			
		||||
| 
						 | 
				
			
			@ -745,7 +745,7 @@ namespace client
 | 
			
		|||
							ins.first->second->SetLocalDestination (serverTunnel->GetLocalDestination ());
 | 
			
		||||
						}
 | 
			
		||||
						ins.first->second->isUpdated = true;
 | 
			
		||||
						LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ",   m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists");
 | 
			
		||||
						LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists");
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -769,9 +769,9 @@ namespace client
 | 
			
		|||
			std::string httpProxyKeys;         i2p::config::GetOption("httpproxy.keys",          httpProxyKeys);
 | 
			
		||||
			std::string httpProxyAddr;         i2p::config::GetOption("httpproxy.address",       httpProxyAddr);
 | 
			
		||||
			uint16_t    httpProxyPort;         i2p::config::GetOption("httpproxy.port",          httpProxyPort);
 | 
			
		||||
			i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
 | 
			
		||||
			std::string httpOutProxyURL;       i2p::config::GetOption("httpproxy.outproxy",      httpOutProxyURL);
 | 
			
		||||
			bool        httpAddresshelper;     i2p::config::GetOption("httpproxy.addresshelper", httpAddresshelper);
 | 
			
		||||
			i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
 | 
			
		||||
			LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort);
 | 
			
		||||
			if (httpProxyKeys.length () > 0)
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,7 +78,8 @@ namespace client
 | 
			
		|||
			std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service,
 | 
			
		||||
				const i2p::data::PrivateKeys& keys, bool isPublic = true,
 | 
			
		||||
				const std::map<std::string, std::string> * params = nullptr); // same as previous but on external io_service
 | 
			
		||||
			std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map<std::string, std::string> * params = nullptr);
 | 
			
		||||
			std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
 | 
			
		||||
				const std::string & name, const std::map<std::string, std::string> * params = nullptr);
 | 
			
		||||
			void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination);
 | 
			
		||||
			std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const;
 | 
			
		||||
			bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename,
 | 
			
		||||
| 
						 | 
				
			
			@ -141,6 +142,7 @@ namespace client
 | 
			
		|||
			std::unique_ptr<boost::asio::deadline_timer> m_CleanupUDPTimer;
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			// for HTTP
 | 
			
		||||
			const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; };
 | 
			
		||||
			const decltype(m_ClientTunnels)& GetClientTunnels () const { return m_ClientTunnels; };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -191,7 +191,7 @@ namespace proxy {
 | 
			
		|||
		res.body = ss.str();
 | 
			
		||||
		std::string response = res.to_string();
 | 
			
		||||
		boost::asio::async_write(*m_sock, boost::asio::buffer(response), boost::asio::transfer_all(),
 | 
			
		||||
					 std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
 | 
			
		||||
			std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm)
 | 
			
		||||
| 
						 | 
				
			
			@ -406,7 +406,7 @@ namespace proxy {
 | 
			
		|||
	void HTTPReqHandler::ForwardToUpstreamProxy()
 | 
			
		||||
	{
 | 
			
		||||
		LogPrint(eLogDebug, "HTTPProxy: forward to upstream");
 | 
			
		||||
		// build http requset
 | 
			
		||||
		// build http request
 | 
			
		||||
 | 
			
		||||
		m_ClientRequestURL = m_RequestURL;
 | 
			
		||||
		LogPrint(eLogDebug, "HTTPProxy: ", m_ClientRequestURL.host);
 | 
			
		||||
| 
						 | 
				
			
			@ -458,7 +458,7 @@ namespace proxy {
 | 
			
		|||
			if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified
 | 
			
		||||
			boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port));
 | 
			
		||||
			m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) {
 | 
			
		||||
						m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamSocksProxyConnect, this, std::placeholders::_1));
 | 
			
		||||
				m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamSocksProxyConnect, this, std::placeholders::_1));
 | 
			
		||||
			}));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
| 
						 | 
				
			
			@ -562,14 +562,16 @@ namespace proxy {
 | 
			
		|||
		if(m_ClientRequest.method == "CONNECT") {
 | 
			
		||||
			m_ClientResponse.code = 200;
 | 
			
		||||
			m_send_buf = m_ClientResponse.to_string();
 | 
			
		||||
			boost::asio::async_write(*m_sock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&] (const boost::system::error_code & ec, std::size_t transferred) {
 | 
			
		||||
			boost::asio::async_write(*m_sock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&] (const boost::system::error_code & ec, std::size_t transferred)
 | 
			
		||||
				{
 | 
			
		||||
					if(ec) GenericProxyError("socks proxy error", ec.message().c_str());
 | 
			
		||||
					else HandoverToUpstreamProxy();
 | 
			
		||||
				});
 | 
			
		||||
		} else {
 | 
			
		||||
			m_send_buf = m_ClientRequestBuffer.str();
 | 
			
		||||
			LogPrint(eLogDebug, "HTTPProxy: send ", m_send_buf.size(), " bytes");
 | 
			
		||||
			boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t transferred) {
 | 
			
		||||
			boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t transferred)
 | 
			
		||||
				{
 | 
			
		||||
					if(ec) GenericProxyError("failed to send request to upstream", ec.message().c_str());
 | 
			
		||||
					else HandoverToUpstreamProxy();
 | 
			
		||||
				});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ namespace proxy {
 | 
			
		|||
	class HTTPProxy: public i2p::client::TCPIPAcceptor
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, bool addresshelper, std::shared_ptr<i2p::client::ClientDestination> localDestination);
 | 
			
		||||
			HTTPProxy(const std::string& name, const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr) :
 | 
			
		||||
				HTTPProxy(name, address, port, "", true, localDestination) {} ;
 | 
			
		||||
| 
						 | 
				
			
			@ -15,11 +16,13 @@ namespace proxy {
 | 
			
		|||
			bool GetHelperSupport() { return m_Addresshelper; }
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			// Implements TCPIPAcceptor
 | 
			
		||||
			std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
 | 
			
		||||
			const char* GetName() { return m_Name.c_str (); }
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::string m_Name;
 | 
			
		||||
			std::string m_OutproxyUrl;
 | 
			
		||||
			bool m_Addresshelper;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -221,7 +221,7 @@ namespace client
 | 
			
		|||
			auto s = shared_from_this ();
 | 
			
		||||
			m_Socket->async_read_some (boost::asio::buffer (m_Header, 1),
 | 
			
		||||
				[s](const boost::system::error_code& ecode, std::size_t bytes_transferred)
 | 
			
		||||
				    {
 | 
			
		||||
					{
 | 
			
		||||
						if (!ecode && bytes_transferred > 0 && s->m_Header[0] == I2CP_PROTOCOL_BYTE)
 | 
			
		||||
							s->ReceiveHeader ();
 | 
			
		||||
						else
 | 
			
		||||
| 
						 | 
				
			
			@ -323,7 +323,7 @@ namespace client
 | 
			
		|||
			memcpy (buf + I2CP_HEADER_SIZE, payload, len);
 | 
			
		||||
			boost::asio::async_write (*socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (),
 | 
			
		||||
			std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (),
 | 
			
		||||
							std::placeholders::_1, std::placeholders::_2, buf));
 | 
			
		||||
				std::placeholders::_1, std::placeholders::_2, buf));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint (eLogError, "I2CP: Can't write to the socket");
 | 
			
		||||
| 
						 | 
				
			
			@ -779,14 +779,14 @@ namespace client
 | 
			
		|||
		memcpy (buf + I2CP_HEADER_SIZE + 10, payload, len);
 | 
			
		||||
		boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (),
 | 
			
		||||
		std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (),
 | 
			
		||||
						std::placeholders::_1, std::placeholders::_2, buf));
 | 
			
		||||
			std::placeholders::_1, std::placeholders::_2, buf));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	I2CPServer::I2CPServer (const std::string& interface, int port):
 | 
			
		||||
		m_IsRunning (false), m_Thread (nullptr),
 | 
			
		||||
		m_Acceptor (m_Service,
 | 
			
		||||
#ifdef ANDROID
 | 
			
		||||
            I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address
 | 
			
		||||
			I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address
 | 
			
		||||
#else
 | 
			
		||||
			I2CPSession::proto::endpoint(boost::asio::ip::address::from_string(interface), port))
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -899,4 +899,3 @@ namespace client
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -220,4 +220,3 @@ namespace client
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -115,14 +115,16 @@ namespace client
 | 
			
		|||
	{
 | 
			
		||||
		if(m_ConnectTimeout && !m_LocalDestination->IsReady())
 | 
			
		||||
		{
 | 
			
		||||
			AddReadyCallback([this, streamRequestComplete, address, port] (const boost::system::error_code & ec) {
 | 
			
		||||
			AddReadyCallback([this, streamRequestComplete, address, port] (const boost::system::error_code & ec)
 | 
			
		||||
				{
 | 
			
		||||
					if(ec)
 | 
			
		||||
					{
 | 
			
		||||
						LogPrint(eLogWarning, "I2PService::CreateStream() ", ec.message());
 | 
			
		||||
						streamRequestComplete(nullptr);
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{	if (address->IsIdentHash ())
 | 
			
		||||
					{
 | 
			
		||||
						if (address->IsIdentHash ())
 | 
			
		||||
							this->m_LocalDestination->CreateStream(streamRequestComplete, address->identHash, port);
 | 
			
		||||
						else
 | 
			
		||||
							this->m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port);
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +182,7 @@ namespace client
 | 
			
		|||
		{
 | 
			
		||||
			m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE),
 | 
			
		||||
				std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
 | 
			
		||||
				std::placeholders::_1, std::placeholders::_2));
 | 
			
		||||
					std::placeholders::_1, std::placeholders::_2));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket");
 | 
			
		||||
| 
						 | 
				
			
			@ -191,7 +193,7 @@ namespace client
 | 
			
		|||
		if (m_down) {
 | 
			
		||||
			m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE),
 | 
			
		||||
				std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
 | 
			
		||||
				std::placeholders::_1, std::placeholders::_2));
 | 
			
		||||
					std::placeholders::_1, std::placeholders::_2));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket");
 | 
			
		||||
| 
						 | 
				
			
			@ -205,8 +207,8 @@ namespace client
 | 
			
		|||
			boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len),
 | 
			
		||||
				boost::asio::transfer_all(),
 | 
			
		||||
				std::bind(&TCPIPPipe::HandleUpstreamWrite,
 | 
			
		||||
				shared_from_this(),
 | 
			
		||||
				std::placeholders::_1));
 | 
			
		||||
					shared_from_this(),
 | 
			
		||||
					std::placeholders::_1));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint(eLogError, "TCPIPPipe: upstream write: no socket");
 | 
			
		||||
| 
						 | 
				
			
			@ -220,8 +222,8 @@ namespace client
 | 
			
		|||
			boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len),
 | 
			
		||||
				boost::asio::transfer_all(),
 | 
			
		||||
				std::bind(&TCPIPPipe::HandleDownstreamWrite,
 | 
			
		||||
				shared_from_this(),
 | 
			
		||||
				std::placeholders::_1));
 | 
			
		||||
					shared_from_this(),
 | 
			
		||||
					std::placeholders::_1));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint(eLogError, "TCPIPPipe: downstream write: no socket");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,10 +18,12 @@ namespace client
 | 
			
		|||
	class I2PService : public std::enable_shared_from_this<I2PService>
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			typedef std::function<void(const boost::system::error_code &)> ReadyCallback;
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
			I2PService (std::shared_ptr<ClientDestination> localDestination  = nullptr);
 | 
			
		||||
 | 
			
		||||
			I2PService (std::shared_ptr<ClientDestination> localDestination = nullptr);
 | 
			
		||||
			I2PService (i2p::data::SigningKeyType kt);
 | 
			
		||||
			virtual ~I2PService ();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +44,7 @@ namespace client
 | 
			
		|||
			void AddReadyCallback(ReadyCallback cb);
 | 
			
		||||
 | 
			
		||||
			inline std::shared_ptr<ClientDestination> GetLocalDestination () { return m_LocalDestination; }
 | 
			
		||||
			inline std::shared_ptr<const ClientDestination> GetLocalDestination () const  { return m_LocalDestination; }
 | 
			
		||||
			inline std::shared_ptr<const ClientDestination> GetLocalDestination () const { return m_LocalDestination; }
 | 
			
		||||
			inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest)
 | 
			
		||||
			{
 | 
			
		||||
				if (m_LocalDestination) m_LocalDestination->Release ();
 | 
			
		||||
| 
						 | 
				
			
			@ -59,21 +61,24 @@ namespace client
 | 
			
		|||
			virtual const char* GetName() { return "Generic I2P Service"; }
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			void TriggerReadyCheckTimer();
 | 
			
		||||
			void HandleReadyCheckTimer(const boost::system::error_code & ec);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<ClientDestination> m_LocalDestination;
 | 
			
		||||
			std::unordered_set<std::shared_ptr<I2PServiceHandler> > m_Handlers;
 | 
			
		||||
			std::mutex m_HandlersMutex;
 | 
			
		||||
			std::vector<std::pair<ReadyCallback, uint32_t> > m_ReadyCallbacks;
 | 
			
		||||
			boost::asio::deadline_timer m_ReadyTimer;
 | 
			
		||||
            bool m_ReadyTimerTriggered;
 | 
			
		||||
			bool m_ReadyTimerTriggered;
 | 
			
		||||
			uint32_t m_ConnectTimeout;
 | 
			
		||||
 | 
			
		||||
            const size_t NEVER_TIMES_OUT = 0;
 | 
			
		||||
			const size_t NEVER_TIMES_OUT = 0;
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			bool isUpdated; // transient, used during reload only
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +86,7 @@ namespace client
 | 
			
		|||
	class I2PServiceHandler
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PServiceHandler(I2PService * parent) : m_Service(parent), m_Dead(false) { }
 | 
			
		||||
			virtual ~I2PServiceHandler() { }
 | 
			
		||||
			//If you override this make sure you call it from the children
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +95,7 @@ namespace client
 | 
			
		|||
			void Terminate () { Kill (); };
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			// Call when terminating or handing over to avoid race conditions
 | 
			
		||||
			inline bool Kill () { return m_Dead.exchange(true); }
 | 
			
		||||
			// Call to know if the handler is dead
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +106,7 @@ namespace client
 | 
			
		|||
			inline I2PService * GetOwner() { return m_Service; }
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			I2PService *m_Service;
 | 
			
		||||
			std::atomic<bool> m_Dead; //To avoid cleaning up multiple times
 | 
			
		||||
	};
 | 
			
		||||
| 
						 | 
				
			
			@ -109,11 +117,13 @@ namespace client
 | 
			
		|||
	class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe>
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream);
 | 
			
		||||
			~TCPIPPipe();
 | 
			
		||||
			void Start();
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			void Terminate();
 | 
			
		||||
			void AsyncReceiveUpstream();
 | 
			
		||||
			void AsyncReceiveDownstream();
 | 
			
		||||
| 
						 | 
				
			
			@ -125,6 +135,7 @@ namespace client
 | 
			
		|||
			void DownstreamWrite(size_t len);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE];
 | 
			
		||||
			uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE];
 | 
			
		||||
			std::shared_ptr<boost::asio::ip::tcp::socket> m_up, m_down;
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +146,7 @@ namespace client
 | 
			
		|||
	class TCPIPAcceptor: public I2PService
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			TCPIPAcceptor (const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination = nullptr) :
 | 
			
		||||
				I2PService(localDestination),
 | 
			
		||||
				m_LocalEndpoint (boost::asio::ip::address::from_string(address), port),
 | 
			
		||||
| 
						 | 
				
			
			@ -149,14 +161,16 @@ namespace client
 | 
			
		|||
			//If you override this make sure you call it from the children
 | 
			
		||||
			void Stop ();
 | 
			
		||||
 | 
			
		||||
			const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const  { return m_LocalEndpoint; };
 | 
			
		||||
			const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; };
 | 
			
		||||
 | 
			
		||||
			virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; }
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			virtual std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) = 0;
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			void Accept();
 | 
			
		||||
			void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
 | 
			
		||||
			boost::asio::ip::tcp::endpoint m_LocalEndpoint;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -168,7 +168,7 @@ namespace client
 | 
			
		|||
			{
 | 
			
		||||
				m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
 | 
			
		||||
					std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (),
 | 
			
		||||
						std::placeholders::_1, std::placeholders::_2),
 | 
			
		||||
					std::placeholders::_1, std::placeholders::_2),
 | 
			
		||||
					I2P_TUNNEL_CONNECTION_MAX_IDLE);
 | 
			
		||||
			}
 | 
			
		||||
			else // closed by peer
 | 
			
		||||
| 
						 | 
				
			
			@ -281,7 +281,7 @@ namespace client
 | 
			
		|||
			if (endOfHeader)
 | 
			
		||||
			{
 | 
			
		||||
				if (!m_ConnectionSent) m_OutHeader << "Connection: close\r\n";
 | 
			
		||||
				 if (!m_ProxyConnectionSent) m_OutHeader << "Proxy-Connection: close\r\n";
 | 
			
		||||
				if (!m_ProxyConnectionSent) m_OutHeader << "Proxy-Connection: close\r\n";
 | 
			
		||||
				m_OutHeader << "\r\n"; // end of header
 | 
			
		||||
				m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
 | 
			
		||||
				m_InHeader.str ("");
 | 
			
		||||
| 
						 | 
				
			
			@ -477,7 +477,7 @@ namespace client
 | 
			
		|||
	{
 | 
			
		||||
		auto address = GetAddress ();
 | 
			
		||||
		if (address)
 | 
			
		||||
			return  std::make_shared<I2PClientTunnelHandler>(this, address, m_DestinationPort, socket);
 | 
			
		||||
			return std::make_shared<I2PClientTunnelHandler>(this, address, m_DestinationPort, socket);
 | 
			
		||||
		else
 | 
			
		||||
			return nullptr;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ namespace client
 | 
			
		|||
	class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection>
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
				std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
 | 
			
		||||
			I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +42,7 @@ namespace client
 | 
			
		|||
			void Connect (bool isUniqueLocal = true);
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			void Terminate ();
 | 
			
		||||
 | 
			
		||||
			void Receive ();
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +57,7 @@ namespace client
 | 
			
		|||
			std::shared_ptr<const boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; };
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE];
 | 
			
		||||
			std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
 | 
			
		||||
			std::shared_ptr<i2p::stream::Stream> m_Stream;
 | 
			
		||||
| 
						 | 
				
			
			@ -65,15 +68,18 @@ namespace client
 | 
			
		|||
	class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
				std::shared_ptr<i2p::stream::Stream> stream):
 | 
			
		||||
				I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false),
 | 
			
		||||
				m_ConnectionSent (false), m_ProxyConnectionSent (false) {};
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			void Write (const uint8_t * buf, size_t len);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::stringstream m_InHeader, m_OutHeader;
 | 
			
		||||
			bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent;
 | 
			
		||||
	};
 | 
			
		||||
| 
						 | 
				
			
			@ -81,14 +87,17 @@ namespace client
 | 
			
		|||
	class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
 | 
			
		||||
				std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
				const boost::asio::ip::tcp::endpoint& target, const std::string& host);
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			void Write (const uint8_t * buf, size_t len);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::string m_Host;
 | 
			
		||||
			std::stringstream m_InHeader, m_OutHeader;
 | 
			
		||||
			bool m_HeaderSent;
 | 
			
		||||
| 
						 | 
				
			
			@ -98,14 +107,17 @@ namespace client
 | 
			
		|||
	class I2PTunnelConnectionIRC: public I2PTunnelConnection
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
 | 
			
		||||
				std::shared_ptr<boost::asio::ip::tcp::socket> socket,
 | 
			
		||||
				const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass);
 | 
			
		||||
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			void Write (const uint8_t * buf, size_t len);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<const i2p::data::IdentityEx> m_From;
 | 
			
		||||
			std::stringstream m_OutPacket, m_InPacket;
 | 
			
		||||
			bool m_NeedsWebIrc;
 | 
			
		||||
| 
						 | 
				
			
			@ -116,10 +128,12 @@ namespace client
 | 
			
		|||
	class I2PClientTunnel: public TCPIPAcceptor
 | 
			
		||||
	{
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			// Implements TCPIPAcceptor
 | 
			
		||||
			std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
 | 
			
		||||
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PClientTunnel (const std::string& name, const std::string& destination,
 | 
			
		||||
				const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort = 0);
 | 
			
		||||
			~I2PClientTunnel () {}
 | 
			
		||||
| 
						 | 
				
			
			@ -130,9 +144,11 @@ namespace client
 | 
			
		|||
			const char* GetName() { return m_Name.c_str (); }
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<const Address> GetAddress ();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::string m_Name, m_Destination;
 | 
			
		||||
			std::shared_ptr<const Address> m_Address;
 | 
			
		||||
			int m_DestinationPort;
 | 
			
		||||
| 
						 | 
				
			
			@ -160,9 +176,9 @@ namespace client
 | 
			
		|||
		uint8_t m_Buffer[I2P_UDP_MAX_MTU];
 | 
			
		||||
 | 
			
		||||
		UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
 | 
			
		||||
							 const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
 | 
			
		||||
							 boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident,
 | 
			
		||||
							 uint16_t ourPort, uint16_t theirPort);
 | 
			
		||||
			const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
 | 
			
		||||
			boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident,
 | 
			
		||||
			uint16_t ourPort, uint16_t theirPort);
 | 
			
		||||
		void HandleReceived(const boost::system::error_code & ecode, std::size_t len);
 | 
			
		||||
		void Receive();
 | 
			
		||||
	};
 | 
			
		||||
| 
						 | 
				
			
			@ -195,6 +211,7 @@ namespace client
 | 
			
		|||
	class I2PUDPServerTunnel
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PUDPServerTunnel(const std::string & name,
 | 
			
		||||
				std::shared_ptr<i2p::client::ClientDestination> localDestination,
 | 
			
		||||
				boost::asio::ip::address localAddress,
 | 
			
		||||
| 
						 | 
				
			
			@ -210,10 +227,12 @@ namespace client
 | 
			
		|||
			void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
 | 
			
		||||
			UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			bool m_IsUniqueLocal;
 | 
			
		||||
			const std::string m_Name;
 | 
			
		||||
			boost::asio::ip::address m_LocalAddress;
 | 
			
		||||
| 
						 | 
				
			
			@ -226,6 +245,7 @@ namespace client
 | 
			
		|||
	class I2PUDPClientTunnel
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest,
 | 
			
		||||
				boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr<i2p::client::ClientDestination> localDestination,
 | 
			
		||||
				uint16_t remotePort, bool gzip);
 | 
			
		||||
| 
						 | 
				
			
			@ -240,6 +260,7 @@ namespace client
 | 
			
		|||
			void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
 | 
			
		||||
			void RecvFromLocal();
 | 
			
		||||
			void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred);
 | 
			
		||||
| 
						 | 
				
			
			@ -263,6 +284,7 @@ namespace client
 | 
			
		|||
	class I2PServerTunnel: public I2PService
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PServerTunnel (const std::string& name, const std::string& address, int port,
 | 
			
		||||
				std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -282,6 +304,7 @@ namespace client
 | 
			
		|||
			const char* GetName() { return m_Name.c_str (); }
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
 | 
			
		||||
				std::shared_ptr<boost::asio::ip::tcp::resolver> resolver);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -290,6 +313,7 @@ namespace client
 | 
			
		|||
			virtual std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			bool m_IsUniqueLocal;
 | 
			
		||||
			std::string m_Name, m_Address;
 | 
			
		||||
			int m_Port;
 | 
			
		||||
| 
						 | 
				
			
			@ -302,28 +326,34 @@ namespace client
 | 
			
		|||
	class I2PServerTunnelHTTP: public I2PServerTunnel
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port,
 | 
			
		||||
				std::shared_ptr<ClientDestination> localDestination, const std::string& host,
 | 
			
		||||
				int inport = 0, bool gzip = true);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::string m_Host;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class I2PServerTunnelIRC: public I2PServerTunnel
 | 
			
		||||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			I2PServerTunnelIRC (const std::string& name, const std::string& address, int port,
 | 
			
		||||
				std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass,
 | 
			
		||||
				int inport = 0, bool gzip = true);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			std::string m_WebircPass;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ namespace client
 | 
			
		|||
		{
 | 
			
		||||
			m_ResolveTimer->expires_from_now(boost::posix_time::seconds(1));
 | 
			
		||||
			m_ResolveTimer->async_wait([&](const boost::system::error_code & ec) {
 | 
			
		||||
					if(!ec)	ResolveCurrentLeaseSet();
 | 
			
		||||
				if(!ec)	ResolveCurrentLeaseSet();
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue