mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 08:30:46 +00:00 
			
		
		
		
	Compare commits
	
		
			20 commits
		
	
	
		
			3a8e30320d
			...
			bd357a2e97
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
							 | 
						bd357a2e97 | ||
| 
							 | 
						29d77113cc | ||
| 
							 | 
						0d09a8be00 | ||
| 
							 | 
						b8d61e04f0 | ||
| 
							 | 
						4432c5a2c4 | ||
| 
							 | 
						2419f52af4 | ||
| 
							 | 
						b2a10ac82b | ||
| 
							 | 
						0086f8e27a | ||
| 
							 | 
						8a8277edda | ||
| 
							 | 
						3f10f6651d | ||
| 
							 | 
						9bc595a9a2 | ||
| 
							 | 
						f04048717d | ||
| 
							 | 
						361f364966 | ||
| 
							 | 
						4c90a88b85 | ||
| 
							 | 
						23e66671c2 | ||
| 
							 | 
						ec67f48d85 | ||
| 
							 | 
						3a229ea65c | ||
| 
							 | 
						0e8d624d86 | ||
| 
							 | 
						8f9874570a | ||
| 
							 | 
						17399da399 | 
					 25 changed files with 258 additions and 316 deletions
				
			
		
							
								
								
									
										13
									
								
								contrib/docker/docker-compose.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								contrib/docker/docker-compose.yml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
services:
 | 
			
		||||
  i2pd:
 | 
			
		||||
    container_name: i2pd2
 | 
			
		||||
    image: purplei2p/i2pd
 | 
			
		||||
    #optional
 | 
			
		||||
    entrypoint: ["./entrypoint.sh", "--loglevel error"]
 | 
			
		||||
    ports:
 | 
			
		||||
      - 127.0.0.1:7656:7656
 | 
			
		||||
      - 127.0.0.1:7070:7070
 | 
			
		||||
      - 127.0.0.1:4444:4444
 | 
			
		||||
    volumes:
 | 
			
		||||
      - /path/to/i2pd/data:/home/i2pd/data                 # make sure data directory and it's contents are owned by 100:65533
 | 
			
		||||
      - /path/to/i2pd/i2pd_certificates:/i2pd_certificates # make sure i2pd_certificates is owned by root:root and 755 permissions on the directory
 | 
			
		||||
| 
						 | 
				
			
			@ -240,17 +240,12 @@ namespace crypto
 | 
			
		|||
// x25519
 | 
			
		||||
	X25519Keys::X25519Keys ()
 | 
			
		||||
	{
 | 
			
		||||
#if OPENSSL_X25519
 | 
			
		||||
		m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
 | 
			
		||||
		m_Pkey = nullptr;
 | 
			
		||||
#else
 | 
			
		||||
		m_Ctx = BN_CTX_new ();
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub)
 | 
			
		||||
	{
 | 
			
		||||
#if OPENSSL_X25519
 | 
			
		||||
		m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
 | 
			
		||||
		m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
 | 
			
		||||
		if (pub)
 | 
			
		||||
| 
						 | 
				
			
			@ -260,29 +255,16 @@ namespace crypto
 | 
			
		|||
			size_t len = 32;
 | 
			
		||||
			EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
 | 
			
		||||
		}
 | 
			
		||||
#else
 | 
			
		||||
		m_Ctx = BN_CTX_new ();
 | 
			
		||||
		memcpy (m_PrivateKey, priv, 32);
 | 
			
		||||
		if (pub)
 | 
			
		||||
			memcpy (m_PublicKey, pub, 32);
 | 
			
		||||
		else
 | 
			
		||||
			GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	X25519Keys::~X25519Keys ()
 | 
			
		||||
	{
 | 
			
		||||
#if OPENSSL_X25519
 | 
			
		||||
		EVP_PKEY_CTX_free (m_Ctx);
 | 
			
		||||
		if (m_Pkey) EVP_PKEY_free (m_Pkey);
 | 
			
		||||
#else
 | 
			
		||||
		BN_CTX_free (m_Ctx);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void X25519Keys::GenerateKeys ()
 | 
			
		||||
	{
 | 
			
		||||
#if OPENSSL_X25519
 | 
			
		||||
		if (m_Pkey)
 | 
			
		||||
		{
 | 
			
		||||
			EVP_PKEY_free (m_Pkey);
 | 
			
		||||
| 
						 | 
				
			
			@ -294,16 +276,11 @@ namespace crypto
 | 
			
		|||
		m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx?
 | 
			
		||||
		size_t len = 32;
 | 
			
		||||
		EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
 | 
			
		||||
#else
 | 
			
		||||
		RAND_bytes (m_PrivateKey, 32);
 | 
			
		||||
		GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
 | 
			
		||||
	{
 | 
			
		||||
		if (!pub || (pub[31] & 0x80)) return false; // not x25519 key
 | 
			
		||||
#if OPENSSL_X25519
 | 
			
		||||
		EVP_PKEY_derive_init (m_Ctx);
 | 
			
		||||
		auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
 | 
			
		||||
		if (!pkey) return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -311,25 +288,17 @@ namespace crypto
 | 
			
		|||
		size_t len = 32;
 | 
			
		||||
		EVP_PKEY_derive (m_Ctx, shared, &len);
 | 
			
		||||
		EVP_PKEY_free (pkey);
 | 
			
		||||
#else
 | 
			
		||||
		GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx);
 | 
			
		||||
#endif
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void X25519Keys::GetPrivateKey (uint8_t * priv) const
 | 
			
		||||
	{
 | 
			
		||||
#if OPENSSL_X25519
 | 
			
		||||
		size_t len = 32;
 | 
			
		||||
		EVP_PKEY_get_raw_private_key (m_Pkey, priv, &len);
 | 
			
		||||
#else
 | 
			
		||||
		memcpy (priv, m_PrivateKey, 32);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void X25519Keys::SetPrivateKey (const uint8_t * priv, bool calculatePublic)
 | 
			
		||||
	{
 | 
			
		||||
#if OPENSSL_X25519
 | 
			
		||||
		if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx);
 | 
			
		||||
		if (m_Pkey) EVP_PKEY_free (m_Pkey);
 | 
			
		||||
		m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
 | 
			
		||||
| 
						 | 
				
			
			@ -339,11 +308,6 @@ namespace crypto
 | 
			
		|||
			size_t len = 32;
 | 
			
		||||
			EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
 | 
			
		||||
		}
 | 
			
		||||
#else
 | 
			
		||||
		memcpy (m_PrivateKey, priv, 32);
 | 
			
		||||
		if (calculatePublic)
 | 
			
		||||
			GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
// ElGamal
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,6 @@
 | 
			
		|||
#if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
 | 
			
		||||
#	define OPENSSL_HKDF 1
 | 
			
		||||
#	define OPENSSL_EDDSA 1
 | 
			
		||||
#	define OPENSSL_X25519 1
 | 
			
		||||
#	if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL
 | 
			
		||||
#		define OPENSSL_SIPHASH 1
 | 
			
		||||
#	endif
 | 
			
		||||
| 
						 | 
				
			
			@ -70,13 +69,8 @@ namespace crypto
 | 
			
		|||
		private:
 | 
			
		||||
 | 
			
		||||
			uint8_t m_PublicKey[32];
 | 
			
		||||
#if OPENSSL_X25519
 | 
			
		||||
			EVP_PKEY_CTX * m_Ctx;
 | 
			
		||||
			EVP_PKEY * m_Pkey;
 | 
			
		||||
#else
 | 
			
		||||
			BN_CTX * m_Ctx;
 | 
			
		||||
			uint8_t m_PrivateKey[32];
 | 
			
		||||
#endif
 | 
			
		||||
			bool m_IsElligatorIneligible = false; // true if definitely ineligible
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2013-2023, The PurpleI2P Project
 | 
			
		||||
* Copyright (c) 2013-2024, The PurpleI2P Project
 | 
			
		||||
*
 | 
			
		||||
* This file is part of Purple i2pd project and licensed under BSD3
 | 
			
		||||
*
 | 
			
		||||
| 
						 | 
				
			
			@ -457,86 +457,6 @@ namespace crypto
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if !OPENSSL_X25519
 | 
			
		||||
	BIGNUM * Ed25519::ScalarMul (const BIGNUM * u, const BIGNUM * k, BN_CTX * ctx) const
 | 
			
		||||
	{
 | 
			
		||||
		BN_CTX_start (ctx);
 | 
			
		||||
		auto x1 = BN_CTX_get (ctx); BN_copy (x1, u);
 | 
			
		||||
		auto x2 = BN_CTX_get (ctx); BN_one (x2);
 | 
			
		||||
		auto z2 = BN_CTX_get (ctx); BN_zero (z2);
 | 
			
		||||
		auto x3 = BN_CTX_get (ctx); BN_copy (x3, u);
 | 
			
		||||
		auto z3 = BN_CTX_get (ctx); BN_one (z3);
 | 
			
		||||
		auto c121666 = BN_CTX_get (ctx); BN_set_word (c121666, 121666);
 | 
			
		||||
		auto tmp0 = BN_CTX_get (ctx); auto tmp1 = BN_CTX_get (ctx);
 | 
			
		||||
		unsigned int swap = 0;
 | 
			
		||||
		auto bits = BN_num_bits (k);
 | 
			
		||||
		while(bits)
 | 
			
		||||
		{
 | 
			
		||||
			--bits;
 | 
			
		||||
			auto k_t = BN_is_bit_set(k, bits) ? 1 : 0;
 | 
			
		||||
			swap ^= k_t;
 | 
			
		||||
			if (swap)
 | 
			
		||||
			{
 | 
			
		||||
				std::swap (x2, x3);
 | 
			
		||||
				std::swap (z2, z3);
 | 
			
		||||
			}
 | 
			
		||||
			swap = k_t;
 | 
			
		||||
			BN_mod_sub(tmp0, x3, z3, q, ctx);
 | 
			
		||||
			BN_mod_sub(tmp1, x2, z2, q, ctx);
 | 
			
		||||
			BN_mod_add(x2, x2, z2, q, ctx);
 | 
			
		||||
			BN_mod_add(z2, x3, z3, q, ctx);
 | 
			
		||||
			BN_mod_mul(z3, tmp0, x2, q, ctx);
 | 
			
		||||
			BN_mod_mul(z2, z2, tmp1, q, ctx);
 | 
			
		||||
			BN_mod_sqr(tmp0, tmp1, q, ctx);
 | 
			
		||||
			BN_mod_sqr(tmp1, x2, q, ctx);
 | 
			
		||||
			BN_mod_add(x3, z3, z2, q, ctx);
 | 
			
		||||
			BN_mod_sub(z2, z3, z2, q, ctx);
 | 
			
		||||
			BN_mod_mul(x2, tmp1, tmp0, q, ctx);
 | 
			
		||||
			BN_mod_sub(tmp1, tmp1, tmp0, q, ctx);
 | 
			
		||||
			BN_mod_sqr(z2, z2, q, ctx);
 | 
			
		||||
			BN_mod_mul(z3, tmp1, c121666, q, ctx);
 | 
			
		||||
			BN_mod_sqr(x3, x3, q, ctx);
 | 
			
		||||
			BN_mod_add(tmp0, tmp0, z3, q, ctx);
 | 
			
		||||
			BN_mod_mul(z3, x1, z2, q, ctx);
 | 
			
		||||
			BN_mod_mul(z2, tmp1, tmp0, q, ctx);
 | 
			
		||||
		}
 | 
			
		||||
		if (swap)
 | 
			
		||||
		{
 | 
			
		||||
			std::swap (x2, x3);
 | 
			
		||||
			std::swap (z2, z3);
 | 
			
		||||
		}
 | 
			
		||||
		BN_mod_inverse (z2, z2, q, ctx);
 | 
			
		||||
		BIGNUM * res = BN_new (); // not from ctx
 | 
			
		||||
		BN_mod_mul(res, x2, z2, q, ctx);
 | 
			
		||||
		BN_CTX_end (ctx);
 | 
			
		||||
		return res;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Ed25519::ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
 | 
			
		||||
	{
 | 
			
		||||
		BIGNUM * p1 = DecodeBN<32> (p);
 | 
			
		||||
		uint8_t k[32];
 | 
			
		||||
		memcpy (k, e, 32);
 | 
			
		||||
		k[0] &= 248; k[31] &= 127; k[31] |= 64;
 | 
			
		||||
		BIGNUM * n = DecodeBN<32> (k);
 | 
			
		||||
		BIGNUM * q1 = ScalarMul (p1, n, ctx);
 | 
			
		||||
		EncodeBN (q1, buf, 32);
 | 
			
		||||
		BN_free (p1); BN_free (n); BN_free (q1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Ed25519::ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
 | 
			
		||||
	{
 | 
			
		||||
		BIGNUM *p1 = BN_new (); BN_set_word (p1, 9);
 | 
			
		||||
		uint8_t k[32];
 | 
			
		||||
		memcpy (k, e, 32);
 | 
			
		||||
		k[0] &= 248; k[31] &= 127; k[31] |= 64;
 | 
			
		||||
		BIGNUM * n = DecodeBN<32> (k);
 | 
			
		||||
		BIGNUM * q1 = ScalarMul (p1, n, ctx);
 | 
			
		||||
		EncodeBN (q1, buf, 32);
 | 
			
		||||
		BN_free (p1); BN_free (n); BN_free (q1);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	void Ed25519::BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded)
 | 
			
		||||
	{
 | 
			
		||||
		BN_CTX * ctx = BN_CTX_new ();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2013-2020, The PurpleI2P Project
 | 
			
		||||
* Copyright (c) 2013-2024, The PurpleI2P Project
 | 
			
		||||
*
 | 
			
		||||
* This file is part of Purple i2pd project and licensed under BSD3
 | 
			
		||||
*
 | 
			
		||||
| 
						 | 
				
			
			@ -84,10 +84,7 @@ namespace crypto
 | 
			
		|||
			EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const;
 | 
			
		||||
			EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
 | 
			
		||||
			void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
 | 
			
		||||
#if !OPENSSL_X25519
 | 
			
		||||
			void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
 | 
			
		||||
			void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			void BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
 | 
			
		||||
			void BlindPrivateKey (const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -115,11 +112,6 @@ namespace crypto
 | 
			
		|||
			BIGNUM * DecodeBN (const uint8_t * buf) const;
 | 
			
		||||
			void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const;
 | 
			
		||||
 | 
			
		||||
#if !OPENSSL_X25519
 | 
			
		||||
			// for x25519
 | 
			
		||||
			BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			BIGNUM * q, * l, * d, * I;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,6 +103,7 @@ namespace http
 | 
			
		|||
 | 
			
		||||
	bool URL::parse(std::string_view url) 
 | 
			
		||||
	{
 | 
			
		||||
		if (url.empty ()) return false;
 | 
			
		||||
		std::size_t pos_p = 0; /* < current parse position */
 | 
			
		||||
		std::size_t pos_c = 0; /* < work position */
 | 
			
		||||
		if(url.at(0) != '/' || pos_p > 0) 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -375,6 +375,8 @@ namespace transport
 | 
			
		|||
			m_Socket.close ();
 | 
			
		||||
			transports.PeerDisconnected (shared_from_this ());
 | 
			
		||||
			m_Server.RemoveNTCP2Session (shared_from_this ());
 | 
			
		||||
			if (!m_IntermediateQueue.empty ())
 | 
			
		||||
				m_SendQueue.splice (m_SendQueue.end (), m_IntermediateQueue);
 | 
			
		||||
			for (auto& it: m_SendQueue)
 | 
			
		||||
				it->Drop ();
 | 
			
		||||
			m_SendQueue.clear ();
 | 
			
		||||
| 
						 | 
				
			
			@ -1207,7 +1209,7 @@ namespace transport
 | 
			
		|||
	void NTCP2Session::MoveSendQueue (std::shared_ptr<NTCP2Session> other)
 | 
			
		||||
	{
 | 
			
		||||
		if (!other || m_SendQueue.empty ()) return;
 | 
			
		||||
		std::vector<std::shared_ptr<I2NPMessage> > msgs;
 | 
			
		||||
		std::list<std::shared_ptr<I2NPMessage> > msgs;
 | 
			
		||||
		auto ts = i2p::util::GetMillisecondsSinceEpoch ();
 | 
			
		||||
		for (auto it: m_SendQueue)
 | 
			
		||||
			if (!it->IsExpired (ts))
 | 
			
		||||
| 
						 | 
				
			
			@ -1216,7 +1218,7 @@ namespace transport
 | 
			
		|||
				it->Drop ();
 | 
			
		||||
		m_SendQueue.clear ();
 | 
			
		||||
		if (!msgs.empty ())
 | 
			
		||||
			other->PostI2NPMessages (msgs);
 | 
			
		||||
			other->SendI2NPMessages (msgs);
 | 
			
		||||
	}	
 | 
			
		||||
		
 | 
			
		||||
	size_t NTCP2Session::CreatePaddingBlock (size_t msgLen, uint8_t * buf, size_t len)
 | 
			
		||||
| 
						 | 
				
			
			@ -1297,20 +1299,42 @@ namespace transport
 | 
			
		|||
		m_Server.GetService ().post (std::bind (&NTCP2Session::Terminate, shared_from_this ())); // let termination message go
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void NTCP2Session::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
 | 
			
		||||
	void NTCP2Session::SendI2NPMessages (std::list<std::shared_ptr<I2NPMessage> >& msgs)
 | 
			
		||||
	{
 | 
			
		||||
		m_Server.GetService ().post (std::bind (&NTCP2Session::PostI2NPMessages, shared_from_this (), msgs));
 | 
			
		||||
		if (m_IsTerminated || msgs.empty ()) 
 | 
			
		||||
		{
 | 
			
		||||
			msgs.clear ();
 | 
			
		||||
			return;
 | 
			
		||||
		}	
 | 
			
		||||
		bool empty = false;
 | 
			
		||||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> l(m_IntermediateQueueMutex);
 | 
			
		||||
			empty = m_IntermediateQueue.empty ();
 | 
			
		||||
			m_IntermediateQueue.splice (m_IntermediateQueue.end (), msgs);
 | 
			
		||||
		}
 | 
			
		||||
		if (empty)
 | 
			
		||||
			m_Server.GetService ().post (std::bind (&NTCP2Session::PostI2NPMessages, shared_from_this ()));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void NTCP2Session::PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs)
 | 
			
		||||
	void NTCP2Session::PostI2NPMessages ()
 | 
			
		||||
	{
 | 
			
		||||
		if (m_IsTerminated) return;
 | 
			
		||||
		std::list<std::shared_ptr<I2NPMessage> > msgs;
 | 
			
		||||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> l(m_IntermediateQueueMutex);
 | 
			
		||||
			m_IntermediateQueue.swap (msgs);		
 | 
			
		||||
		}	
 | 
			
		||||
		bool isSemiFull = m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE/2;
 | 
			
		||||
		for (auto it: msgs)
 | 
			
		||||
			if (isSemiFull && it->onDrop)
 | 
			
		||||
				it->Drop (); // drop earlier because we can handle it
 | 
			
		||||
			else
 | 
			
		||||
				m_SendQueue.push_back (std::move (it));
 | 
			
		||||
		if (isSemiFull)
 | 
			
		||||
		{	
 | 
			
		||||
			for (auto it: msgs)
 | 
			
		||||
				if (it->onDrop)
 | 
			
		||||
					it->Drop (); // drop earlier because we can handle it
 | 
			
		||||
				else
 | 
			
		||||
					m_SendQueue.push_back (std::move (it));
 | 
			
		||||
		}	
 | 
			
		||||
		else
 | 
			
		||||
			m_SendQueue.splice (m_SendQueue.end (), msgs);
 | 
			
		||||
		
 | 
			
		||||
		if (!m_IsSending && m_IsEstablished)
 | 
			
		||||
			SendQueue ();
 | 
			
		||||
| 
						 | 
				
			
			@ -1822,7 +1846,7 @@ namespace transport
 | 
			
		|||
							LogPrint(eLogError, "NTCP2: HTTP proxy write error ", ec.message());
 | 
			
		||||
					});
 | 
			
		||||
 | 
			
		||||
				boost::asio::streambuf * readbuff = new boost::asio::streambuf;
 | 
			
		||||
				auto readbuff = std::make_shared<boost::asio::streambuf>();
 | 
			
		||||
				boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n",
 | 
			
		||||
					[readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred)
 | 
			
		||||
					{
 | 
			
		||||
| 
						 | 
				
			
			@ -1842,7 +1866,6 @@ namespace transport
 | 
			
		|||
								{
 | 
			
		||||
									timer->cancel();
 | 
			
		||||
									conn->ClientLogin();
 | 
			
		||||
									delete readbuff;
 | 
			
		||||
									return;
 | 
			
		||||
								}
 | 
			
		||||
								else
 | 
			
		||||
| 
						 | 
				
			
			@ -1852,7 +1875,6 @@ namespace transport
 | 
			
		|||
								LogPrint(eLogError, "NTCP2: HTTP proxy gave malformed response");
 | 
			
		||||
							timer->cancel();
 | 
			
		||||
							conn->Terminate();
 | 
			
		||||
							delete readbuff;
 | 
			
		||||
						}
 | 
			
		||||
					});
 | 
			
		||||
				break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ namespace transport
 | 
			
		|||
			void ServerLogin (); // Bob
 | 
			
		||||
 | 
			
		||||
			void SendLocalRouterInfo (bool update) override; // after handshake or by update
 | 
			
		||||
			void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override;
 | 
			
		||||
			void SendI2NPMessages (std::list<std::shared_ptr<I2NPMessage> >& msgs) override;
 | 
			
		||||
			void MoveSendQueue (std::shared_ptr<NTCP2Session> other);
 | 
			
		||||
			
 | 
			
		||||
		private:
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +196,7 @@ namespace transport
 | 
			
		|||
			void SendRouterInfo ();
 | 
			
		||||
			void SendTermination (NTCP2TerminationReason reason);
 | 
			
		||||
			void SendTerminationAndTerminate (NTCP2TerminationReason reason);
 | 
			
		||||
			void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
 | 
			
		||||
			void PostI2NPMessages ();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -229,7 +229,10 @@ namespace transport
 | 
			
		|||
			bool m_IsSending, m_IsReceiving;
 | 
			
		||||
			std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
 | 
			
		||||
			uint64_t m_NextRouterInfoResendTime; // seconds since epoch
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
			std::list<std::shared_ptr<I2NPMessage> > m_IntermediateQueue; // from transports
 | 
			
		||||
			mutable std::mutex m_IntermediateQueueMutex;
 | 
			
		||||
			
 | 
			
		||||
			uint16_t m_PaddingSizes[16];
 | 
			
		||||
			int m_NextPaddingSize;
 | 
			
		||||
	};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -480,7 +480,7 @@ namespace data
 | 
			
		|||
	void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
 | 
			
		||||
	{
 | 
			
		||||
		LogPrint(eLogInfo, "NetDB: Reseeding from floodfill ", ri.GetIdentHashBase64());
 | 
			
		||||
		std::vector<std::shared_ptr<i2p::I2NPMessage> > requests;
 | 
			
		||||
		std::list<std::shared_ptr<i2p::I2NPMessage> > requests;
 | 
			
		||||
 | 
			
		||||
		i2p::data::IdentHash ourIdent = i2p::context.GetIdentHash();
 | 
			
		||||
		i2p::data::IdentHash ih = ri.GetIdentHash();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,7 +111,6 @@ namespace transport
 | 
			
		|||
					SendPeerTest (7, buf + offset, len - offset);
 | 
			
		||||
				else
 | 
			
		||||
					LogPrint (eLogWarning, "SSU2: Unknown address for peer test 6");
 | 
			
		||||
				GetServer ().AddConnectedRecently (GetRemoteEndpoint (), i2p::util::GetSecondsSinceEpoch ());
 | 
			
		||||
				GetServer ().RequestRemoveSession (GetConnID ());
 | 
			
		||||
				break;
 | 
			
		||||
			}			
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +140,6 @@ namespace transport
 | 
			
		|||
						}
 | 
			
		||||
					}	
 | 
			
		||||
				}	
 | 
			
		||||
				GetServer ().AddConnectedRecently (GetRemoteEndpoint (), i2p::util::GetSecondsSinceEpoch ());
 | 
			
		||||
				GetServer ().RequestRemoveSession (GetConnID ());	
 | 
			
		||||
				break;
 | 
			
		||||
			}	
 | 
			
		||||
| 
						 | 
				
			
			@ -188,6 +186,7 @@ namespace transport
 | 
			
		|||
		i2p::crypto::ChaCha20 (h + 16, 16, addr->i, n, h + 16);
 | 
			
		||||
		// send
 | 
			
		||||
		GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, GetRemoteEndpoint ());
 | 
			
		||||
		UpdateNumSentBytes (payloadSize + 32);
 | 
			
		||||
	}	
 | 
			
		||||
 | 
			
		||||
	void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, bool delayed)
 | 
			
		||||
| 
						 | 
				
			
			@ -309,6 +308,7 @@ namespace transport
 | 
			
		|||
		i2p::crypto::ChaCha20 (h + 16, 16, addr->i, n, h + 16);
 | 
			
		||||
		// send
 | 
			
		||||
		GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep);
 | 
			
		||||
		UpdateNumSentBytes (payloadSize + 32);
 | 
			
		||||
	}	
 | 
			
		||||
 | 
			
		||||
	void SSU2HolePunchSession::SendHolePunch (const uint8_t * relayResponseBlock, size_t relayResponseBlockLen)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -293,6 +293,8 @@ namespace transport
 | 
			
		|||
			m_SentHandshakePacket.reset (nullptr);
 | 
			
		||||
			m_SessionConfirmedFragment.reset (nullptr);
 | 
			
		||||
			m_PathChallenge.reset (nullptr);
 | 
			
		||||
			if (!m_IntermediateQueue.empty ())
 | 
			
		||||
				m_SendQueue.splice (m_SendQueue.end (), m_IntermediateQueue);
 | 
			
		||||
			for (auto& it: m_SendQueue)
 | 
			
		||||
				it->Drop ();
 | 
			
		||||
			m_SendQueue.clear ();
 | 
			
		||||
| 
						 | 
				
			
			@ -372,14 +374,31 @@ namespace transport
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void SSU2Session::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
 | 
			
		||||
	void SSU2Session::SendI2NPMessages (std::list<std::shared_ptr<I2NPMessage> >& msgs)
 | 
			
		||||
	{
 | 
			
		||||
		m_Server.GetService ().post (std::bind (&SSU2Session::PostI2NPMessages, shared_from_this (), msgs));
 | 
			
		||||
		if (m_State == eSSU2SessionStateTerminated || msgs.empty ()) 
 | 
			
		||||
		{
 | 
			
		||||
			msgs.clear ();
 | 
			
		||||
			return;
 | 
			
		||||
		}	
 | 
			
		||||
		bool empty = false;
 | 
			
		||||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> l(m_IntermediateQueueMutex);
 | 
			
		||||
			empty = m_IntermediateQueue.empty ();
 | 
			
		||||
			m_IntermediateQueue.splice (m_IntermediateQueue.end (), msgs);
 | 
			
		||||
		}
 | 
			
		||||
		if (empty)
 | 
			
		||||
			m_Server.GetService ().post (std::bind (&SSU2Session::PostI2NPMessages, shared_from_this ()));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void SSU2Session::PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs)
 | 
			
		||||
	void SSU2Session::PostI2NPMessages ()
 | 
			
		||||
	{
 | 
			
		||||
		if (m_State == eSSU2SessionStateTerminated) return;
 | 
			
		||||
		std::list<std::shared_ptr<I2NPMessage> > msgs;
 | 
			
		||||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> l(m_IntermediateQueueMutex);
 | 
			
		||||
			m_IntermediateQueue.swap (msgs);		
 | 
			
		||||
		}	
 | 
			
		||||
		uint64_t mts = i2p::util::GetMonotonicMicroseconds ();
 | 
			
		||||
		bool isSemiFull = false;
 | 
			
		||||
		if (m_SendQueue.size ())
 | 
			
		||||
| 
						 | 
				
			
			@ -393,16 +412,24 @@ namespace transport
 | 
			
		|||
					" is semi-full (size = ", m_SendQueue.size (), ", lag = ", queueLag / 1000, ", rtt = ", (int)m_RTT, ")");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		for (auto it: msgs)
 | 
			
		||||
		{
 | 
			
		||||
			if (isSemiFull && it->onDrop)
 | 
			
		||||
				it->Drop (); // drop earlier because we can handle it
 | 
			
		||||
			else
 | 
			
		||||
		if (isSemiFull)
 | 
			
		||||
		{	
 | 
			
		||||
			for (auto it: msgs)
 | 
			
		||||
			{
 | 
			
		||||
				it->SetEnqueueTime (mts);
 | 
			
		||||
				m_SendQueue.push_back (std::move (it));
 | 
			
		||||
				if (it->onDrop)
 | 
			
		||||
					it->Drop (); // drop earlier because we can handle it
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					it->SetEnqueueTime (mts);
 | 
			
		||||
					m_SendQueue.push_back (std::move (it));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		}	
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			for (auto& it: msgs) it->SetEnqueueTime (mts);
 | 
			
		||||
			m_SendQueue.splice (m_SendQueue.end (), msgs);
 | 
			
		||||
		}	
 | 
			
		||||
		if (IsEstablished ())
 | 
			
		||||
		{	
 | 
			
		||||
			SendQueue ();
 | 
			
		||||
| 
						 | 
				
			
			@ -415,7 +442,7 @@ namespace transport
 | 
			
		|||
	void SSU2Session::MoveSendQueue (std::shared_ptr<SSU2Session> other)
 | 
			
		||||
	{
 | 
			
		||||
		if (!other || m_SendQueue.empty ()) return;
 | 
			
		||||
		std::vector<std::shared_ptr<I2NPMessage> > msgs;
 | 
			
		||||
		std::list<std::shared_ptr<I2NPMessage> > msgs;
 | 
			
		||||
		auto ts = i2p::util::GetMillisecondsSinceEpoch ();
 | 
			
		||||
		for (auto it: m_SendQueue)
 | 
			
		||||
			if (!it->IsExpired (ts))
 | 
			
		||||
| 
						 | 
				
			
			@ -424,7 +451,7 @@ namespace transport
 | 
			
		|||
				it->Drop ();
 | 
			
		||||
		m_SendQueue.clear ();
 | 
			
		||||
		if (!msgs.empty ())
 | 
			
		||||
			other->PostI2NPMessages (msgs);
 | 
			
		||||
			other->SendI2NPMessages (msgs);
 | 
			
		||||
	}	
 | 
			
		||||
		
 | 
			
		||||
	bool SSU2Session::SendQueue ()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -261,7 +261,7 @@ namespace transport
 | 
			
		|||
			void FlushData ();
 | 
			
		||||
			void Done () override;
 | 
			
		||||
			void SendLocalRouterInfo (bool update) override;
 | 
			
		||||
			void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override;
 | 
			
		||||
			void SendI2NPMessages (std::list<std::shared_ptr<I2NPMessage> >& msgs) override;
 | 
			
		||||
			void MoveSendQueue (std::shared_ptr<SSU2Session> other);
 | 
			
		||||
			uint32_t GetRelayTag () const override { return m_RelayTag; };
 | 
			
		||||
			size_t Resend (uint64_t ts); // return number of resent packets
 | 
			
		||||
| 
						 | 
				
			
			@ -307,7 +307,7 @@ namespace transport
 | 
			
		|||
			void Established ();
 | 
			
		||||
			void ScheduleConnectTimer ();
 | 
			
		||||
			void HandleConnectTimer (const boost::system::error_code& ecode);
 | 
			
		||||
			void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
 | 
			
		||||
			void PostI2NPMessages ();
 | 
			
		||||
			bool SendQueue (); // returns true if ack block was sent
 | 
			
		||||
			bool SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg);
 | 
			
		||||
			void ResendHandshakePacket ();
 | 
			
		||||
| 
						 | 
				
			
			@ -381,6 +381,8 @@ namespace transport
 | 
			
		|||
			std::unordered_map<uint32_t, std::pair <std::shared_ptr<SSU2Session>, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice
 | 
			
		||||
			std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
 | 
			
		||||
			i2p::I2NPMessagesHandler m_Handler;
 | 
			
		||||
			std::list<std::shared_ptr<I2NPMessage> > m_IntermediateQueue; // from transports
 | 
			
		||||
			mutable std::mutex m_IntermediateQueueMutex;
 | 
			
		||||
			bool m_IsDataReceived;
 | 
			
		||||
			double m_RTT;
 | 
			
		||||
			int m_MsgLocalExpirationTimeout;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1276,10 +1276,12 @@ namespace stream
 | 
			
		|||
							else
 | 
			
		||||
								m_WindowSize += (m_WindowSize - (1 - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowSize;
 | 
			
		||||
							if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE;
 | 
			
		||||
							m_WindowIncCounter --;
 | 
			
		||||
							UpdatePacingTime ();
 | 
			
		||||
							m_WindowIncCounter--;
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
							break;
 | 
			
		||||
					}
 | 
			
		||||
					UpdatePacingTime ();
 | 
			
		||||
				}
 | 
			
		||||
				if (m_IsNAcked)
 | 
			
		||||
					ResendPacket ();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2013-2022, The PurpleI2P Project
 | 
			
		||||
* Copyright (c) 2013-2024, The PurpleI2P Project
 | 
			
		||||
*
 | 
			
		||||
* This file is part of Purple i2pd project and licensed under BSD3
 | 
			
		||||
*
 | 
			
		||||
| 
						 | 
				
			
			@ -59,8 +59,7 @@ namespace tunnel
 | 
			
		|||
			auto num = m_TunnelDataMsgs.size ();
 | 
			
		||||
			if (num > 1)
 | 
			
		||||
				LogPrint (eLogDebug, "TransitTunnel: ", GetTunnelID (), "->", GetNextTunnelID (), " ", num);
 | 
			
		||||
			i2p::transport::transports.SendMessages (GetNextIdentHash (), m_TunnelDataMsgs);
 | 
			
		||||
			m_TunnelDataMsgs.clear ();
 | 
			
		||||
			i2p::transport::transports.SendMessages (GetNextIdentHash (), m_TunnelDataMsgs); // send and clear
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2013-2023, The PurpleI2P Project
 | 
			
		||||
* Copyright (c) 2013-2024, The PurpleI2P Project
 | 
			
		||||
*
 | 
			
		||||
* This file is part of Purple i2pd project and licensed under BSD3
 | 
			
		||||
*
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
#define TRANSIT_TUNNEL_H__
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include "Crypto.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ namespace tunnel
 | 
			
		|||
		private:
 | 
			
		||||
 | 
			
		||||
			size_t m_NumTransmittedBytes;
 | 
			
		||||
			std::vector<std::shared_ptr<i2p::I2NPMessage> > m_TunnelDataMsgs;
 | 
			
		||||
			std::list<std::shared_ptr<i2p::I2NPMessage> > m_TunnelDataMsgs;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class TransitTunnelGateway: public TransitTunnel
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -144,8 +144,12 @@ namespace transport
 | 
			
		|||
			void SetLastActivityTimestamp (uint64_t ts) { m_LastActivityTimestamp = ts; };
 | 
			
		||||
			
 | 
			
		||||
			virtual uint32_t GetRelayTag () const { return 0; };
 | 
			
		||||
			virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
 | 
			
		||||
			virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
 | 
			
		||||
			virtual void SendLocalRouterInfo (bool update = false) 
 | 
			
		||||
			{
 | 
			
		||||
				std::list<std::shared_ptr<I2NPMessage> > msgs{ CreateDatabaseStoreMsg () };
 | 
			
		||||
				SendI2NPMessages (msgs); 
 | 
			
		||||
			};
 | 
			
		||||
			virtual void SendI2NPMessages (std::list<std::shared_ptr<I2NPMessage> >& msgs) = 0;
 | 
			
		||||
			virtual bool IsEstablished () const = 0;
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ namespace transport
 | 
			
		|||
{
 | 
			
		||||
	template<typename Keys>
 | 
			
		||||
	EphemeralKeysSupplier<Keys>::EphemeralKeysSupplier (int size):
 | 
			
		||||
		m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr)
 | 
			
		||||
		m_QueueSize (size), m_IsRunning (false)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ namespace transport
 | 
			
		|||
	void EphemeralKeysSupplier<Keys>::Start ()
 | 
			
		||||
	{
 | 
			
		||||
		m_IsRunning = true;
 | 
			
		||||
		m_Thread = new std::thread (std::bind (&EphemeralKeysSupplier<Keys>::Run, this));
 | 
			
		||||
		m_Thread.reset (new std::thread (std::bind (&EphemeralKeysSupplier<Keys>::Run, this)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template<typename Keys>
 | 
			
		||||
| 
						 | 
				
			
			@ -53,8 +53,7 @@ namespace transport
 | 
			
		|||
		if (m_Thread)
 | 
			
		||||
		{
 | 
			
		||||
			m_Thread->join ();
 | 
			
		||||
			delete m_Thread;
 | 
			
		||||
			m_Thread = 0;
 | 
			
		||||
			m_Thread = nullptr;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,18 +65,19 @@ namespace transport
 | 
			
		|||
		while (m_IsRunning)
 | 
			
		||||
		{
 | 
			
		||||
			int num, total = 0;
 | 
			
		||||
			while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 10)
 | 
			
		||||
			while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < m_QueueSize)
 | 
			
		||||
			{
 | 
			
		||||
				CreateEphemeralKeys (num);
 | 
			
		||||
				total += num;
 | 
			
		||||
			}
 | 
			
		||||
			if (total >= 10)
 | 
			
		||||
			if (total > m_QueueSize)
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogWarning, "Transports: ", total, " ephemeral keys generated at the time");
 | 
			
		||||
				std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				m_KeysPool.CleanUpMt ();
 | 
			
		||||
				std::unique_lock<std::mutex> l(m_AcquiredMutex);
 | 
			
		||||
				if (!m_IsRunning) break;
 | 
			
		||||
				m_Acquired.wait (l); // wait for element gets acquired
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +92,7 @@ namespace transport
 | 
			
		|||
		{
 | 
			
		||||
			for (int i = 0; i < num; i++)
 | 
			
		||||
			{
 | 
			
		||||
				auto pair = std::make_shared<Keys> ();
 | 
			
		||||
				auto pair = m_KeysPool.AcquireSharedMt ();
 | 
			
		||||
				pair->GenerateKeys ();
 | 
			
		||||
				std::unique_lock<std::mutex> l(m_AcquiredMutex);
 | 
			
		||||
				m_Queue.push (pair);
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ namespace transport
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// queue is empty, create new
 | 
			
		||||
		auto pair = std::make_shared<Keys> ();
 | 
			
		||||
		auto pair = m_KeysPool.AcquireSharedMt ();
 | 
			
		||||
		pair->GenerateKeys ();
 | 
			
		||||
		return pair;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -124,12 +124,12 @@ namespace transport
 | 
			
		|||
	{
 | 
			
		||||
		if (pair)
 | 
			
		||||
		{
 | 
			
		||||
			std::unique_lock<std::mutex>l(m_AcquiredMutex);
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_AcquiredMutex);
 | 
			
		||||
			if ((int)m_Queue.size () < 2*m_QueueSize)
 | 
			
		||||
				m_Queue.push (pair);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			LogPrint(eLogError, "Transports: Return null DHKeys");
 | 
			
		||||
			LogPrint(eLogError, "Transports: Return null keys");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Peer::UpdateParams (std::shared_ptr<const i2p::data::RouterInfo> router)
 | 
			
		||||
| 
						 | 
				
			
			@ -149,7 +149,7 @@ namespace transport
 | 
			
		|||
		m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_CheckReserved(true), m_Thread (nullptr),
 | 
			
		||||
		m_Service (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
 | 
			
		||||
		m_UpdateBandwidthTimer (nullptr), m_SSU2Server (nullptr), m_NTCP2Server (nullptr),
 | 
			
		||||
		m_X25519KeysPairSupplier (15), // 15 pre-generated keys
 | 
			
		||||
		m_X25519KeysPairSupplier (NUM_X25519_PRE_GENERATED_KEYS),
 | 
			
		||||
		m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0),
 | 
			
		||||
		m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0),
 | 
			
		||||
		m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0),
 | 
			
		||||
| 
						 | 
				
			
			@ -450,15 +450,25 @@ namespace transport
 | 
			
		|||
	void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg)
 | 
			
		||||
	{
 | 
			
		||||
		if (m_IsOnline)
 | 
			
		||||
			SendMessages (ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > {msg });
 | 
			
		||||
			SendMessages (ident, { msg });
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Transports::SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs)
 | 
			
		||||
	void Transports::SendMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs)
 | 
			
		||||
	{
 | 
			
		||||
		m_Service->post (std::bind (&Transports::PostMessages, this, ident, msgs));
 | 
			
		||||
		std::list<std::shared_ptr<i2p::I2NPMessage> > msgs1;
 | 
			
		||||
		msgs.swap (msgs1);
 | 
			
		||||
		SendMessages (ident, std::move (msgs1));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Transports::PostMessages (i2p::data::IdentHash ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > msgs)
 | 
			
		||||
	void Transports::SendMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >&& msgs)
 | 
			
		||||
	{
 | 
			
		||||
		m_Service->post ([this, ident, msgs = std::move(msgs)] () mutable
 | 
			
		||||
			{
 | 
			
		||||
				PostMessages (ident, msgs);
 | 
			
		||||
			});	
 | 
			
		||||
	}	
 | 
			
		||||
	
 | 
			
		||||
	void Transports::PostMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs)
 | 
			
		||||
	{
 | 
			
		||||
		if (ident == i2p::context.GetRouterInfo ().GetIdentHash ())
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -470,8 +480,13 @@ namespace transport
 | 
			
		|||
		}
 | 
			
		||||
		if(RoutesRestricted() && !IsRestrictedPeer(ident)) return;
 | 
			
		||||
		std::shared_ptr<Peer> peer;
 | 
			
		||||
		auto it = m_Peers.find (ident);
 | 
			
		||||
		if (it == m_Peers.end ())
 | 
			
		||||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
			auto it = m_Peers.find (ident);
 | 
			
		||||
			if (it != m_Peers.end ())
 | 
			
		||||
				peer = it->second;
 | 
			
		||||
		}	
 | 
			
		||||
		if (!peer)
 | 
			
		||||
		{
 | 
			
		||||
			// check if not banned
 | 
			
		||||
			if (i2p::data::IsRouterBanned (ident)) return; // don't create peer to unreachable router
 | 
			
		||||
| 
						 | 
				
			
			@ -481,10 +496,10 @@ namespace transport
 | 
			
		|||
			{
 | 
			
		||||
				auto r = netdb.FindRouter (ident);
 | 
			
		||||
				if (r && (r->IsUnreachable () || !r->IsReachableFrom (i2p::context.GetRouterInfo ()))) return; // router found but non-reachable
 | 
			
		||||
				{
 | 
			
		||||
					auto ts = i2p::util::GetSecondsSinceEpoch ();
 | 
			
		||||
					peer = std::make_shared<Peer>(r, ts);
 | 
			
		||||
					std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
 | 
			
		||||
				peer = std::make_shared<Peer>(r, i2p::util::GetSecondsSinceEpoch ());
 | 
			
		||||
				{	
 | 
			
		||||
					std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
					peer = m_Peers.emplace (ident, peer).first->second;
 | 
			
		||||
				}
 | 
			
		||||
				if (peer)
 | 
			
		||||
| 
						 | 
				
			
			@ -496,8 +511,6 @@ namespace transport
 | 
			
		|||
			}
 | 
			
		||||
			if (!connected) return;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			peer = it->second;
 | 
			
		||||
		
 | 
			
		||||
		if (!peer) return;
 | 
			
		||||
		if (peer->IsConnected ())
 | 
			
		||||
| 
						 | 
				
			
			@ -512,22 +525,27 @@ namespace transport
 | 
			
		|||
					if (i2p::data::IsRouterBanned (ident))
 | 
			
		||||
					{
 | 
			
		||||
						LogPrint (eLogWarning, "Transports: Router ", ident.ToBase64 (), " is banned. Peer dropped");
 | 
			
		||||
						std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
						std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
						m_Peers.erase (ident);
 | 
			
		||||
						return;
 | 
			
		||||
					}	
 | 
			
		||||
				}	
 | 
			
		||||
				for (auto& it1: msgs)
 | 
			
		||||
					if (sz > MAX_NUM_DELAYED_MESSAGES/2 && it1->onDrop)
 | 
			
		||||
						it1->Drop (); // drop earlier because we can handle it
 | 
			
		||||
					else
 | 
			
		||||
						peer->delayedMessages.push_back (it1);
 | 
			
		||||
				if (sz > MAX_NUM_DELAYED_MESSAGES/2)
 | 
			
		||||
				{	
 | 
			
		||||
					for (auto& it1: msgs)
 | 
			
		||||
						if (it1->onDrop)
 | 
			
		||||
							it1->Drop (); // drop earlier because we can handle it
 | 
			
		||||
						else
 | 
			
		||||
							peer->delayedMessages.push_back (it1);
 | 
			
		||||
				}	
 | 
			
		||||
				else
 | 
			
		||||
					peer->delayedMessages.splice (peer->delayedMessages.end (), msgs);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogWarning, "Transports: Delayed messages queue size to ",
 | 
			
		||||
					ident.ToBase64 (), " exceeds ", MAX_NUM_DELAYED_MESSAGES);
 | 
			
		||||
				std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
				std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
				m_Peers.erase (ident);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -602,7 +620,7 @@ namespace transport
 | 
			
		|||
			if (!i2p::context.IsLimitedConnectivity () && peer->router->IsReachableFrom (i2p::context.GetRouterInfo ()))
 | 
			
		||||
				i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed but router claimed them
 | 
			
		||||
			peer->Done ();
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
			std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
			m_Peers.erase (ident);
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -610,7 +628,7 @@ namespace transport
 | 
			
		|||
		{
 | 
			
		||||
			LogPrint (eLogWarning, "Transports: Router ", ident.ToBase64 (), " is banned. Peer dropped");
 | 
			
		||||
			peer->Done ();
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
			std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
			m_Peers.erase (ident);
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -706,23 +724,29 @@ namespace transport
 | 
			
		|||
 | 
			
		||||
	void Transports::HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident)
 | 
			
		||||
	{
 | 
			
		||||
		auto it = m_Peers.find (ident);
 | 
			
		||||
		if (it != m_Peers.end ())
 | 
			
		||||
		std::shared_ptr<Peer> peer;
 | 
			
		||||
		{
 | 
			
		||||
			if (r)
 | 
			
		||||
			std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
			auto it = m_Peers.find (ident);
 | 
			
		||||
			if (it != m_Peers.end ())
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogDebug, "Transports: RouterInfo for ", ident.ToBase64 (), " found, trying to connect");
 | 
			
		||||
				it->second->SetRouter (r);
 | 
			
		||||
				if (!it->second->IsConnected ())
 | 
			
		||||
					ConnectToPeer (ident, it->second);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogWarning, "Transports: RouterInfo not found, failed to send messages");
 | 
			
		||||
				std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
				m_Peers.erase (it);
 | 
			
		||||
			}
 | 
			
		||||
				if (r)
 | 
			
		||||
					peer = it->second;
 | 
			
		||||
				else
 | 
			
		||||
					m_Peers.erase (it);
 | 
			
		||||
			}	
 | 
			
		||||
		}
 | 
			
		||||
				
 | 
			
		||||
		if (peer && !peer->router && r)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogDebug, "Transports: RouterInfo for ", ident.ToBase64 (), " found, trying to connect");
 | 
			
		||||
			peer->SetRouter (r);
 | 
			
		||||
			if (!peer->IsConnected ())
 | 
			
		||||
				ConnectToPeer (ident, peer);
 | 
			
		||||
		}
 | 
			
		||||
		else if (!r)
 | 
			
		||||
			LogPrint (eLogInfo, "Transports: RouterInfo not found, failed to send messages");
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Transports::DetectExternalIP ()
 | 
			
		||||
| 
						 | 
				
			
			@ -865,7 +889,7 @@ namespace transport
 | 
			
		|||
				if (it->second->delayedMessages.size () > 0)
 | 
			
		||||
				{
 | 
			
		||||
					// check if first message is our DatabaseStore (publishing)
 | 
			
		||||
					auto firstMsg = peer->delayedMessages[0];
 | 
			
		||||
					auto firstMsg = peer->delayedMessages.front ();
 | 
			
		||||
					if (firstMsg && firstMsg->GetTypeID () == eI2NPDatabaseStore &&
 | 
			
		||||
							i2p::data::IdentHash(firstMsg->GetPayload () + DATABASE_STORE_KEY_OFFSET) == i2p::context.GetIdentHash ())
 | 
			
		||||
						sendDatabaseStore = false; // we have it in the list already
 | 
			
		||||
| 
						 | 
				
			
			@ -875,8 +899,7 @@ namespace transport
 | 
			
		|||
				else
 | 
			
		||||
					session->SetTerminationTimeout (10); // most likely it's publishing, no follow-up messages expected, set timeout to 10 seconds
 | 
			
		||||
				peer->sessions.push_back (session);
 | 
			
		||||
				session->SendI2NPMessages (peer->delayedMessages);
 | 
			
		||||
				peer->delayedMessages.clear ();
 | 
			
		||||
				session->SendI2NPMessages (peer->delayedMessages); // send and clear
 | 
			
		||||
			}
 | 
			
		||||
			else // incoming connection or peer test
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -887,14 +910,17 @@ namespace transport
 | 
			
		|||
					return;
 | 
			
		||||
				}
 | 
			
		||||
				if (!session->IsOutgoing ()) // incoming
 | 
			
		||||
					session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
 | 
			
		||||
				{
 | 
			
		||||
					std::list<std::shared_ptr<I2NPMessage> > msgs{ CreateDatabaseStoreMsg () };
 | 
			
		||||
					session->SendI2NPMessages (msgs); // send DatabaseStore
 | 
			
		||||
				}	
 | 
			
		||||
				auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed
 | 
			
		||||
				if (r) r->GetProfile ()->Connected ();
 | 
			
		||||
				auto ts = i2p::util::GetSecondsSinceEpoch ();
 | 
			
		||||
				auto peer = std::make_shared<Peer>(r, ts);
 | 
			
		||||
				peer->sessions.push_back (session);
 | 
			
		||||
				peer->router = nullptr;
 | 
			
		||||
				std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
				std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
				m_Peers.emplace (ident, peer);
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
| 
						 | 
				
			
			@ -923,7 +949,7 @@ namespace transport
 | 
			
		|||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
						std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
						m_Peers.erase (it);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -933,9 +959,13 @@ namespace transport
 | 
			
		|||
 | 
			
		||||
	bool Transports::IsConnected (const i2p::data::IdentHash& ident) const
 | 
			
		||||
	{
 | 
			
		||||
		std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
		std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
#if __cplusplus >= 202002L // C++20
 | 
			
		||||
		return m_Peers.contains (ident);
 | 
			
		||||
#else		
 | 
			
		||||
		auto it = m_Peers.find (ident);
 | 
			
		||||
		return it != m_Peers.end ();
 | 
			
		||||
#endif		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Transports::HandlePeerCleanupTimer (const boost::system::error_code& ecode)
 | 
			
		||||
| 
						 | 
				
			
			@ -959,7 +989,7 @@ namespace transport
 | 
			
		|||
						auto profile = i2p::data::GetRouterProfile (it->first);
 | 
			
		||||
						if (profile) profile->Unreachable ();
 | 
			
		||||
					}	*/
 | 
			
		||||
					std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
					std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
					it = m_Peers.erase (it);
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
| 
						 | 
				
			
			@ -1009,7 +1039,7 @@ namespace transport
 | 
			
		|||
		{
 | 
			
		||||
			uint16_t inds[3];
 | 
			
		||||
			RAND_bytes ((uint8_t *)inds, sizeof (inds));
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_PeersMutex);
 | 
			
		||||
			std::lock_guard<std::mutex> l(m_PeersMutex);
 | 
			
		||||
			auto count = m_Peers.size ();
 | 
			
		||||
			if(count == 0) return nullptr;
 | 
			
		||||
			inds[0] %= count;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@
 | 
			
		|||
#include "RouterInfo.h"
 | 
			
		||||
#include "I2NPProtocol.h"
 | 
			
		||||
#include "Identity.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -53,9 +54,10 @@ namespace transport
 | 
			
		|||
 | 
			
		||||
			const int m_QueueSize;
 | 
			
		||||
			std::queue<std::shared_ptr<Keys> > m_Queue;
 | 
			
		||||
			i2p::util::MemoryPoolMt<Keys> m_KeysPool;
 | 
			
		||||
 | 
			
		||||
			bool m_IsRunning;
 | 
			
		||||
			std::thread * m_Thread;
 | 
			
		||||
			std::unique_ptr<std::thread> m_Thread;
 | 
			
		||||
			std::condition_variable m_Acquired;
 | 
			
		||||
			std::mutex m_AcquiredMutex;
 | 
			
		||||
	};
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +73,7 @@ namespace transport
 | 
			
		|||
		std::shared_ptr<const i2p::data::RouterInfo> router;
 | 
			
		||||
		std::list<std::shared_ptr<TransportSession> > sessions;
 | 
			
		||||
		uint64_t creationTime, nextRouterInfoUpdateTime, lastSelectionTime;
 | 
			
		||||
		std::vector<std::shared_ptr<i2p::I2NPMessage> > delayedMessages;
 | 
			
		||||
		std::list<std::shared_ptr<i2p::I2NPMessage> > delayedMessages;
 | 
			
		||||
		std::vector<i2p::data::RouterInfo::SupportedTransports> priority;
 | 
			
		||||
		bool isHighBandwidth, isEligible;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +110,8 @@ namespace transport
 | 
			
		|||
	const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
 | 
			
		||||
	const int MAX_NUM_DELAYED_MESSAGES = 150;
 | 
			
		||||
	const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after
 | 
			
		||||
 | 
			
		||||
	const int NUM_X25519_PRE_GENERATED_KEYS = 25; // pre-generated x25519 keys pairs
 | 
			
		||||
	
 | 
			
		||||
	const int TRAFFIC_SAMPLE_COUNT = 301; // seconds
 | 
			
		||||
 | 
			
		||||
	struct TrafficSample
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +144,8 @@ namespace transport
 | 
			
		|||
			void ReuseX25519KeysPair (std::shared_ptr<i2p::crypto::X25519Keys> pair);
 | 
			
		||||
 | 
			
		||||
			void SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg);
 | 
			
		||||
			void SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs);
 | 
			
		||||
			void SendMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs);
 | 
			
		||||
			void SendMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >&& msgs);
 | 
			
		||||
 | 
			
		||||
			void PeerConnected (std::shared_ptr<TransportSession> session);
 | 
			
		||||
			void PeerDisconnected (std::shared_ptr<TransportSession> session);
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +189,7 @@ namespace transport
 | 
			
		|||
			void Run ();
 | 
			
		||||
			void RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident);
 | 
			
		||||
			void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident);
 | 
			
		||||
			void PostMessages (i2p::data::IdentHash ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > msgs);
 | 
			
		||||
			void PostMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs);
 | 
			
		||||
			bool ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer);
 | 
			
		||||
			void SetPriority (std::shared_ptr<Peer> peer) const;
 | 
			
		||||
			void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -221,7 +221,7 @@ namespace tunnel
 | 
			
		|||
	void TunnelGateway::SendBuffer ()
 | 
			
		||||
	{
 | 
			
		||||
		m_Buffer.CompleteCurrentTunnelDataMessage ();
 | 
			
		||||
		std::vector<std::shared_ptr<I2NPMessage> > newTunnelMsgs;
 | 
			
		||||
		std::list<std::shared_ptr<I2NPMessage> > newTunnelMsgs;
 | 
			
		||||
		const auto& tunnelDataMsgs = m_Buffer.GetTunnelDataMsgs ();
 | 
			
		||||
		for (auto& tunnelMsg : tunnelDataMsgs)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +234,7 @@ namespace tunnel
 | 
			
		|||
			m_NumSentBytes += TUNNEL_DATA_MSG_SIZE;
 | 
			
		||||
		}
 | 
			
		||||
		m_Buffer.ClearTunnelDataMsgs ();
 | 
			
		||||
		i2p::transport::transports.SendMessages (m_Tunnel->GetNextIdentHash (), newTunnelMsgs);
 | 
			
		||||
		i2p::transport::transports.SendMessages (m_Tunnel->GetNextIdentHash (), std::move (newTunnelMsgs));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -305,7 +305,7 @@ namespace client
 | 
			
		|||
		identHash = hash;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false),
 | 
			
		||||
	AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false),
 | 
			
		||||
		m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr),
 | 
			
		||||
		m_IsEnabled (true)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -344,20 +344,28 @@ namespace client
 | 
			
		|||
			delete m_SubscriptionsUpdateTimer;
 | 
			
		||||
			m_SubscriptionsUpdateTimer = nullptr;
 | 
			
		||||
		}
 | 
			
		||||
		if (m_IsDownloading)
 | 
			
		||||
		bool isDownloading = m_Downloading.valid ();
 | 
			
		||||
		if (isDownloading)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint (eLogInfo, "Addressbook: Subscriptions are downloading, abort");
 | 
			
		||||
			for (int i = 0; i < 30; i++)
 | 
			
		||||
			{
 | 
			
		||||
				if (!m_IsDownloading)
 | 
			
		||||
			if (m_Downloading.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
 | 
			
		||||
				isDownloading = false;
 | 
			
		||||
			else	
 | 
			
		||||
			{	
 | 
			
		||||
				LogPrint (eLogInfo, "Addressbook: Subscriptions are downloading, abort");
 | 
			
		||||
				for (int i = 0; i < 30; i++)
 | 
			
		||||
				{
 | 
			
		||||
					LogPrint (eLogInfo, "Addressbook: Subscriptions download complete");
 | 
			
		||||
					break;
 | 
			
		||||
					if (m_Downloading.wait_for(std::chrono::seconds(1)) == std::future_status::ready) // wait for 1 seconds
 | 
			
		||||
					{
 | 
			
		||||
						isDownloading = false;
 | 
			
		||||
						LogPrint (eLogInfo, "Addressbook: Subscriptions download complete");
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				std::this_thread::sleep_for (std::chrono::seconds (1)); // wait for 1 seconds
 | 
			
		||||
			}
 | 
			
		||||
			LogPrint (eLogError, "Addressbook: Subscription download timeout");
 | 
			
		||||
			m_IsDownloading = false;
 | 
			
		||||
			}	
 | 
			
		||||
			if (!isDownloading)
 | 
			
		||||
				m_Downloading.get ();
 | 
			
		||||
			else
 | 
			
		||||
				LogPrint (eLogError, "Addressbook: Subscription download timeout");
 | 
			
		||||
		}
 | 
			
		||||
		if (m_Storage)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -582,16 +590,15 @@ namespace client
 | 
			
		|||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint (eLogInfo, "Addressbook: Loading subscriptions from config file");
 | 
			
		||||
				LogPrint (eLogInfo, "Addressbook: Loading subscriptions from config");
 | 
			
		||||
				// 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 (const auto& s: subsList)
 | 
			
		||||
				{
 | 
			
		||||
					m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, s));
 | 
			
		||||
				}
 | 
			
		||||
					if (!s.empty ())
 | 
			
		||||
						m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, s));
 | 
			
		||||
				LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -645,7 +652,6 @@ namespace client
 | 
			
		|||
 | 
			
		||||
	void AddressBook::DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified)
 | 
			
		||||
	{
 | 
			
		||||
		m_IsDownloading = false;
 | 
			
		||||
		m_NumRetries++;
 | 
			
		||||
		int nextUpdateTimeout = m_NumRetries*CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT;
 | 
			
		||||
		if (m_NumRetries > CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES || nextUpdateTimeout > CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT)
 | 
			
		||||
| 
						 | 
				
			
			@ -700,7 +706,13 @@ namespace client
 | 
			
		|||
				LogPrint(eLogWarning, "Addressbook: Missing local destination, skip subscription update");
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			if (!m_IsDownloading && dest->IsReady ())
 | 
			
		||||
			bool isDownloading = m_Downloading.valid ();
 | 
			
		||||
			if (isDownloading && m_Downloading.wait_for(std::chrono::seconds(0)) == std::future_status::ready) // still active?
 | 
			
		||||
			{
 | 
			
		||||
				m_Downloading.get ();
 | 
			
		||||
				isDownloading = false;
 | 
			
		||||
			}	
 | 
			
		||||
			if (!isDownloading && dest->IsReady ())
 | 
			
		||||
			{
 | 
			
		||||
				if (!m_IsLoaded)
 | 
			
		||||
				{
 | 
			
		||||
| 
						 | 
				
			
			@ -709,17 +721,15 @@ namespace client
 | 
			
		|||
					std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL);
 | 
			
		||||
					if (!m_DefaultSubscription)
 | 
			
		||||
						m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, defaultSubURL);
 | 
			
		||||
					m_IsDownloading = true;
 | 
			
		||||
					std::thread load_hosts(std::bind (&AddressBookSubscription::CheckUpdates, m_DefaultSubscription));
 | 
			
		||||
					load_hosts.detach(); // TODO: use join
 | 
			
		||||
					m_Downloading = std::async (std::launch::async,
 | 
			
		||||
						std::bind (&AddressBookSubscription::CheckUpdates, m_DefaultSubscription));
 | 
			
		||||
				}
 | 
			
		||||
				else if (!m_Subscriptions.empty ())
 | 
			
		||||
				{
 | 
			
		||||
					// pick random subscription
 | 
			
		||||
					auto ind = rand () % m_Subscriptions.size();
 | 
			
		||||
					m_IsDownloading = true;
 | 
			
		||||
					std::thread load_hosts(std::bind (&AddressBookSubscription::CheckUpdates, m_Subscriptions[ind]));
 | 
			
		||||
					load_hosts.detach(); // TODO: use join
 | 
			
		||||
					m_Downloading = std::async (std::launch::async,
 | 
			
		||||
						std::bind (&AddressBookSubscription::CheckUpdates, m_Subscriptions[ind]));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
| 
						 | 
				
			
			@ -823,7 +833,7 @@ namespace client
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	AddressBookSubscription::AddressBookSubscription (AddressBook& book, const std::string& link):
 | 
			
		||||
	AddressBookSubscription::AddressBookSubscription (AddressBook& book, std::string_view link):
 | 
			
		||||
		m_Book (book), m_Link (link)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,10 +11,12 @@
 | 
			
		|||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <string_view>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <future>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <boost/asio.hpp>
 | 
			
		||||
#include "Base.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +126,8 @@ namespace client
 | 
			
		|||
			std::mutex m_LookupsMutex;
 | 
			
		||||
			std::map<uint32_t, std::string> m_Lookups; // nonce -> address
 | 
			
		||||
			AddressBookStorage * m_Storage;
 | 
			
		||||
			volatile bool m_IsLoaded, m_IsDownloading;
 | 
			
		||||
			volatile bool m_IsLoaded;
 | 
			
		||||
			std::future<void> m_Downloading;
 | 
			
		||||
			int m_NumRetries;
 | 
			
		||||
			std::vector<std::shared_ptr<AddressBookSubscription> > m_Subscriptions;
 | 
			
		||||
			std::shared_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +139,7 @@ namespace client
 | 
			
		|||
	{
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			AddressBookSubscription (AddressBook& book, const std::string& link);
 | 
			
		||||
			AddressBookSubscription (AddressBook& book, std::string_view link);
 | 
			
		||||
			void CheckUpdates ();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -203,7 +203,7 @@ namespace client
 | 
			
		|||
		std::vector<std::shared_ptr<DatagramSessionInfo> > sessions;
 | 
			
		||||
		std::lock_guard<std::mutex> lock (m_SessionsMutex);
 | 
			
		||||
 | 
			
		||||
		for (auto it: m_Sessions)
 | 
			
		||||
        for (const auto &it: m_Sessions)
 | 
			
		||||
		{
 | 
			
		||||
			auto s = it.second;
 | 
			
		||||
			if (!s->m_Destination) continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,10 +49,6 @@ set(test-gost-sig_SRCS
 | 
			
		|||
  test-gost-sig.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(test-x25519_SRCS
 | 
			
		||||
  test-x25519.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(test-aeadchacha20poly1305_SRCS
 | 
			
		||||
  test-aeadchacha20poly1305.cpp
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +73,6 @@ add_executable(test-http-url ${test-http-url_SRCS})
 | 
			
		|||
add_executable(test-base-64 ${test-base-64_SRCS})
 | 
			
		||||
add_executable(test-gost ${test-gost_SRCS})
 | 
			
		||||
add_executable(test-gost-sig ${test-gost-sig_SRCS})
 | 
			
		||||
add_executable(test-x25519 ${test-x25519_SRCS})
 | 
			
		||||
add_executable(test-aeadchacha20poly1305 ${test-aeadchacha20poly1305_SRCS})
 | 
			
		||||
add_executable(test-blinding ${test-blinding_SRCS})
 | 
			
		||||
add_executable(test-elligator ${test-elligator_SRCS})
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +97,6 @@ target_link_libraries(test-http-url ${LIBS})
 | 
			
		|||
target_link_libraries(test-base-64 ${LIBS})
 | 
			
		||||
target_link_libraries(test-gost ${LIBS})
 | 
			
		||||
target_link_libraries(test-gost-sig ${LIBS})
 | 
			
		||||
target_link_libraries(test-x25519 ${LIBS})
 | 
			
		||||
target_link_libraries(test-aeadchacha20poly1305 ${LIBS})
 | 
			
		||||
target_link_libraries(test-blinding ${LIBS})
 | 
			
		||||
target_link_libraries(test-elligator ${LIBS})
 | 
			
		||||
| 
						 | 
				
			
			@ -116,7 +110,6 @@ add_test(test-http-url ${TEST_PATH}/test-http-url)
 | 
			
		|||
add_test(test-base-64 ${TEST_PATH}/test-base-64)
 | 
			
		||||
add_test(test-gost ${TEST_PATH}/test-gost)
 | 
			
		||||
add_test(test-gost-sig ${TEST_PATH}/test-gost-sig)
 | 
			
		||||
add_test(test-x25519 ${TEST_PATH}/test-x25519)
 | 
			
		||||
add_test(test-aeadchacha20poly1305 ${TEST_PATH}/test-aeadchacha20poly1305)
 | 
			
		||||
add_test(test-blinding ${TEST_PATH}/test-blinding)
 | 
			
		||||
add_test(test-elligator ${TEST_PATH}/test-elligator)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ LIBI2PD = ../libi2pd.a
 | 
			
		|||
 | 
			
		||||
TESTS = \
 | 
			
		||||
	test-http-merge_chunked test-http-req test-http-res test-http-url test-http-url_decode \
 | 
			
		||||
	test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding \
 | 
			
		||||
	test-gost test-gost-sig test-base-64 test-aeadchacha20poly1305 test-blinding \
 | 
			
		||||
	test-elligator test-eddsa 
 | 
			
		||||
 | 
			
		||||
ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
 | 
			
		||||
| 
						 | 
				
			
			@ -44,9 +44,6 @@ test-gost: test-gost.cpp $(LIBI2PD)
 | 
			
		|||
test-gost-sig: test-gost-sig.cpp $(LIBI2PD)
 | 
			
		||||
	$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
 | 
			
		||||
 | 
			
		||||
test-x25519: test-x25519.cpp $(LIBI2PD)
 | 
			
		||||
	$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
 | 
			
		||||
 | 
			
		||||
test-aeadchacha20poly1305: test-aeadchacha20poly1305.cpp $(LIBI2PD)
 | 
			
		||||
	 $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,38 +0,0 @@
 | 
			
		|||
#include <cassert>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "Ed25519.h"
 | 
			
		||||
 | 
			
		||||
const uint8_t k[32] =
 | 
			
		||||
{
 | 
			
		||||
    0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
 | 
			
		||||
    0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
 | 
			
		||||
    0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const uint8_t u[32] =
 | 
			
		||||
{
 | 
			
		||||
    0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1,
 | 
			
		||||
    0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3,
 | 
			
		||||
    0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
uint8_t p[32] =
 | 
			
		||||
{
 | 
			
		||||
    0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
 | 
			
		||||
    0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
 | 
			
		||||
    0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main ()
 | 
			
		||||
{
 | 
			
		||||
#if !OPENSSL_X25519
 | 
			
		||||
// we test it for openssl < 1.1.0
 | 
			
		||||
    uint8_t buf[32];
 | 
			
		||||
    BN_CTX * ctx = BN_CTX_new ();
 | 
			
		||||
    i2p::crypto::GetEd25519 ()->ScalarMul (u, k, buf, ctx);
 | 
			
		||||
    BN_CTX_free (ctx);
 | 
			
		||||
    assert(memcmp (buf, p, 32) == 0);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue