/ libi2pd / RouterContext.cpp
RouterContext.cpp
   1  /*
   2  * Copyright (c) 2013-2026, The PurpleI2P Project
   3  *
   4  * This file is part of Purple i2pd project and licensed under BSD3
   5  *
   6  * See full license text in LICENSE file at top of project tree
   7  */
   8  
   9  #include <fstream>
  10  #include <openssl/rand.h>
  11  #include "Config.h"
  12  #include "Crypto.h"
  13  #include "Ed25519.h"
  14  #include "Timestamp.h"
  15  #include "I2NPProtocol.h"
  16  #include "NetDb.hpp"
  17  #include "FS.h"
  18  #include "util.h"
  19  #include "version.h"
  20  #include "Log.h"
  21  #include "Family.h"
  22  #include "ECIESX25519AEADRatchetSession.h"
  23  #include "Transports.h"
  24  #include "Tunnel.h"
  25  #include "CryptoKey.h"
  26  #include "RouterContext.h"
  27  
  28  namespace i2p
  29  {
  30  	RouterContext context;
  31  
  32  	RouterContext::RouterContext ():
  33  		m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
  34  		m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown),
  35  		m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone),
  36  		m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID),
  37  		m_PublishReplyToken (0), m_IsHiddenMode (false), m_IsSaving (false)
  38  	{
  39  	}
  40  
  41  	void RouterContext::Init ()
  42  	{
  43  		srand (GetRng ()() % 1000);
  44  		m_StartupTime = i2p::util::GetMonotonicSeconds ();
  45  
  46  		if (!Load ())
  47  			CreateNewRouter ();
  48  		m_Decryptor = m_Keys.CreateDecryptor (nullptr);
  49  		m_TunnelDecryptor = m_Keys.CreateDecryptor (nullptr);
  50  		UpdateRouterInfo ();
  51  		i2p::crypto::InitNoiseNState (m_InitialNoiseState, GetIdentity ()->GetEncryptionPublicKey ());
  52  		m_ECIESSession = std::make_shared<i2p::garlic::RouterIncomingRatchetSession>(m_InitialNoiseState);
  53  	}
  54  
  55  	void RouterContext::Start ()
  56  	{
  57  		if (!m_Service)
  58  		{
  59  			m_Service.reset (new RouterService);
  60  			m_Service->Start ();
  61  			m_PublishTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ()));
  62  			ScheduleInitialPublish ();
  63  			m_CongestionUpdateTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ()));
  64  			ScheduleCongestionUpdate ();
  65  			m_CleanupTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ()));
  66  			ScheduleCleanupTimer ();
  67  		}
  68  	}
  69  
  70  	void RouterContext::Stop ()
  71  	{
  72  		if (m_Service)
  73  		{
  74  			if (m_PublishTimer)
  75  				m_PublishTimer->cancel ();
  76  			if (m_CongestionUpdateTimer)
  77  				m_CongestionUpdateTimer->cancel ();
  78  			m_Service->Stop ();
  79  			CleanUp (); // GarlicDestination
  80  		}
  81  	}
  82  
  83  	std::shared_ptr<i2p::data::RouterInfo::Buffer> RouterContext::CopyRouterInfoBuffer () const
  84  	{
  85  		std::lock_guard<std::mutex> l(m_RouterInfoMutex);
  86  		return m_RouterInfo.CopyBuffer ();
  87  	}
  88  
  89  	void RouterContext::CreateNewRouter ()
  90  	{
  91  		m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
  92  			i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
  93  		SaveKeys ();
  94  		NewRouterInfo ();
  95  	}
  96  
  97  	void RouterContext::NewRouterInfo ()
  98  	{
  99  		i2p::data::LocalRouterInfo routerInfo;
 100  		routerInfo.SetRouterIdentity (GetIdentity ());
 101  		uint16_t port; i2p::config::GetOption("port", port);
 102  		if (!port) port = SelectRandomPort ();
 103  		bool ipv4;  i2p::config::GetOption("ipv4", ipv4);
 104  		bool ipv6;  i2p::config::GetOption("ipv6", ipv6);
 105  		bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
 106  		bool ssu2;  i2p::config::GetOption("ssu2.enabled", ssu2);
 107  		bool ygg;   i2p::config::GetOption("meshnets.yggdrasil", ygg);
 108  		bool nat;   i2p::config::GetOption("nat", nat);
 109  
 110  		if ((ntcp2 || ygg) && !m_NTCP2Keys)
 111  			NewNTCP2Keys ();
 112  		if (ssu2 && !m_SSU2Keys)
 113  			NewSSU2Keys ();
 114  		bool ntcp2Published = false;
 115  		if (ntcp2)
 116  		{
 117  			i2p::config::GetOption("ntcp2.published", ntcp2Published);
 118  			if (ntcp2Published)
 119  			{
 120  				std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
 121  				if (!ntcp2proxy.empty ()) ntcp2Published = false;
 122  			}
 123  		}
 124  		bool ssu2Published = false;
 125  		if (ssu2)
 126  			i2p::config::GetOption("ssu2.published", ssu2Published);
 127  		uint8_t caps = 0;
 128  		if (ipv4)
 129  		{
 130  			std::string host;
 131  			if (!nat)
 132  				// we have no NAT so set external address from local address
 133  				i2p::config::GetOption("address4", host);
 134  			if (host.empty ()) i2p::config::GetOption("host", host);
 135  
 136  			if (ntcp2)
 137  			{
 138  				uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
 139  				if (!ntcp2Port) ntcp2Port = port;
 140  				if (ntcp2Published && ntcp2Port)
 141  				{
 142  					boost::asio::ip::address addr;
 143  					if (!host.empty ())
 144  						addr = boost::asio::ip::make_address (host);
 145  					if (!addr.is_v4())
 146  						addr = boost::asio::ip::address_v4 ();
 147  					routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port);
 148  				}
 149  				else
 150  				{
 151  					// add non-published NTCP2 address
 152  					uint8_t addressCaps = i2p::data::RouterInfo::AddressCaps::eV4;
 153  					if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
 154  					routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, addressCaps);
 155  				}
 156  			}
 157  			if (ssu2)
 158  			{
 159  				uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
 160  				if (!ssu2Port) ssu2Port = port;
 161  				if (ssu2Published && ssu2Port)
 162  				{
 163  					boost::asio::ip::address addr;
 164  					if (!host.empty ())
 165  						addr = boost::asio::ip::make_address (host);
 166  					if (!addr.is_v4())
 167  						addr = boost::asio::ip::address_v4 ();
 168  					routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port);
 169  				}
 170  				else
 171  				{
 172  					uint8_t addressCaps = i2p::data::RouterInfo::AddressCaps::eV4;
 173  					if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
 174  					routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, addressCaps);
 175  				}
 176  			}
 177  		}
 178  		if (ipv6)
 179  		{
 180  			auto ipv6addr = i2p::util::net::GetClearnetIPV6Address ();
 181  			if (!ipv6addr.is_unspecified ())
 182  			{
 183  				std::string host; i2p::config::GetOption("address6", host);
 184  				if (host.empty () && !ipv4) i2p::config::GetOption("host", host); // use host for ipv6 only if ipv4 is not presented
 185  
 186  				if (ntcp2)
 187  				{
 188  					uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
 189  					if (!ntcp2Port) ntcp2Port = port;
 190  					if (ntcp2Published && ntcp2Port)
 191  					{
 192  						std::string ntcp2Host;
 193  						if (!i2p::config::IsDefault ("ntcp2.addressv6"))
 194  							i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host);
 195  						else
 196  							ntcp2Host = host;
 197  						boost::asio::ip::address addr;
 198  						if (!ntcp2Host.empty ())
 199  							addr = boost::asio::ip::make_address (ntcp2Host);
 200  						if (!addr.is_v6())
 201  							addr = boost::asio::ip::address_v6 ();
 202  						routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port);
 203  					}
 204  					else
 205  					{
 206  						if (!ipv4) // no other ntcp2 addresses yet
 207  							routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::AddressCaps::eV6);
 208  					}
 209  				}
 210  				if (ssu2)
 211  				{
 212  					uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
 213  					if (!ssu2Port) ssu2Port = port;
 214  					if (ssu2Published && ssu2Port)
 215  					{
 216  						boost::asio::ip::address addr;
 217  						if (!host.empty ())
 218  							addr = boost::asio::ip::make_address (host);
 219  						if (!addr.is_v6())
 220  							addr = boost::asio::ip::address_v6 ();
 221  						routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port);
 222  					}
 223  					else
 224  					{
 225  						if (!ipv4) // no other ssu2 addresses yet
 226  							routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::AddressCaps::eV6);
 227  					}
 228  				}
 229  			}
 230  		}
 231  		if (ygg)
 232  		{
 233  			auto yggaddr = i2p::util::net::GetYggdrasilAddress ();
 234  			if (!yggaddr.is_unspecified ())
 235  				routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, yggaddr, port);
 236  		}
 237  
 238  		routerInfo.UpdateCaps (caps); // caps + L
 239  		routerInfo.SetProperty ("netId", std::to_string (m_NetID));
 240  		routerInfo.SetProperty ("router.version", I2P_VERSION);
 241  		routerInfo.CreateBuffer (m_Keys);
 242  		m_RouterInfo.SetRouterIdentity (GetIdentity ());
 243  		m_RouterInfo.Update (routerInfo.GetBuffer (), routerInfo.GetBufferLen ());
 244  		m_RouterInfo.SetUnreachable (false);
 245  	}
 246  
 247  	uint16_t RouterContext::SelectRandomPort () const
 248  	{
 249  		uint16_t port;
 250  		do
 251  		{
 252  			port = rand () % (30777 - 9111) + 9111; // I2P network ports range
 253  		}
 254  		while(i2p::util::net::IsPortInReservedRange(port));
 255  
 256  		return port;
 257  	}
 258  
 259  	void RouterContext::UpdateRouterInfo ()
 260  	{
 261  		std::shared_ptr<i2p::data::RouterInfo::Buffer> buffer;
 262  		{
 263  			std::lock_guard<std::mutex> l(m_RouterInfoMutex);
 264  			m_RouterInfo.CreateBuffer (m_Keys);
 265  			buffer = m_RouterInfo.CopyBuffer ();
 266  		}
 267  		{
 268  			// update save buffer to latest
 269  			std::lock_guard<std::mutex> l(m_SaveBufferMutex);
 270  			m_SaveBuffer = buffer;
 271  		}
 272  		bool isSaving = false;
 273  		if (m_IsSaving.compare_exchange_strong (isSaving, true)) // try to save only if not being saved
 274  		{
 275  			auto savingRouterInfo = std::async (std::launch::async, [this]()
 276  				{
 277  					std::shared_ptr<i2p::data::RouterInfo::Buffer> buffer;
 278  					while (m_SaveBuffer)
 279  					{
 280  						{
 281  							std::lock_guard<std::mutex> l(m_SaveBufferMutex);
 282  							buffer = m_SaveBuffer;
 283  							m_SaveBuffer = nullptr;
 284  						}
 285  						if (buffer)
 286  							i2p::data::RouterInfo::SaveToFile (i2p::fs::DataDirPath (ROUTER_INFO), buffer);
 287  					}
 288  					m_IsSaving = false;
 289  				});
 290  		}
 291  		m_LastUpdateTime = i2p::util::GetSecondsSinceEpoch ();
 292  	}
 293  
 294  	void RouterContext::NewNTCP2Keys ()
 295  	{
 296  		m_NTCP2StaticKeys.reset (new i2p::crypto::X25519Keys ());
 297  		m_NTCP2StaticKeys->GenerateKeys ();
 298  		m_NTCP2Keys.reset (new NTCP2PrivateKeys ());
 299  		m_NTCP2StaticKeys->GetPrivateKey (m_NTCP2Keys->staticPrivateKey);
 300  		memcpy (m_NTCP2Keys->staticPublicKey, m_NTCP2StaticKeys->GetPublicKey (), 32);
 301  		RAND_bytes (m_NTCP2Keys->iv, 16);
 302  		// save
 303  		std::ofstream fk (i2p::fs::DataDirPath (NTCP2_KEYS), std::ofstream::binary | std::ofstream::out);
 304  		fk.write ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys));
 305  	}
 306  
 307  	void RouterContext::NewSSU2Keys ()
 308  	{
 309  		m_SSU2StaticKeys.reset (new i2p::crypto::X25519Keys ());
 310  		m_SSU2StaticKeys->GenerateKeys ();
 311  		m_SSU2Keys.reset (new SSU2PrivateKeys ());
 312  		m_SSU2StaticKeys->GetPrivateKey (m_SSU2Keys->staticPrivateKey);
 313  		memcpy (m_SSU2Keys->staticPublicKey, m_SSU2StaticKeys->GetPublicKey (), 32);
 314  		RAND_bytes (m_SSU2Keys->intro, 32);
 315  		// save
 316  		std::ofstream fk (i2p::fs::DataDirPath (SSU2_KEYS), std::ofstream::binary | std::ofstream::out);
 317  		fk.write ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys));
 318  	}
 319  
 320  	void RouterContext::SetTesting (bool testing)
 321  	{
 322  		if (testing != m_Testing)
 323  		{
 324  			m_Testing = testing;
 325  			if (m_Testing)
 326  				m_Error = eRouterErrorNone;
 327  		}
 328  	}
 329  
 330  	void RouterContext::SetTestingV6 (bool testing)
 331  	{
 332  		if (testing != m_TestingV6)
 333  		{
 334  			m_TestingV6 = testing;
 335  			if (m_TestingV6)
 336  				m_ErrorV6 = eRouterErrorNone;
 337  		}
 338  	}
 339  
 340  	void RouterContext::SetStatus (RouterStatus status)
 341  	{
 342  		SetTesting (false);
 343  		if (status != m_Status)
 344  		{
 345  			LogPrint(eLogInfo, "Router: network status v4 changed ",
 346  				ROUTER_STATUS_NAMES[m_Status], " -> ", ROUTER_STATUS_NAMES[status]);
 347  			m_Status = status;
 348  			switch (m_Status)
 349  			{
 350  				case eRouterStatusOK:
 351  					SetReachable (true, false); // ipv4
 352  				break;
 353  				case eRouterStatusFirewalled:
 354  					SetUnreachable (true, false); // ipv4
 355  				break;
 356  				case eRouterStatusMesh:
 357  					m_RouterInfo.UpdateCaps (m_RouterInfo.GetCaps () | i2p::data::RouterInfo::eReachable);
 358  				break;
 359  				case eRouterStatusProxy:
 360  				case eRouterStatusStan:
 361  					m_RouterInfo.UpdateCaps ((m_RouterInfo.GetCaps () | i2p::data::RouterInfo::eUnreachable) & ~i2p::data::RouterInfo::eReachable);
 362  				break;
 363  				default:
 364  					;
 365  			}
 366  		}
 367  	}
 368  
 369  	void RouterContext::SetStatusV6 (RouterStatus status)
 370  	{
 371  		SetTestingV6 (false);
 372  		if (status != m_StatusV6)
 373  		{
 374  			LogPrint(eLogInfo, "Router: network status v6 changed ",
 375  				ROUTER_STATUS_NAMES[m_StatusV6], " -> ", ROUTER_STATUS_NAMES[status]);
 376  			m_StatusV6 = status;
 377  			switch (m_StatusV6)
 378  			{
 379  				case eRouterStatusOK:
 380  					SetReachable (false, true); // ipv6
 381  				break;
 382  				case eRouterStatusFirewalled:
 383  					SetUnreachable (false, true); // ipv6
 384  				break;
 385  				default:
 386  					;
 387  			}
 388  		}
 389  	}
 390  
 391  	void RouterContext::UpdatePort (int port)
 392  	{
 393  		auto addresses = m_RouterInfo.GetAddresses ();
 394  		if (!addresses) return;
 395  		bool updated = false;
 396  		for (auto& address : *addresses)
 397  		{
 398  			if (address && address->port != port)
 399  			{
 400  				address->port = port;
 401  				updated = true;
 402  			}
 403  		}
 404  		if (updated)
 405  			UpdateRouterInfo ();
 406  	}
 407  
 408  	void RouterContext::PublishNTCP2Address (std::shared_ptr<i2p::data::RouterInfo::Address> address,
 409  		int port, bool publish, int version) const
 410  	{
 411  		if (!address) return;
 412  		if (!port && !address->port) port = SelectRandomPort ();
 413  		if (port) address->port = port;
 414  		address->published = publish;
 415  		address->v = version;
 416  		memcpy (address->i, m_NTCP2Keys->iv, 16);
 417  	}
 418  
 419  	void RouterContext::PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg, int version)
 420  	{
 421  		if (!m_NTCP2Keys) return;
 422  		auto addresses = m_RouterInfo.GetAddresses ();
 423  		if (!addresses) return;
 424  		bool updated = false;
 425  		if (v4)
 426  		{
 427  			auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V4Idx];
 428  			if (addr && (addr->port != port || addr->published != publish || addr->v != version))
 429  			{
 430  				PublishNTCP2Address (addr, port, publish, version);
 431  				updated = true;
 432  			}
 433  		}
 434  		if (v6)
 435  		{
 436  			auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx];
 437  			if (addr && (addr->port != port || addr->published != publish || addr->v != version))
 438  			{
 439  				PublishNTCP2Address (addr, port, publish, version);
 440  				updated = true;
 441  			}
 442  		}
 443  		if (ygg)
 444  		{
 445  			auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6MeshIdx];
 446  			if (addr && (addr->port != port || addr->published != publish))
 447  			{
 448  				PublishNTCP2Address (addr, port, publish, 2);
 449  				updated = true;
 450  			}
 451  		}
 452  
 453  		if (updated)
 454  			UpdateRouterInfo ();
 455  	}
 456  
 457  	void RouterContext::UpdateNTCP2Keys ()
 458  	{
 459  		if (!m_NTCP2Keys) return;
 460  		auto addresses = m_RouterInfo.GetAddresses ();
 461  		if (!addresses) return;
 462  		for (auto& it: *addresses)
 463  		{
 464  			if (it && it->IsNTCP2 ())
 465  			{
 466  				it->s = m_NTCP2Keys->staticPublicKey;
 467  				memcpy (it->i, m_NTCP2Keys->iv, 16);
 468  			}
 469  		}
 470  	}
 471  
 472  	void RouterContext::PublishSSU2Address (int port, bool publish, bool v4, bool v6)
 473  	{
 474  		if (!m_SSU2Keys) return;
 475  		auto addresses = m_RouterInfo.GetAddresses ();
 476  		if (!addresses) return;
 477  		int newPort = 0;
 478  		if (!port)
 479  		{
 480  			for (const auto& address : *addresses)
 481  				if (address && address->port)
 482  				{
 483  					newPort = address->port;
 484  					break;
 485  				}
 486  			if (!newPort) newPort = SelectRandomPort ();
 487  		}
 488  		bool updated = false;
 489  		for (auto& address : *addresses)
 490  		{
 491  			if (address && address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) &&
 492  				((v4 && address->IsV4 ()) || (v6 && address->IsV6 ())))
 493  			{
 494  				if (port) address->port = port;
 495  				else if (!address->port) address->port = newPort;
 496  				address->published = publish;
 497  				if (publish)
 498  				{
 499                      UpdateSSU2AddressCapsTesting (address, true);
 500                      UpdateSSU2AddressCapsIntroducer (address, !m_IsFloodfill);
 501  				}
 502  				else
 503  				{
 504                      UpdateSSU2AddressCapsTesting (address, false);
 505                      UpdateSSU2AddressCapsIntroducer (address, false);
 506  				}
 507  				updated = true;
 508  			}
 509  		}
 510  		if (updated)
 511  			UpdateRouterInfo ();
 512  	}
 513  
 514  	void RouterContext::UpdateSSU2AddressCapsIntroducer (std::shared_ptr<i2p::data::RouterInfo::Address> address, bool isIntroducer) const
 515  	{
 516          if (address)
 517          {
 518              if (isIntroducer)
 519                  address->caps |= i2p::data::RouterInfo::eSSUIntroducer;
 520              else
 521                  address->caps &= ~i2p::data::RouterInfo::eSSUIntroducer;
 522          }
 523  	}
 524  
 525      void RouterContext::UpdateSSU2AddressCapsTesting (std::shared_ptr<i2p::data::RouterInfo::Address> address, bool isTesting) const
 526  	{
 527          if (address)
 528          {
 529              if (isTesting)
 530                  address->caps |= i2p::data::RouterInfo::eSSUTesting;
 531              else
 532                  address->caps &= ~i2p::data::RouterInfo::eSSUTesting;
 533          }
 534      }
 535  
 536  	void RouterContext::UpdateSSU2Keys ()
 537  	{
 538  		if (!m_SSU2Keys) return;
 539  		auto addresses = m_RouterInfo.GetAddresses ();
 540  		if (!addresses) return;
 541  		for (auto& it: *addresses)
 542  		{
 543  			if (it && it->IsSSU2 ())
 544  			{
 545  				it->s = m_SSU2Keys->staticPublicKey;
 546  				it->i = m_SSU2Keys->intro;
 547  			}
 548  		}
 549  	}
 550  
 551  	void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
 552  	{
 553  		auto addresses = m_RouterInfo.GetAddresses ();
 554  		if (!addresses) return;
 555  		bool updated = false;
 556  		if (host.is_v4 ())
 557  		{
 558  			auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V4Idx];
 559  			if (addr && addr->host != host)
 560  			{
 561  				addr->host = host;
 562  				updated = true;
 563  			}
 564  			addr = (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx];
 565  			if (addr && addr->host != host)
 566  			{
 567  				addr->host = host;
 568  				updated = true;
 569  			}
 570  		}
 571  		else if (host.is_v6 ())
 572  		{
 573  			auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx];
 574  			if (addr && addr->host != host)
 575  			{
 576  				addr->host = host;
 577  				updated = true;
 578  			}
 579  			addr = (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx];
 580  			if (addr && (addr->host != host || !addr->ssu->mtu))
 581  			{
 582  				addr->host = host;
 583  				if (m_StatusV6 != eRouterStatusProxy)
 584  				{
 585  					// update MTU
 586  					auto mtu = i2p::util::net::GetMTU (host);
 587  					if (mtu)
 588  					{
 589  						LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu);
 590  						int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ());
 591  						if (mtu > maxMTU)
 592  						{
 593  							mtu = maxMTU;
 594  							LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes");
 595  						}
 596  						addr->ssu->mtu = mtu;
 597  					}
 598  				}
 599  				updated = true;
 600  			}
 601  		}
 602  
 603  		auto ts = i2p::util::GetSecondsSinceEpoch ();
 604  		if (updated || ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL)
 605  			UpdateRouterInfo ();
 606  	}
 607  
 608  	bool RouterContext::AddSSU2Introducer (const i2p::data::RouterInfo::Introducer& introducer, bool v4)
 609  	{
 610  		bool ret = m_RouterInfo.AddSSU2Introducer (introducer, v4);
 611  		if (ret)
 612  			UpdateRouterInfo ();
 613  		return ret;
 614  	}
 615  
 616  	void RouterContext::RemoveSSU2Introducer (const i2p::data::IdentHash& h, bool v4)
 617  	{
 618  		if (m_RouterInfo.RemoveSSU2Introducer (h, v4))
 619  			UpdateRouterInfo ();
 620  	}
 621  
 622  	void RouterContext::UpdateSSU2Introducer (const i2p::data::IdentHash& h, bool v4, uint32_t iTag, uint32_t iExp)
 623  	{
 624  		if (m_RouterInfo.UpdateSSU2Introducer (h, v4, iTag, iExp))
 625  			UpdateRouterInfo ();
 626  	}
 627  
 628  	void RouterContext::ClearSSU2Introducers (bool v4)
 629  	{
 630  		auto addr = m_RouterInfo.GetSSU2Address (v4);
 631  		if (addr && !addr->ssu->introducers.empty ())
 632  		{
 633  			addr->ssu->introducers.clear ();
 634  			UpdateRouterInfo ();
 635  		}
 636  	}
 637  
 638  	void RouterContext::SetFloodfill (bool floodfill)
 639  	{
 640          if (m_IsFloodfill != floodfill)
 641          {
 642              m_IsFloodfill = floodfill;
 643              auto addresses = m_RouterInfo.GetAddresses ();
 644              if (floodfill)
 645              {
 646                  m_RouterInfo.UpdateFloodfillProperty (true);
 647                  if (addresses)
 648                  {
 649                      // diable introducer for all floodfill's SSU2 addresses
 650                      UpdateSSU2AddressCapsIntroducer ((*addresses)[i2p::data::RouterInfo::eSSU2V4Idx], false);
 651                      UpdateSSU2AddressCapsIntroducer ((*addresses)[i2p::data::RouterInfo::eSSU2V6Idx], false);
 652                  }
 653              }
 654              else
 655              {
 656                  m_RouterInfo.UpdateFloodfillProperty (false);
 657                  // we don't publish number of routers and leaseset for non-floodfill
 658                  m_RouterInfo.DeleteProperty (i2p::data::ROUTER_INFO_PROPERTY_LEASESETS);
 659                  m_RouterInfo.DeleteProperty (i2p::data::ROUTER_INFO_PROPERTY_ROUTERS);
 660                  if (addresses)
 661                  {
 662                      // enable introducers for published non-floodfill's SSU2 addresses
 663                      auto addr = (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx];
 664                      if (addr && addr->published) UpdateSSU2AddressCapsIntroducer (addr, true);
 665                      addr = (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx];
 666                      if (addr && addr->published) UpdateSSU2AddressCapsIntroducer (addr, true);
 667                  }
 668              }
 669              UpdateRouterInfo ();
 670  		}
 671  	}
 672  
 673  	std::string RouterContext::GetFamily () const
 674  	{
 675  		return m_RouterInfo.GetProperty (i2p::data::ROUTER_INFO_PROPERTY_FAMILY);
 676  	}
 677  
 678  	void RouterContext::SetFamily (const std::string& family)
 679  	{
 680  		std::string signature;
 681  		if (family.length () > 0)
 682  			signature = i2p::data::CreateFamilySignature (family, GetIdentHash ());
 683  		if (signature.length () > 0)
 684  		{
 685  			m_RouterInfo.SetProperty (i2p::data::ROUTER_INFO_PROPERTY_FAMILY, family);
 686  			m_RouterInfo.SetProperty (i2p::data::ROUTER_INFO_PROPERTY_FAMILY_SIG, signature);
 687  		}
 688  		else
 689  		{
 690  			m_RouterInfo.DeleteProperty (i2p::data::ROUTER_INFO_PROPERTY_FAMILY);
 691  			m_RouterInfo.DeleteProperty (i2p::data::ROUTER_INFO_PROPERTY_FAMILY_SIG);
 692  		}
 693  	}
 694  
 695  	void RouterContext::SetBandwidth (char L)
 696  	{
 697  		uint32_t limit = 0;
 698  		enum { low, high, extra, unlim } type = high;
 699  		/* detect parameters */
 700  		switch (L)
 701  		{
 702  			case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1   : limit = 12; type = low;   break;
 703  			case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2   : limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low;   break; // 48
 704  			case i2p::data::CAPS_FLAG_LOW_BANDWIDTH3  : limit = 64; type = low;  break;
 705  			case i2p::data::CAPS_FLAG_LOW_BANDWIDTH4  : limit = 128; type = low;  break;
 706  			case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH  : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high;  break; // 256
 707  			case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = i2p::data::EXTRA_BANDWIDTH_LIMIT; type = extra; break; // 2048
 708  			case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s
 709  			default:
 710  				limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; // 48
 711  		}
 712  		/* update caps & flags in RI */
 713  		auto caps = m_RouterInfo.GetCaps ();
 714  		caps &= ~i2p::data::RouterInfo::eHighBandwidth;
 715  		caps &= ~i2p::data::RouterInfo::eExtraBandwidth;
 716  		switch (type)
 717  		{
 718  			case low   : /* not set */; break;
 719  			case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P'
 720  			case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth;
 721  			[[fallthrough]];
 722  			// no break here, extra + high means 'X'
 723  			case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break;
 724  		}
 725  		m_RouterInfo.UpdateCaps (caps);
 726  		UpdateRouterInfo ();
 727  		m_BandwidthLimit = limit;
 728  	}
 729  
 730  	void RouterContext::SetBandwidth (int limit)
 731  	{
 732  		if      (limit > (int)i2p::data::EXTRA_BANDWIDTH_LIMIT) { SetBandwidth('X'); }
 733  		else if (limit > (int)i2p::data::HIGH_BANDWIDTH_LIMIT) { SetBandwidth('P'); }
 734  		else if (limit > 128) { SetBandwidth('O'); }
 735  		else if (limit > 64) { SetBandwidth('N'); }
 736  		else if (limit > (int)i2p::data::LOW_BANDWIDTH_LIMIT) { SetBandwidth('M'); }
 737  		else if (limit > 12) { SetBandwidth('L'); }
 738  		else                   { SetBandwidth('K'); }
 739  
 740  
 741  		LogPrint(eLogInfo, "RouterContext: Set bandwidth ", limit, ". kb/s");
 742  		m_BandwidthLimit = limit; // set precise limit
 743  	}
 744  
 745  	void RouterContext::SetShareRatio (int percents)
 746  	{
 747  		if (percents < 0) percents = 0;
 748  		if (percents > 100) percents = 100;
 749  		m_ShareRatio = percents;
 750  	}
 751  
 752  	bool RouterContext::IsUnreachable () const
 753  	{
 754  		return m_RouterInfo.GetCaps () & i2p::data::RouterInfo::eUnreachable;
 755  	}
 756  
 757  	void RouterContext::SetUnreachable (bool v4, bool v6)
 758  	{
 759  		if (v4 || (v6 && !SupportsV4 ()))
 760  		{
 761  			// set caps
 762  			uint8_t caps = m_RouterInfo.GetCaps ();
 763  			caps &= ~i2p::data::RouterInfo::eReachable;
 764  			caps |= i2p::data::RouterInfo::eUnreachable;
 765  			if (v6 || !SupportsV6 ())
 766  				caps &= ~i2p::data::RouterInfo::eFloodfill;	// can't be floodfill
 767  			m_RouterInfo.UpdateCaps (caps);
 768  		}
 769  		uint16_t port = 0;
 770  		// delete previous introducers
 771  		auto addresses = m_RouterInfo.GetAddresses ();
 772  		if (addresses)
 773  		{
 774  			for (auto& addr : *addresses)
 775  				if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
 776  				{
 777  					addr->published = false;
 778  					UpdateSSU2AddressCapsIntroducer (addr, false); // can't be introducer
 779  					addr->ssu->introducers.clear ();
 780  					port = addr->port;
 781  				}
 782  		}
 783  		// unpublish NTCP2 addreeses
 784  		bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
 785  		if (ntcp2)
 786  		{
 787              int ntcp2version = 2;
 788  #if OPENSSL_PQ
 789              i2p::config::GetOption("ntcp2.version", ntcp2version);
 790  #endif
 791  			PublishNTCP2Address (port, false, v4, v6, false, ntcp2version);
 792  		}
 793  		// update
 794  		m_RouterInfo.UpdateSupportedTransports ();
 795  		UpdateRouterInfo ();
 796  	}
 797  
 798  	void RouterContext::SetReachable (bool v4, bool v6)
 799  	{
 800  		if (v4 || (v6 && !SupportsV4 ()))
 801  		{
 802  			// update caps
 803  			uint8_t caps = m_RouterInfo.GetCaps ();
 804  			caps &= ~i2p::data::RouterInfo::eUnreachable;
 805  			caps |= i2p::data::RouterInfo::eReachable;
 806  			if (m_IsFloodfill)
 807  				caps |= i2p::data::RouterInfo::eFloodfill;
 808  			m_RouterInfo.UpdateCaps (caps);
 809  		}
 810  		uint16_t port = 0;
 811  		// delete previous introducers
 812  		bool isSSU2Published; i2p::config::GetOption ("ssu2.published", isSSU2Published);
 813  		auto addresses = m_RouterInfo.GetAddresses ();
 814  		if (addresses)
 815  		{
 816  			for (auto& addr : *addresses)
 817  				if (addr && addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
 818  				{
 819  					addr->published = true;
 820  					UpdateSSU2AddressCapsIntroducer (addr, !m_IsFloodfill);
 821  					addr->ssu->introducers.clear ();
 822  					if (addr->port) port = addr->port;
 823  				}
 824  		}
 825  		// publish NTCP2
 826  		bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
 827  		if (ntcp2)
 828  		{
 829  			bool published; i2p::config::GetOption ("ntcp2.published", published);
 830  			if (published)
 831  			{
 832  				uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
 833  				if (!ntcp2Port) ntcp2Port = port;
 834                  int ntcp2version = 2;
 835  #if OPENSSL_PQ
 836                  i2p::config::GetOption("ntcp2.version", ntcp2version);
 837  #endif
 838  				PublishNTCP2Address (ntcp2Port, true, v4, v6, false, ntcp2version);
 839  			}
 840  		}
 841  		// update
 842  		m_RouterInfo.UpdateSupportedTransports ();
 843  		UpdateRouterInfo ();
 844  	}
 845  
 846  	void RouterContext::SetSupportsV6 (bool supportsV6)
 847  	{
 848  		if (supportsV6)
 849  		{
 850  			// insert v6 addresses if necessary
 851  			bool foundNTCP2 = false, foundSSU2 = false;
 852  			uint16_t port = 0;
 853  			auto addresses = m_RouterInfo.GetAddresses ();
 854  			if (addresses)
 855  			{
 856  				for (auto& addr: *addresses)
 857  				{
 858  					if (addr && addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
 859  					{
 860  						switch (addr->transportStyle)
 861  						{
 862  							case i2p::data::RouterInfo::eTransportNTCP2:
 863  								foundNTCP2 = true;
 864  							break;
 865  							case i2p::data::RouterInfo::eTransportSSU2:
 866  								foundSSU2 = true;
 867  							break;
 868  							default: ;
 869  						}
 870  					}
 871  					if (addr) port = addr->port;
 872  				}
 873  			}
 874  			if (!port)
 875  			{
 876  				i2p::config::GetOption("port", port);
 877  				if (!port) port = SelectRandomPort ();
 878  			}
 879  			// NTCP2
 880  			bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
 881  			if (ntcp2)
 882  			{
 883  				if (!foundNTCP2)
 884  				{
 885  					uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
 886  					if (!ntcp2Port) ntcp2Port = port;
 887  					bool added = false;
 888  					bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published);
 889  					if (ntcp2Published)
 890  					{
 891  						std::string ntcp2Host;
 892  						if (!i2p::config::IsDefault ("ntcp2.addressv6"))
 893  							i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host);
 894  						else
 895  							i2p::config::GetOption("host", ntcp2Host);
 896  						if (!ntcp2Host.empty () && ntcp2Port)
 897  						{
 898  							auto addr = boost::asio::ip::make_address (ntcp2Host);
 899  							if (addr.is_v6 ())
 900  							{
 901  								m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port);
 902  								added = true;
 903  							}
 904  						}
 905  					}
 906  					if (!added)
 907  						m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::eV6);
 908  				}
 909  			}
 910  			else
 911  				m_RouterInfo.RemoveNTCP2Address (false);
 912  			// SSU2
 913  			bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
 914  			if (ssu2)
 915  			{
 916  				if (!foundSSU2)
 917  				{
 918  					uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
 919  					if (!ssu2Port) ssu2Port = port;
 920  					bool added = false;
 921  					bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published);
 922  					if (ssu2Published && ssu2Port)
 923  					{
 924  						std::string host; i2p::config::GetOption("host", host);
 925  						if (!host.empty ())
 926  						{
 927  						    auto addr = boost::asio::ip::make_address (host);
 928  							if (addr.is_v6 ())
 929  							{
 930  								m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port);
 931  								added = true;
 932  							}
 933  						}
 934  					}
 935  					if (!added)
 936  						m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::eV6);
 937  				}
 938  			}
 939  			else
 940  				m_RouterInfo.RemoveSSU2Address (false);
 941  			if (ntcp2 || ssu2)
 942  				m_RouterInfo.EnableV6 ();
 943  		}
 944  		else
 945  			m_RouterInfo.DisableV6 ();
 946  		UpdateRouterInfo ();
 947  	}
 948  
 949  	void RouterContext::SetSupportsV4 (bool supportsV4)
 950  	{
 951  		if (supportsV4)
 952  		{
 953  			bool foundNTCP2 = false, foundSSU2 = false;
 954  			uint16_t port = 0;
 955  			auto addresses = m_RouterInfo.GetAddresses ();
 956  			if (addresses)
 957  			{
 958  				for (auto& addr: *addresses)
 959  				{
 960  					if (addr && addr->IsV4 ())
 961  					{
 962  						switch (addr->transportStyle)
 963  						{
 964  							case i2p::data::RouterInfo::eTransportNTCP2:
 965  								foundNTCP2 = true;
 966  							break;
 967  							case i2p::data::RouterInfo::eTransportSSU2:
 968  								foundSSU2 = true;
 969  							break;
 970  							default: ;
 971  						}
 972  					}
 973  					if (addr && addr->port) port = addr->port;
 974  				}
 975  			}
 976  			if (!port)
 977  			{
 978  				i2p::config::GetOption("port", port);
 979  				if (!port) port = SelectRandomPort ();
 980  			}
 981  			// NTCP2
 982  			bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
 983  			if (ntcp2)
 984  			{
 985  				if (!foundNTCP2)
 986  				{
 987  					uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
 988  					if (!ntcp2Port) ntcp2Port = port;
 989  					bool added = false;
 990  					bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published);
 991  					if (ntcp2Published && ntcp2Port)
 992  					{
 993  						std::string host; i2p::config::GetOption("host", host);
 994  						if (!host.empty ())
 995  						{
 996  						    auto addr = boost::asio::ip::make_address (host);
 997  							if (addr.is_v4 ())
 998  							{
 999  								m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port);
1000  								added = true;
1001  							}
1002  						}
1003  					}
1004  					if (!added)
1005  						m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::eV4);
1006  				}
1007  			}
1008  			else
1009  				m_RouterInfo.RemoveNTCP2Address (true);
1010  			// SSU2
1011  			bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
1012  			if (ssu2)
1013  			{
1014  				if (!foundSSU2)
1015  				{
1016  					uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
1017  					if (!ssu2Port) ssu2Port = port;
1018  					bool added = false;
1019  					bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published);
1020  					std::string host; i2p::config::GetOption("host", host);
1021  					if (ssu2Published && ssu2Port)
1022  					{
1023  						std::string host; i2p::config::GetOption("host", host);
1024  						if (!host.empty ())
1025  						{
1026  						    auto addr = boost::asio::ip::make_address (host);
1027  							if (addr.is_v4 ())
1028  							{
1029  								m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port);
1030  								added = true;
1031  							}
1032  						}
1033  					}
1034  					if (!added)
1035  						m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::eV4);
1036  				}
1037  			}
1038  			else
1039  				m_RouterInfo.RemoveSSU2Address (true);
1040  			if (ntcp2 || ssu2)
1041  				m_RouterInfo.EnableV4 ();
1042  		}
1043  		else
1044  			m_RouterInfo.DisableV4 ();
1045  		UpdateRouterInfo ();
1046  	}
1047  
1048  	void RouterContext::SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host)
1049  	{
1050  		if (supportsmesh)
1051  		{
1052  			auto addresses = m_RouterInfo.GetAddresses ();
1053  			if (!addresses) return;
1054  			m_RouterInfo.EnableMesh ();
1055  			if ((*addresses)[i2p::data::RouterInfo::eNTCP2V6MeshIdx]) return; // we have mesh address already
1056  			uint16_t port = 0;
1057  			i2p::config::GetOption ("ntcp2.port", port);
1058  			if (!port) i2p::config::GetOption("port", port);
1059  			if (!port)
1060  			{
1061  				for (auto& addr: *addresses)
1062  				{
1063  					if (addr && addr->port)
1064  					{
1065  						port = addr->port;
1066  						break;
1067  					}
1068  				}
1069  			}
1070  			if (!port) port = SelectRandomPort ();
1071  			m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port);
1072  		}
1073  		else
1074  			m_RouterInfo.DisableMesh ();
1075  		UpdateRouterInfo ();
1076  	}
1077  
1078  	void RouterContext::SetMTU (int mtu, bool v4)
1079  	{
1080  		if (mtu < 1280 || mtu > 1500) return;
1081  		auto addresses = m_RouterInfo.GetAddresses ();
1082  		if (!addresses) return;
1083  		for (auto& addr: *addresses)
1084  		{
1085  			if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
1086  			{
1087  				addr->ssu->mtu = mtu;
1088  				LogPrint (eLogDebug, "Router: MTU for ", v4 ? "ipv4" : "ipv6", " address ", addr->host.to_string(), " is set to ", mtu);
1089  			}
1090  		}
1091  	}
1092  
1093  	void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host)
1094  	{
1095  		auto addresses = m_RouterInfo.GetAddresses ();
1096  		if (!addresses) return;
1097  		std::shared_ptr<i2p::data::RouterInfo::Address> addr;
1098  		if (i2p::util::net::IsYggdrasilAddress (host)) // yggdrasil
1099  			addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6MeshIdx];
1100  		else if (host.is_v6 ())
1101  			addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx];
1102  		if (addr && addr->IsPublishedNTCP2 () && addr->host != host)
1103  		{
1104  			addr->host = host;
1105  			UpdateRouterInfo ();
1106  		}
1107  	}
1108  
1109  	void RouterContext::UpdateStats ()
1110  	{
1111  		if (m_IsFloodfill)
1112  		{
1113  			// update routers and leasesets
1114  			m_RouterInfo.SetProperty (i2p::data::ROUTER_INFO_PROPERTY_LEASESETS, std::to_string(i2p::data::netdb.GetNumLeaseSets ()));
1115  			m_RouterInfo.SetProperty (i2p::data::ROUTER_INFO_PROPERTY_ROUTERS,   std::to_string(i2p::data::netdb.GetNumRouters ()));
1116  			UpdateRouterInfo ();
1117  		}
1118  	}
1119  
1120  	void RouterContext::UpdateTimestamp (uint64_t ts)
1121  	{
1122  		if (ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL)
1123  			UpdateRouterInfo ();
1124  	}
1125  
1126  	bool RouterContext::Load ()
1127  	{
1128  		{
1129  			std::ifstream fk (i2p::fs::DataDirPath (ROUTER_KEYS), std::ifstream::in | std::ifstream::binary);
1130  			if (!fk.is_open ())	return false;
1131  			fk.seekg (0, std::ios::end);
1132  			size_t len = fk.tellg();
1133  			fk.seekg (0, std::ios::beg);
1134  
1135  			if (len == sizeof (i2p::data::Keys)) // old keys file format
1136  			{
1137  				i2p::data::Keys keys;
1138  				fk.read ((char *)&keys, sizeof (keys));
1139  				m_Keys = keys;
1140  			}
1141  			else // new keys file format
1142  			{
1143  				uint8_t * buf = new uint8_t[len];
1144  				fk.read ((char *)buf, len);
1145  				m_Keys.FromBuffer (buf, len);
1146  				delete[] buf;
1147  			}
1148  		}
1149  		std::shared_ptr<const i2p::data::IdentityEx> oldIdentity;
1150  		if (m_Keys.GetPublic ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1 ||
1151  			m_Keys.GetPublic ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
1152  		{
1153  			// update keys
1154  			LogPrint (eLogInfo, "Router: router keys are obsolete. Creating new");
1155  			oldIdentity = m_Keys.GetPublic ();
1156  			m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
1157  				i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
1158  			SaveKeys ();
1159  		}
1160  		// read NTCP2 keys if available
1161  		std::ifstream n2k (i2p::fs::DataDirPath (NTCP2_KEYS), std::ifstream::in | std::ifstream::binary);
1162  		if (n2k)
1163  		{
1164  			n2k.seekg (0, std::ios::end);
1165  			size_t len = n2k.tellg();
1166  			n2k.seekg (0, std::ios::beg);
1167  			if (len == sizeof (NTCP2PrivateKeys))
1168  			{
1169  				m_NTCP2Keys.reset (new NTCP2PrivateKeys ());
1170  				n2k.read ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys));
1171  			}
1172  			n2k.close ();
1173  		}
1174  		// read SSU2 keys if available
1175  		std::ifstream s2k (i2p::fs::DataDirPath (SSU2_KEYS), std::ifstream::in | std::ifstream::binary);
1176  		if (s2k)
1177  		{
1178  			s2k.seekg (0, std::ios::end);
1179  			size_t len = s2k.tellg();
1180  			s2k.seekg (0, std::ios::beg);
1181  			if (len == sizeof (SSU2PrivateKeys))
1182  			{
1183  				m_SSU2Keys.reset (new SSU2PrivateKeys ());
1184  				s2k.read ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys));
1185  			}
1186  			s2k.close ();
1187  		}
1188  		// read RouterInfo
1189  		m_RouterInfo.SetRouterIdentity (oldIdentity ? oldIdentity : GetIdentity ());
1190  		i2p::data::RouterInfo routerInfo(i2p::fs::DataDirPath (ROUTER_INFO));
1191  		if (!routerInfo.IsUnreachable ()) // router.info looks good
1192  		{
1193  			m_RouterInfo.Update (routerInfo.GetBuffer (), routerInfo.GetBufferLen ());
1194  			if (oldIdentity)
1195  				m_RouterInfo.SetRouterIdentity (GetIdentity ()); // from new keys
1196  			m_IsFloodfill = m_RouterInfo.IsDeclaredFloodfill ();
1197  			m_RouterInfo.SetProperty ("router.version", I2P_VERSION);
1198  			m_RouterInfo.DeleteProperty ("coreVersion"); // TODO: remove later
1199  		}
1200  		else
1201  		{
1202  			LogPrint (eLogError, ROUTER_INFO, " is malformed. Creating new");
1203  			NewRouterInfo ();
1204  		}
1205  
1206  		if (IsUnreachable ())
1207  			SetReachable (true, true); // we assume reachable until we discover firewall through peer tests
1208  
1209  		bool updated = false;
1210  		// create new NTCP2 keys if required
1211  		bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
1212  		bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
1213  		if ((ntcp2 || ygg) && !m_NTCP2Keys)
1214  		{
1215  			NewNTCP2Keys ();
1216  			UpdateNTCP2Keys ();
1217  			updated = true;
1218  		}
1219  		// create new SSU2 keys if required
1220  		bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
1221  		if (ssu2 && !m_SSU2Keys)
1222  		{
1223  			NewSSU2Keys ();
1224  			UpdateSSU2Keys ();
1225  			updated = true;
1226  		}
1227  		if (m_RouterInfo.UpdateCongestion (i2p::data::RouterInfo::eLowCongestion))
1228  			updated = true;
1229  		if (updated)
1230  			UpdateRouterInfo ();
1231  
1232  		return true;
1233  	}
1234  
1235  	void RouterContext::SaveKeys ()
1236  	{
1237  		// save in the same format as .dat files
1238  		std::ofstream fk (i2p::fs::DataDirPath (ROUTER_KEYS), std::ofstream::binary | std::ofstream::out);
1239  		size_t len = m_Keys.GetFullLen ();
1240  		uint8_t * buf = new uint8_t[len];
1241  		m_Keys.ToBuffer (buf, len);
1242  		fk.write ((char *)buf, len);
1243  		delete[] buf;
1244  	}
1245  
1246  	std::shared_ptr<i2p::tunnel::TunnelPool> RouterContext::GetTunnelPool () const
1247  	{
1248  		return i2p::tunnel::tunnels.GetExploratoryPool ();
1249  	}
1250  
1251  	int RouterContext::GetCongestionLevel (bool longTerm) const
1252  	{
1253  		return std::max (
1254  			i2p::tunnel::tunnels.GetCongestionLevel (),
1255  			i2p::transport::transports.GetCongestionLevel (longTerm)
1256  		);
1257  	}
1258  
1259  	void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len)
1260  	{
1261  		i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len)));
1262  	}
1263  
1264  	bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload,
1265  		size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from)
1266  	{
1267  		if (typeID == eI2NPTunnelTest)
1268  		{
1269  			// try tunnel test
1270  			auto pool = GetTunnelPool ();
1271  			if (pool && pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET)))
1272  				return true;
1273  		}
1274  		auto msg = CreateI2NPMessage (typeID, payload, len, msgID);
1275  		if (!msg) return false;
1276  		i2p::HandleI2NPMessage (msg);
1277  		return true;
1278  	}
1279  
1280  	void RouterContext::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
1281  	{
1282  		if (m_Service)
1283  			boost::asio::post (m_Service->GetService (), std::bind (&RouterContext::PostGarlicMessage, this, msg));
1284  		else
1285  			LogPrint (eLogError, "Router: service is NULL");
1286  	}
1287  
1288  	void RouterContext::PostGarlicMessage (std::shared_ptr<I2NPMessage> msg)
1289  	{
1290  		uint8_t * buf = msg->GetPayload ();
1291  		uint32_t len = bufbe32toh (buf);
1292  		if (len > msg->GetLength ())
1293  		{
1294  			LogPrint (eLogWarning, "Router: garlic message length ", len, " exceeds I2NP message length ", msg->GetLength ());
1295  			return;
1296  		}
1297  		buf += 4;
1298  		if (!HandleECIESx25519TagMessage (buf, len)) // try tag first
1299  		{
1300  			// then Noise_N one-time decryption
1301  			if (m_ECIESSession)
1302  				m_ECIESSession->HandleNextMessage (buf, len);
1303  			else
1304  				LogPrint (eLogError, "Router: Session is not set for ECIES router");
1305  		}
1306  	}
1307  
1308  	void RouterContext::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
1309  	{
1310  		if (m_Service)
1311  			boost::asio::post (m_Service->GetService (), std::bind (&RouterContext::PostDeliveryStatusMessage, this, msg));
1312  		else
1313  			LogPrint (eLogError, "Router: service is NULL");
1314  	}
1315  
1316  	void RouterContext::PostDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
1317  	{
1318  		if (m_PublishReplyToken == bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET))
1319  		{
1320  			LogPrint (eLogInfo, "Router: Publishing confirmed. reply token=", m_PublishReplyToken);
1321  			m_PublishExcluded.clear ();
1322  			m_PublishReplyToken = 0;
1323  			SchedulePublish ();
1324  		}
1325  		else
1326  			i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg);
1327  	}
1328  
1329  	void RouterContext::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag)
1330  	{
1331  		if (m_Service)
1332  		{
1333  			struct
1334  			{
1335  				uint8_t k[32];
1336  				uint64_t t;
1337  			} data;
1338  			memcpy (data.k, key, 32);
1339  			data.t = tag;
1340  			boost::asio::post (m_Service->GetService (), [this,data](void)
1341  				{
1342  					AddECIESx25519Key (data.k, data.t);
1343  				});
1344  		}
1345  		else
1346  			LogPrint (eLogError, "Router: service is NULL");
1347  	}
1348  
1349  	uint32_t RouterContext::GetUptime () const
1350  	{
1351  		return i2p::util::GetMonotonicSeconds () - m_StartupTime;
1352  	}
1353  
1354  	bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const
1355  	{
1356  		return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data) : false;
1357  	}
1358  
1359  	bool RouterContext::DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data)
1360  	{
1361  		return DecryptECIESTunnelBuildRecord (encrypted, data, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE);
1362  	}
1363  
1364  	bool RouterContext::DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize)
1365  	{
1366  		// m_InitialNoiseState is h = SHA256(h || hepk)
1367  		m_CurrentNoiseState = m_InitialNoiseState;
1368  		m_CurrentNoiseState.MixHash (encrypted, 32); // h = SHA256(h || sepk)
1369  		uint8_t sharedSecret[32];
1370  		if (!m_TunnelDecryptor->Decrypt (encrypted, sharedSecret))
1371  		{
1372  			LogPrint (eLogWarning, "Router: Incorrect ephemeral public key");
1373  			return false;
1374  		}
1375  		m_CurrentNoiseState.MixKey (sharedSecret);
1376  		encrypted += 32;
1377  		uint8_t nonce[12];
1378  		memset (nonce, 0, 12);
1379  		if (!i2p::crypto::AEADChaCha20Poly1305 (encrypted, clearTextSize, m_CurrentNoiseState.m_H, 32,
1380  			m_CurrentNoiseState.m_CK + 32, nonce, data, clearTextSize, false)) // decrypt
1381  		{
1382  			LogPrint (eLogWarning, "Router: Tunnel record AEAD decryption failed");
1383  			return false;
1384  		}
1385  		m_CurrentNoiseState.MixHash (encrypted, clearTextSize + 16); // h = SHA256(h || ciphertext)
1386  		return true;
1387  	}
1388  
1389  	bool RouterContext::DecryptTunnelShortRequestRecord (const uint8_t * encrypted, uint8_t * data)
1390  	{
1391  		return DecryptECIESTunnelBuildRecord (encrypted, data, SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE);
1392  	}
1393  
1394  	i2p::crypto::X25519Keys& RouterContext::GetNTCP2StaticKeys ()
1395  	{
1396  		if (!m_NTCP2StaticKeys)
1397  		{
1398  			if (!m_NTCP2Keys) NewNTCP2Keys ();
1399  			auto x = new i2p::crypto::X25519Keys (m_NTCP2Keys->staticPrivateKey, m_NTCP2Keys->staticPublicKey);
1400  			if (!m_NTCP2StaticKeys)
1401  				m_NTCP2StaticKeys.reset (x);
1402  			else
1403  				delete x;
1404  		}
1405  		return *m_NTCP2StaticKeys;
1406  	}
1407  
1408  	i2p::crypto::X25519Keys& RouterContext::GetSSU2StaticKeys ()
1409  	{
1410  		if (!m_SSU2StaticKeys)
1411  		{
1412  			if (!m_SSU2Keys) NewSSU2Keys ();
1413  			auto x = new i2p::crypto::X25519Keys (m_SSU2Keys->staticPrivateKey, m_SSU2Keys->staticPublicKey);
1414  			if (!m_SSU2StaticKeys)
1415  				m_SSU2StaticKeys.reset (x);
1416  			else
1417  				delete x;
1418  		}
1419  		return *m_SSU2StaticKeys;
1420  	}
1421  
1422  	void RouterContext::ScheduleInitialPublish ()
1423  	{
1424  		if (m_PublishTimer)
1425  		{
1426  			m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_INITIAL_PUBLISH_INTERVAL));
1427  			m_PublishTimer->async_wait (std::bind (&RouterContext::HandleInitialPublishTimer,
1428  				this, std::placeholders::_1));
1429  		}
1430  		else
1431  			LogPrint (eLogError, "Router: Publish timer is NULL");
1432  	}
1433  
1434  	void RouterContext::HandleInitialPublishTimer (const boost::system::error_code& ecode)
1435  	{
1436  		if (ecode != boost::asio::error::operation_aborted)
1437  		{
1438  			if (m_RouterInfo.IsReachableBy (i2p::data::RouterInfo::eAllTransports))
1439  			{
1440  				UpdateCongestion ();
1441  				HandlePublishTimer (ecode);
1442  			}
1443  			else
1444  			{
1445  				UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ());
1446  				ScheduleInitialPublish ();
1447  			}
1448  		}
1449  	}
1450  
1451  	void RouterContext::SchedulePublish ()
1452  	{
1453  		if (m_PublishTimer)
1454  		{
1455  			m_PublishTimer->cancel ();
1456  			m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_PUBLISH_INTERVAL +
1457  				GetRng ()() % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE));
1458  			m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishTimer,
1459  				this, std::placeholders::_1));
1460  		}
1461  		else
1462  			LogPrint (eLogError, "Router: Publish timer is NULL");
1463  	}
1464  
1465  	void RouterContext::HandlePublishTimer (const boost::system::error_code& ecode)
1466  	{
1467  		if (ecode != boost::asio::error::operation_aborted)
1468  		{
1469  			UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ());
1470  			if (!m_IsHiddenMode && !IsLimitedConnectivity ())
1471  			{
1472  				m_PublishExcluded.clear ();
1473  				m_PublishReplyToken = 0;
1474  				if (IsFloodfill ())
1475  				{
1476  					UpdateStats (); // for floodfill
1477  					m_PublishExcluded.insert (i2p::context.GetIdentHash ()); // don't publish to ourselves
1478  				}
1479  				Publish ();
1480  				SchedulePublishResend ();
1481  			}
1482  			else
1483  				SchedulePublish ();
1484  		}
1485  	}
1486  
1487  	void RouterContext::Publish ()
1488  	{
1489  		if (!i2p::transport::transports.IsOnline ()) return;
1490  		if (m_PublishExcluded.size () > ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS)
1491  		{
1492  			LogPrint (eLogError, "Router: Couldn't publish our RouterInfo to ", ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS, " closest routers. Try again");
1493  			m_PublishExcluded.clear ();
1494  			UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ());
1495  		}
1496  
1497  		auto floodfill = i2p::data::netdb.GetClosestFloodfill (i2p::context.GetIdentHash (), m_PublishExcluded);
1498  		if (floodfill)
1499  		{
1500  			uint32_t replyToken;
1501  			RAND_bytes ((uint8_t *)&replyToken, 4);
1502  			LogPrint (eLogInfo, "Router: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken);
1503  			auto onDrop = [this]()
1504  				{
1505  					if (m_Service)
1506  						boost::asio::post (m_Service->GetService (), [this]() { HandlePublishResendTimer (boost::system::error_code ()); });
1507  				};
1508  			if (i2p::transport::transports.IsConnected (floodfill->GetIdentHash ()) || // already connected
1509  				(floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) && // are we able to connect
1510  				!IsLimitedConnectivity () && // and not limited connectivity
1511                  !i2p::transport::transports.RoutesRestricted ())) // and routes not restricted
1512  			{
1513  				// send directly
1514  				auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken);
1515  				msg->onDrop = onDrop;
1516  				i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), msg);
1517  			}
1518  			else
1519  			{
1520  				// otherwise through exploratory
1521  				auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
1522  				auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr;
1523  				auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr;
1524  				if (inbound && outbound)
1525  				{
1526  					// encrypt for floodfill
1527  					auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound);
1528  					msg->onDrop = onDrop;
1529  					outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0,
1530  						i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ()));
1531  				}
1532  				else
1533  					LogPrint (eLogInfo, "Router: Can't publish our RouterInfo. No tunnels. Try again in ", ROUTER_INFO_CONFIRMATION_TIMEOUT, " milliseconds");
1534  			}
1535  			m_PublishExcluded.insert (floodfill->GetIdentHash ());
1536  			m_PublishReplyToken = replyToken;
1537  		}
1538  		else
1539  			LogPrint (eLogInfo, "Router: Can't find floodfill to publish our RouterInfo");
1540  	}
1541  
1542  	void RouterContext::SchedulePublishResend ()
1543  	{
1544  		if (m_PublishTimer)
1545  		{
1546  			m_PublishTimer->cancel ();
1547  			m_PublishTimer->expires_from_now (boost::posix_time::milliseconds(ROUTER_INFO_CONFIRMATION_TIMEOUT));
1548  			m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishResendTimer,
1549  				this, std::placeholders::_1));
1550  		}
1551  		else
1552  			LogPrint (eLogError, "Router: Publish timer is NULL");
1553  	}
1554  
1555  	void RouterContext::HandlePublishResendTimer (const boost::system::error_code& ecode)
1556  	{
1557  		if (ecode != boost::asio::error::operation_aborted)
1558  		{
1559  			i2p::context.UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ());
1560  			Publish ();
1561  			SchedulePublishResend ();
1562  		}
1563  	}
1564  
1565  	void RouterContext::ScheduleCongestionUpdate ()
1566  	{
1567  		if (m_CongestionUpdateTimer)
1568  		{
1569  			m_CongestionUpdateTimer->cancel ();
1570  			m_CongestionUpdateTimer->expires_from_now (boost::posix_time::seconds(
1571  				ROUTER_INFO_CONGESTION_UPDATE_INTERVAL + GetRng ()() % ROUTER_INFO_CONGESTION_UPDATE_INTERVAL_VARIANCE));
1572  			m_CongestionUpdateTimer->async_wait (std::bind (&RouterContext::HandleCongestionUpdateTimer,
1573  				this, std::placeholders::_1));
1574  		}
1575  		else
1576  			LogPrint (eLogError, "Router: Congestion update timer is NULL");
1577  	}
1578  
1579  	void RouterContext::HandleCongestionUpdateTimer (const boost::system::error_code& ecode)
1580  	{
1581  		if (ecode != boost::asio::error::operation_aborted)
1582  		{
1583  			UpdateCongestion ();
1584  			ScheduleCongestionUpdate ();
1585  		}
1586  	}
1587  
1588  	void RouterContext::UpdateCongestion ()
1589  	{
1590  		auto c = i2p::data::RouterInfo::eLowCongestion;
1591  		if (!AcceptsTunnels () || !m_ShareRatio)
1592  			c = i2p::data::RouterInfo::eRejectAll;
1593  		else
1594  		{
1595  			int congestionLevel = GetCongestionLevel (true);
1596  			if (congestionLevel > CONGESTION_LEVEL_HIGH)
1597  				c = i2p::data::RouterInfo::eHighCongestion;
1598  			else if (congestionLevel > CONGESTION_LEVEL_MEDIUM)
1599  				c = i2p::data::RouterInfo::eMediumCongestion;
1600  		}
1601  		if (m_RouterInfo.UpdateCongestion (c))
1602  			UpdateRouterInfo ();
1603  	}
1604  
1605  	void RouterContext::ScheduleCleanupTimer ()
1606  	{
1607  		if (m_CleanupTimer)
1608  		{
1609  			m_CleanupTimer->cancel ();
1610  			m_CleanupTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_CLEANUP_INTERVAL));
1611  			m_CleanupTimer->async_wait (std::bind (&RouterContext::HandleCleanupTimer,
1612  				this, std::placeholders::_1));
1613  		}
1614  		else
1615  			LogPrint (eLogError, "Router: Cleanup timer is NULL");
1616  	}
1617  
1618  	void RouterContext::HandleCleanupTimer (const boost::system::error_code& ecode)
1619  	{
1620  		if (ecode != boost::asio::error::operation_aborted)
1621  		{
1622  			CleanupExpiredTags ();
1623  			ScheduleCleanupTimer ();
1624  		}
1625  	}
1626  }