diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index aa458127..3526de4d 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -395,8 +395,8 @@ namespace client auto it1 = m_RouterInfoHandlers.find (it->first); if (it1 != m_RouterInfoHandlers.end ()) { - if (!first) results << ","; - else first = false; + if (!first) results << ","; + else first = false; (this->*(it1->second))(results); } else diff --git a/daemon/UPnP.cpp b/daemon/UPnP.cpp index 2752bb9e..fe6a565e 100644 --- a/daemon/UPnP.cpp +++ b/daemon/UPnP.cpp @@ -225,7 +225,7 @@ namespace transport } std::string strType (GetProto (address)), strPort (std::to_string (address->port)); int err = UPNPCOMMAND_SUCCESS; - + err = CheckMapping (strPort.c_str (), strType.c_str ()); if (err == UPNPCOMMAND_SUCCESS) { diff --git a/libi2pd/Blinding.cpp b/libi2pd/Blinding.cpp index 881dde6e..768b856e 100644 --- a/libi2pd/Blinding.cpp +++ b/libi2pd/Blinding.cpp @@ -272,19 +272,19 @@ namespace data case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384: case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521: publicKeyLength = BlindECDSA (m_SigType, priv, seed, BlindEncodedPrivateKeyECDSA, blindedPriv, blindedPub); - break; + break; case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: i2p::crypto::GetEd25519 ()->BlindPrivateKey (priv, seed, blindedPriv, blindedPub); publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; break; - case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: + case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: { - uint8_t exp[64]; - i2p::crypto::Ed25519::ExpandPrivateKey (priv, exp); + uint8_t exp[64]; + i2p::crypto::Ed25519::ExpandPrivateKey (priv, exp); i2p::crypto::GetEd25519 ()->BlindPrivateKey (exp, seed, blindedPriv, blindedPub); - publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; + publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; break; - } + } default: LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType); } diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index d38d489a..053e9af7 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -389,7 +389,7 @@ 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) @@ -440,7 +440,7 @@ namespace crypto bn2buf (a, encrypted + 1, 256); encrypted[257] = 0; bn2buf (b, encrypted + 258, 256); - + BN_free (a); BN_CTX_end (ctx); BN_CTX_free (ctx); @@ -1295,7 +1295,7 @@ namespace crypto } // Noise - + void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len) { SHA256_CTX ctx; @@ -1311,7 +1311,7 @@ namespace crypto // new ck is m_CK[0:31], key is m_CK[32:63] } - static void InitNoiseState (NoiseSymmetricState& state, const uint8_t * ck, + static void InitNoiseState (NoiseSymmetricState& state, const uint8_t * ck, const uint8_t * hh, const uint8_t * pub) { // pub is Bob's public static key, hh = SHA256(h) @@ -1321,19 +1321,19 @@ namespace crypto SHA256_Update (&ctx, hh, 32); SHA256_Update (&ctx, pub, 32); SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub) - } - + } + void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub) { static const char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars static const uint8_t hh[32] = { - 0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1, + 0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1, 0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54 }; // hh = SHA256(protocol_name || 0) InitNoiseState (state, (const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0 - } - + } + void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub) { static const uint8_t protocolNameHash[] = @@ -1346,8 +1346,8 @@ namespace crypto 0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5, 0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e }; // SHA256 (protocolNameHash) - InitNoiseState (state, protocolNameHash, hh, pub); - } + InitNoiseState (state, protocolNameHash, hh, pub); + } void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub) { @@ -1361,9 +1361,9 @@ namespace crypto 0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32, 0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c }; // SHA256 (protocolNameHash) - InitNoiseState (state, protocolNameHash, hh, pub); - } - + InitNoiseState (state, protocolNameHash, hh, pub); + } + // init and terminate /* std::vector > m_OpenSSLMutexes; diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index d0ff42e4..ce68ec05 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -95,7 +95,7 @@ namespace crypto bool IsElligatorIneligible () const { return m_IsElligatorIneligible; } void SetElligatorIneligible () { m_IsElligatorIneligible = true; } - + private: uint8_t m_PublicKey[32]; @@ -110,7 +110,7 @@ namespace crypto }; // ElGamal - void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted); // 222 bytes data, 514 bytes encrypted + void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted); // 222 bytes data, 514 bytes encrypted bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data); // 514 bytes encrypted, 222 data void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub); @@ -317,13 +317,13 @@ namespace crypto uint8_t m_H[32] /*h*/, m_CK[64] /*[ck, k]*/; void MixHash (const uint8_t * buf, size_t len); - void MixKey (const uint8_t * sharedSecret); + void MixKey (const uint8_t * sharedSecret); }; void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_N (tunnels, router) void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (NTCP2) void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets) - + // init and terminate void InitCrypto (bool precomputation, bool aesni, bool avx, bool force); void TerminateCrypto (); diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 0ac0bdd5..a7d86d09 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -29,7 +29,7 @@ namespace crypto public: virtual ~CryptoKeyDecryptor () {}; - virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data) = 0; + virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data) = 0; virtual size_t GetPublicKeyLen () const = 0; // we need it to set key in LS2 }; diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 4ee115cf..2affc8be 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -303,7 +303,7 @@ namespace datagram } } - if (!m_RoutingSession || m_RoutingSession->IsTerminated () || !m_RoutingSession->IsReadyToSend ()) + if (!m_RoutingSession || m_RoutingSession->IsTerminated () || !m_RoutingSession->IsReadyToSend ()) { bool found = false; for (auto& it: m_PendingRoutingSessions) @@ -384,7 +384,7 @@ namespace datagram } else return nullptr; - + auto leaseRouter = i2p::data::netdb.FindRouter (path->remoteLease->tunnelGateway); path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(nullptr, leaseRouter ? leaseRouter->GetCompatibleTransports (false) : (i2p::data::RouterInfo::CompatibleTransports)i2p::data::RouterInfo::eAllTransports); diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index 564eb10b..a55c8edf 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -117,12 +117,12 @@ namespace datagram void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void SendRawDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); // TODO: implement calls from other thread from SAM - + std::shared_ptr GetSession(const i2p::data::IdentHash & ident); void SendDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); void SendRawDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); void FlushSendQueue (std::shared_ptr session); - + void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false); void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 606cee9d..ba336ec2 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -89,7 +89,7 @@ namespace client bool dontpublish = false; i2p::config::GetOption (it->second, dontpublish); m_IsPublic = !dontpublish; - } + } it = params->find (I2CP_PARAM_LEASESET_TYPE); if (it != params->end ()) m_LeaseSetType = std::stoi(it->second); @@ -367,8 +367,8 @@ namespace client HandleDatabaseSearchReplyMessage (payload, len); break; case eI2NPShortTunnelBuildReply: // might come as garlic encrypted - i2p::HandleI2NPMessage (CreateI2NPMessage (typeID, payload, len, msgID)); - break; + i2p::HandleI2NPMessage (CreateI2NPMessage (typeID, payload, len, msgID)); + break; default: LogPrint (eLogWarning, "Destination: Unexpected I2NP message type ", typeID); return false; @@ -395,7 +395,7 @@ namespace client LogPrint (eLogDebug, "Destination: Remote LeaseSet"); std::lock_guard lock(m_RemoteLeaseSetsMutex); auto it = m_RemoteLeaseSets.find (key); - if (it != m_RemoteLeaseSets.end () && + if (it != m_RemoteLeaseSets.end () && it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type { leaseSet = it->second; @@ -487,7 +487,7 @@ namespace client i2p::data::IdentHash peerHash (buf + 33 + i*32); if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash)) { - LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); + LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory } } @@ -767,11 +767,11 @@ namespace client uint8_t replyKey[32], replyTag[32]; RAND_bytes (replyKey, 32); // random session key RAND_bytes (replyTag, isECIES ? 8 : 32); // random session tag - if (isECIES) + if (isECIES) AddECIESx25519Key (replyKey, replyTag); - else + else AddSessionKey (replyKey, replyTag); - auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest, + auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES)); request->outboundTunnel->SendTunnelDataMsg ( { @@ -866,8 +866,8 @@ namespace client ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): - LeaseSetDestination (service, isPublic, params), - m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), + LeaseSetDestination (service, isPublic, params), + m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(service) @@ -916,11 +916,11 @@ namespace client encryptionKey->GenerateKeys (); encryptionKey->CreateDecryptor (); if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) - { + { m_ECIESx25519EncryptionKey.reset (encryptionKey); if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) - SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Rathets must use LeaseSet2 - } + SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Rathets must use LeaseSet2 + } else m_StandardEncryptionKey.reset (encryptionKey); } @@ -939,7 +939,7 @@ namespace client it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); if (it != params->end ()) i2p::config::GetOption (it->second, m_IsStreamingAnswerPings); - + if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) { // authentication for encrypted LeaseSet @@ -1099,21 +1099,21 @@ namespace client void ClientDestination::SendPing (const i2p::data::IdentHash& to) { if (m_StreamingDestination) - { + { auto leaseSet = FindLeaseSet (to); if (leaseSet) m_StreamingDestination->SendPing (leaseSet); else - { + { auto s = m_StreamingDestination; RequestDestination (to, [s](std::shared_ptr ls) { if (ls) s->SendPing (ls); }); - } - } - } + } + } + } void ClientDestination::SendPing (std::shared_ptr to) { @@ -1122,9 +1122,9 @@ namespace client [s](std::shared_ptr ls) { if (ls) s->SendPing (ls); - }); - } - + }); + } + std::shared_ptr ClientDestination::GetStreamingDestination (int port) const { if (port) @@ -1182,18 +1182,18 @@ namespace client auto ret = it->second; m_StreamingDestinationsByPorts.erase (it); return ret; - } + } } return nullptr; - } - + } + i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip) { if (m_DatagramDestination == nullptr) m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip); return m_DatagramDestination; - } - + } + std::vector > ClientDestination::GetAllStreams () const { std::vector > ret; diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 54df8706..cb85db4c 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -68,8 +68,8 @@ namespace client const char I2CP_PARAM_LEASESET_PRIV_KEY[] = "i2cp.leaseSetPrivKey"; // PSK decryption key, base64 const char I2CP_PARAM_LEASESET_AUTH_TYPE[] = "i2cp.leaseSetAuthType"; const char I2CP_PARAM_LEASESET_CLIENT_DH[] = "i2cp.leaseSetClient.dh"; // group of i2cp.leaseSetClient.dh.nnn - const char I2CP_PARAM_LEASESET_CLIENT_PSK[] = "i2cp.leaseSetClient.psk"; // group of i2cp.leaseSetClient.psk.nnn - + const char I2CP_PARAM_LEASESET_CLIENT_PSK[] = "i2cp.leaseSetClient.psk"; // group of i2cp.leaseSetClient.psk.nnn + // latency const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min"; const int DEFAULT_MIN_TUNNEL_LATENCY = 0; @@ -80,7 +80,7 @@ namespace client const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay"; const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds const char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings"; - const int DEFAULT_ANSWER_PINGS = true; + const int DEFAULT_ANSWER_PINGS = true; typedef std::function stream)> StreamRequestComplete; @@ -139,7 +139,7 @@ namespace client void SetLeaseSetUpdated (); bool IsPublic () const { return m_IsPublic; }; - void SetPublic (bool pub) { m_IsPublic = pub; }; + void SetPublic (bool pub) { m_IsPublic = pub; }; protected: @@ -251,7 +251,7 @@ namespace client void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor); int GetStreamingAckDelay () const { return m_StreamingAckDelay; } bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; } - + // datagram i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true); diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 0bf74e3d..e240e925 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -90,24 +90,24 @@ namespace garlic } void RatchetTagSet::DeleteSymmKey (int index) - { + { m_ItermediateSymmKeys.erase (index); } - + void ReceiveRatchetTagSet::Expire () { if (!m_ExpirationTimestamp) m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT; } - bool ReceiveRatchetTagSet::IsExpired (uint64_t ts) const - { - return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; - } - - bool ReceiveRatchetTagSet::IsIndexExpired (int index) const - { - return index < m_TrimBehindIndex; + bool ReceiveRatchetTagSet::IsExpired (uint64_t ts) const + { + return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; + } + + bool ReceiveRatchetTagSet::IsIndexExpired (int index) const + { + return index < m_TrimBehindIndex; } bool ReceiveRatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index) @@ -115,21 +115,21 @@ namespace garlic auto session = GetSession (); if (!session) return false; return session->HandleNextMessage (buf, len, shared_from_this (), index); - } + } SymmetricKeyTagSet::SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key): - ReceiveRatchetTagSet (nullptr), m_Destination (destination) - { - memcpy (m_Key, key, 32); - Expire (); + ReceiveRatchetTagSet (nullptr), m_Destination (destination) + { + memcpy (m_Key, key, 32); + Expire (); } - + bool SymmetricKeyTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index) { if (len < 24) return false; uint8_t nonce[12]; memset (nonce, 0, 12); // n = 0 - size_t offset = 8; // first 8 bytes is reply tag used as AD + size_t offset = 8; // first 8 bytes is reply tag used as AD len -= 16; // poly1305 if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len - offset, buf, 8, m_Key, nonce, buf + offset, len - offset, false)) // decrypt { @@ -137,33 +137,33 @@ namespace garlic return false; } // we assume 1 I2NP block with delivery type local - if (offset + 3 > len) - { + if (offset + 3 > len) + { LogPrint (eLogWarning, "Garlic: Symmetric key tagset is too short ", len); return false; - } + } if (buf[offset] != eECIESx25519BlkGalicClove) { LogPrint (eLogWarning, "Garlic: Symmetric key tagset unexpected block ", (int)buf[offset]); return false; - } + } offset++; auto size = bufbe16toh (buf + offset); offset += 2; - if (offset + size > len) + if (offset + size > len) { LogPrint (eLogWarning, "Garlic: Symmetric key tagset block is too long ", size); return false; - } + } if (m_Destination) - m_Destination->HandleECIESx25519GarlicClove (buf + offset, size); + m_Destination->HandleECIESx25519GarlicClove (buf + offset, size); return true; - } - + } + ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSetNS): GarlicRoutingSession (owner, true) { - if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate); + if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate); RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0; } @@ -181,11 +181,11 @@ namespace garlic { bool ineligible = false; while (!ineligible) - { + { m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair (); ineligible = m_EphemeralKeys->IsElligatorIneligible (); if (!ineligible) // we haven't tried it yet - { + { if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys->GetPublicKey (), buf)) return true; // success // otherwise return back @@ -194,7 +194,7 @@ namespace garlic } else i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys); - } + } // we still didn't find elligator eligible pair for (int i = 0; i < 25; i++) { @@ -208,7 +208,7 @@ namespace garlic // let NTCP2 use it m_EphemeralKeys->SetElligatorIneligible (); i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys); - } + } } LogPrint (eLogError, "Garlic: Can't generate elligator eligible x25519 keys"); return false; @@ -229,7 +229,7 @@ namespace garlic // we are Bob // KDF1 i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk - + if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk)) { LogPrint (eLogError, "Garlic: Can't decode elligator"); @@ -243,7 +243,7 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key"); return false; - } + } MixKey (sharedSecret); // decrypt flags/static @@ -267,7 +267,7 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); return false; - } + } MixKey (sharedSecret); } else // all zeros flags @@ -280,13 +280,13 @@ namespace garlic LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed"); return false; } - + m_State = eSessionStateNewSessionReceived; - if (isStatic) - { + if (isStatic) + { MixHash (buf, len); // h = SHA256(h || ciphertext) GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); - } + } HandlePayload (payload.data (), len - 16, nullptr, 0); return true; @@ -468,7 +468,7 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: Incorrect Bob static key"); return false; - } + } MixKey (sharedSecret); // encrypt flags/static key section uint8_t nonce[12]; @@ -478,7 +478,7 @@ namespace garlic fs = GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); else { - memset (out + offset, 0, 32); // all zeros flags section + memset (out + offset, 0, 32); // all zeros flags section fs = out + offset; } if (!i2p::crypto::AEADChaCha20Poly1305 (fs, 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt @@ -486,14 +486,14 @@ namespace garlic LogPrint (eLogWarning, "Garlic: Flags/static section AEAD encryption failed "); return false; } - + MixHash (out + offset, 48); // h = SHA256(h || ciphertext) offset += 48; // KDF2 if (isStatic) - { + { GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bpk) - MixKey (sharedSecret); + MixKey (sharedSecret); } else CreateNonce (1, nonce); @@ -503,10 +503,10 @@ namespace garlic LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed"); return false; } - + m_State = eSessionStateNewSessionSent; if (isStatic) - { + { MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext) if (GetOwner ()) { @@ -514,11 +514,11 @@ namespace garlic InitNewSessionTagset (tagsetNsr); tagsetNsr->Expire (); // let non-replied session expire GenerateMoreReceiveTags (tagsetNsr, ECIESX25519_NSR_NUM_GENERATED_TAGS); - } + } } return true; } - + bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) { // we are Bob @@ -545,13 +545,13 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key"); return false; - } + } MixKey (sharedSecret); if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // sharedSecret = x25519(besk, apk) { LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); return false; - } + } MixKey (sharedSecret); uint8_t nonce[12]; CreateNonce (0, nonce); @@ -584,10 +584,10 @@ namespace garlic } m_State = eSessionStateNewSessionReplySent; m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch (); - + return true; } - + bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) { // we are Bob and sent NSR already @@ -637,7 +637,7 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: Incorrect Bob ephemeral key"); return false; - } + } MixKey (sharedSecret); GetOwner ()->Decrypt (bepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk) MixKey (sharedSecret); @@ -704,7 +704,7 @@ namespace garlic if (GetOwner ()) GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey); return false; - } + } memcpy (out, &tag, 8); // ad = The session tag, 8 bytes // ciphertext = ENCRYPT(k, n, payload, ad) @@ -736,7 +736,7 @@ namespace garlic } HandlePayload (payload, len - 16, receiveTagset, index); if (GetOwner ()) - { + { int moreTags = 0; if (GetOwner ()->GetNumRatchetInboundTags () > 0) // override in settings? { @@ -745,17 +745,17 @@ namespace garlic index -= GetOwner ()->GetNumRatchetInboundTags (); // trim behind } else - { + { moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4 if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS; moreTags -= (receiveTagset->GetNextIndex () - index); index -= ECIESX25519_MAX_NUM_GENERATED_TAGS; // trim behind - } + } if (moreTags > 0) GenerateMoreReceiveTags (receiveTagset, moreTags); if (index > 0) receiveTagset->SetTrimBehind (index); - } + } return true; } @@ -774,13 +774,13 @@ namespace garlic #endif case eSessionStateEstablished: if (receiveTagset->IsNS ()) - { - // our of sequence NSR + { + // our of sequence NSR LogPrint (eLogDebug, "Garlic: Check for out of order NSR with index ", index); if (receiveTagset->GetNextIndex () - index < ECIESX25519_NSR_NUM_GENERATED_TAGS/2) GenerateMoreReceiveTags (receiveTagset, ECIESX25519_NSR_NUM_GENERATED_TAGS); return HandleNewOutgoingSessionReply (buf, len); - } + } else return HandleExistingSessionMessage (buf, len, receiveTagset, index); case eSessionStateNew: @@ -792,7 +792,7 @@ namespace garlic } return true; } - + std::shared_ptr ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr msg) { uint8_t * payload = GetOwner ()->GetPayloadBuffer (); @@ -829,7 +829,7 @@ namespace garlic if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen, false)) return nullptr; len += 96; - break; + break; default: return nullptr; } @@ -844,18 +844,18 @@ namespace garlic { m_State = eSessionStateOneTime; return WrapSingleMessage (msg); - } - + } + size_t ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr msg, bool first, uint8_t * payload) { uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); size_t payloadLen = 0; if (first) payloadLen += 7;// datatime if (msg) - { + { payloadLen += msg->GetPayloadLength () + 13; if (m_Destination) payloadLen += 32; - } + } if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT) { // resubmit non-confirmed LeaseSet @@ -896,9 +896,9 @@ namespace garlic paddingSize = m_PaddingSizes[m_NextPaddingSize++] & 0x0F; // 0 - 15 if (m_NextPaddingSize >= 32) { - RAND_bytes (m_PaddingSizes, 32); + RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0; - } + } if (delta > 3) { delta -= 3; @@ -914,7 +914,7 @@ namespace garlic { LogPrint (eLogError, "Garlic: Payload length ", payloadLen, " is too long"); return 0; - } + } m_LastSentTimestamp = ts; size_t offset = 0; // DateTime @@ -993,7 +993,7 @@ namespace garlic htobe16buf (payload + offset, paddingSize); offset += 2; memset (payload + offset, 0, paddingSize); offset += paddingSize; } - } + } return payloadLen; } @@ -1050,17 +1050,17 @@ namespace garlic void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags) { if (GetOwner ()) - { + { for (int i = 0; i < numTags; i++) - { + { auto tag = GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset); if (!tag) { LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for receive tagset"); break; - } - } - } + } + } + } } bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts) @@ -1073,9 +1073,9 @@ namespace garlic RouterIncomingRatchetSession::RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState): ECIESX25519AEADRatchetSession (&i2p::context, false) { - SetLeaseSetUpdateStatus (eLeaseSetDoNotSend); + SetLeaseSetUpdateStatus (eLeaseSetDoNotSend); SetNoiseState (initState); - } + } bool RouterIncomingRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len) { @@ -1088,12 +1088,12 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key"); return false; - } + } m_CurrentNoiseState.MixKey (sharedSecret); - buf += 32; len -= 32; + buf += 32; len -= 32; uint8_t nonce[12]; CreateNonce (0, nonce); - std::vector payload (len - 16); + std::vector payload (len - 16); if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_CurrentNoiseState.m_H, 32, m_CurrentNoiseState.m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt { @@ -1102,20 +1102,20 @@ namespace garlic } HandlePayload (payload.data (), len - 16, nullptr, 0); return true; - } + } - static size_t CreateGarlicPayload (std::shared_ptr msg, uint8_t * payload, + static size_t CreateGarlicPayload (std::shared_ptr msg, uint8_t * payload, bool datetime, size_t optimalSize) { size_t len = 0; if (datetime) - { + { // DateTime - payload[0] = eECIESx25519BlkDateTime; + payload[0] = eECIESx25519BlkDateTime; htobe16buf (payload + 1, 4); - htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); + htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); len = 7; - } + } // I2NP payload += len; uint16_t cloveSize = msg->GetPayloadLength () + 10; @@ -1139,14 +1139,14 @@ namespace garlic delta -= 3; if (paddingSize > delta) paddingSize %= delta; } - payload[0] = eECIESx25519BlkPadding; - htobe16buf (payload + 1, paddingSize); + payload[0] = eECIESx25519BlkPadding; + htobe16buf (payload + 1, paddingSize); if (paddingSize) memset (payload + 3, 0, paddingSize); len += paddingSize + 3; - } + } return len; - } - + } + std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag) { auto m = NewI2NPMessage (); @@ -1188,8 +1188,8 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: Incorrect Bob static key"); return nullptr; - } - noiseState.MixKey (sharedSecret); + } + noiseState.MixKey (sharedSecret); auto payload = buf + offset; size_t len = CreateGarlicPayload (msg, payload, true, 900); // 1003 - 32 eph key - 16 Poly1305 hash - 16 I2NP header - 4 garlic length - 35 router tunnel delivery uint8_t nonce[12]; @@ -1205,6 +1205,6 @@ namespace garlic m->len += offset + 4; m->FillI2NPMessageHeader (eI2NPGarlic); return m; - } + } } } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 5fd2c929..0c18814f 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013-2021, The PurpleI2P Project * @@ -28,7 +27,7 @@ namespace garlic { const int ECIESX25519_RESTART_TIMEOUT = 120; // number of second since session creation we can restart session after const int ECIESX25519_INACTIVITY_TIMEOUT = 90; // number of seconds we receive nothing and should restart if we can - const int ECIESX25519_SEND_INACTIVITY_TIMEOUT = 5000; // number of milliseconds we can send empty(pyaload only) packet after + const int ECIESX25519_SEND_INACTIVITY_TIMEOUT = 5000; // number of milliseconds we can send empty(pyaload only) packet after const int ECIESX25519_SEND_EXPIRATION_TIMEOUT = 480; // in seconds const int ECIESX25519_RECEIVE_EXPIRATION_TIMEOUT = 600; // in seconds const int ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT = 180; // 180 @@ -46,7 +45,7 @@ namespace garlic RatchetTagSet () {}; virtual ~RatchetTagSet () {}; - + void DHInitialize (const uint8_t * rootKey, const uint8_t * k); void NextSessionTagRatchet (); uint64_t GetNextSessionTag (); @@ -57,14 +56,14 @@ namespace garlic int GetTagSetID () const { return m_TagSetID; }; void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; }; - + private: i2p::data::Tag<64> m_SessionTagKeyData; uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32]; int m_NextIndex, m_NextSymmKeyIndex; std::unordered_map > m_ItermediateSymmKeys; - + int m_TagSetID = 0; }; @@ -74,27 +73,27 @@ namespace garlic { public: - ReceiveRatchetTagSet (std::shared_ptr session, bool isNS = false): + ReceiveRatchetTagSet (std::shared_ptr session, bool isNS = false): m_Session (session), m_IsNS (isNS) {}; bool IsNS () const { return m_IsNS; }; std::shared_ptr GetSession () { return m_Session; }; - void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; }; + void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; }; int GetTrimBehind () const { return m_TrimBehindIndex; }; - + void Expire (); - bool IsExpired (uint64_t ts) const; - + bool IsExpired (uint64_t ts) const; + virtual bool IsIndexExpired (int index) const; virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index); - + private: - + int m_TrimBehindIndex = 0; std::shared_ptr m_Session; bool m_IsNS; uint64_t m_ExpirationTimestamp = 0; - }; + }; class SymmetricKeyTagSet: public ReceiveRatchetTagSet { @@ -104,13 +103,13 @@ namespace garlic bool IsIndexExpired (int index) const { return false; }; bool HandleNextMessage (uint8_t * buf, size_t len, int index); - + private: GarlicDestination * m_Destination; uint8_t m_Key[32]; - }; - + }; + enum ECIESx25519BlockType { eECIESx25519BlkDateTime = 0, @@ -128,7 +127,7 @@ namespace garlic const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02; const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04; - class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, + class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, private i2p::crypto::NoiseSymmetricState, public std::enable_shared_from_this { @@ -158,10 +157,10 @@ namespace garlic bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index = 0); std::shared_ptr WrapSingleMessage (std::shared_ptr msg); std::shared_ptr WrapOneTimeMessage (std::shared_ptr msg); - + const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; } void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); } - + void Terminate () { m_IsTerminated = true; } void SetDestination (const i2p::data::IdentHash& dest) // TODO: { @@ -171,19 +170,19 @@ namespace garlic bool CheckExpired (uint64_t ts); // true is expired bool CanBeRestarted (uint64_t ts) const { return ts > m_SessionCreatedTimestamp + ECIESX25519_RESTART_TIMEOUT; } bool IsInactive (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_INACTIVITY_TIMEOUT && CanBeRestarted (ts); } - + bool IsRatchets () const { return true; }; bool IsReadyToSend () const { return m_State != eSessionStateNewSessionSent; }; bool IsTerminated () const { return m_IsTerminated; } uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; }; - protected: - + protected: + i2p::crypto::NoiseSymmetricState& GetNoiseState () { return *this; }; void SetNoiseState (const i2p::crypto::NoiseSymmetricState& state) { GetNoiseState () = state; }; void CreateNonce (uint64_t seqn, uint8_t * nonce); void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index); - + private: bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes @@ -198,7 +197,7 @@ namespace garlic bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); - + size_t CreatePayload (std::shared_ptr msg, bool first, uint8_t * payload); size_t CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len); size_t CreateLeaseSetClove (std::shared_ptr ls, uint64_t ts, uint8_t * buf, size_t len); @@ -221,7 +220,7 @@ namespace garlic bool m_SendReverseKey = false, m_SendForwardKey = false, m_IsTerminated = false; std::unique_ptr m_NextReceiveRatchet, m_NextSendRatchet; uint8_t m_PaddingSizes[32], m_NextPaddingSize; - + public: // for HTTP only @@ -240,12 +239,12 @@ namespace garlic RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState); bool HandleNextMessage (const uint8_t * buf, size_t len); i2p::crypto::NoiseSymmetricState& GetCurrentNoiseState () { return m_CurrentNoiseState; }; - + private: i2p::crypto::NoiseSymmetricState m_CurrentNoiseState; - }; - + }; + std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag); std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey); } diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index d01dc1bd..03376f9e 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -452,7 +452,7 @@ namespace garlic { it.second->Terminate (); it.second->SetOwner (nullptr); - } + } m_ECIESx25519Sessions.clear (); m_ECIESx25519Tags.clear (); } @@ -470,14 +470,14 @@ namespace garlic uint64_t t; memcpy (&t, tag, 8); AddECIESx25519Key (key, t); - } + } void GarlicDestination::AddECIESx25519Key (const uint8_t * key, uint64_t tag) { auto tagset = std::make_shared(this, key); m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{0, tagset}); - } - + } + bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) { AddSessionKey (key, tag); @@ -498,10 +498,10 @@ namespace garlic bool found = false; if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) - // try ECIESx25519 tag + // try ECIESx25519 tag found = HandleECIESx25519TagMessage (buf, length); if (!found) - { + { auto it = !mod ? m_Tags.find (SessionTag(buf)) : m_Tags.end (); // AES block is multiple of 16 // AES tag might be used even if encryption type is not ElGamal/AES if (it != m_Tags.end ()) // try AES tag @@ -542,7 +542,7 @@ namespace garlic auto session = std::make_shared (this, false); // incoming if (!session->HandleNextMessage (buf, length, nullptr, 0)) { - // try to generate more tags for last tagset + // try to generate more tags for last tagset if (m_LastTagset && (m_LastTagset->GetNextIndex () - m_LastTagset->GetTrimBehind () < 3*ECIESX25519_MAX_NUM_GENERATED_TAGS)) { uint64_t missingTag; memcpy (&missingTag, buf, 8); @@ -555,24 +555,24 @@ namespace garlic { LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for last tagset"); break; - } + } if (nextTag == missingTag) { LogPrint (eLogDebug, "Garlic: Missing ECIES-X25519-AEAD-Ratchet tag was generated"); if (m_LastTagset->HandleNextMessage (buf, length, m_ECIESx25519Tags[nextTag].index)) found = true; break; - } + } } if (!found) m_LastTagset = nullptr; } if (!found) LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); - } + } } else LogPrint (eLogError, "Garlic: Failed to decrypt message"); - } + } } } @@ -585,14 +585,14 @@ namespace garlic { if (it->second.tagset->HandleNextMessage (buf, len, it->second.index)) m_LastTagset = it->second.tagset; - else + else LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); m_ECIESx25519Tags.erase (it); return true; } return false; - } - + } + void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, std::shared_ptr from) { @@ -759,10 +759,10 @@ namespace garlic if (router->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) return WrapECIESX25519MessageForRouter (msg, router->GetIdentity ()->GetEncryptionPublicKey ()); else - { + { auto session = GetRoutingSession (router, false); return session->WrapSingleMessage (msg); - } + } } std::shared_ptr GarlicDestination::GetRoutingSession ( @@ -776,14 +776,14 @@ namespace garlic destination->Encrypt (nullptr, staticKey); // we are supposed to get static key auto it = m_ECIESx25519Sessions.find (staticKey); if (it != m_ECIESx25519Sessions.end ()) - { + { session = it->second; if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ())) { LogPrint (eLogDebug, "Garlic: Session restarted"); session = nullptr; - } - } + } + } if (!session) { session = std::make_shared (this, true); @@ -879,18 +879,18 @@ namespace garlic it->second.tagset->DeleteSymmKey (it->second.index); it = m_ECIESx25519Tags.erase (it); numExpiredTags++; - } + } else { auto session = it->second.tagset->GetSession (); if (!session || session->IsTerminated()) - { + { it = m_ECIESx25519Tags.erase (it); numExpiredTags++; - } + } else ++it; - } + } } if (numExpiredTags > 0) LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ()); @@ -1099,10 +1099,10 @@ namespace garlic if (it != m_ECIESx25519Sessions.end ()) { if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ())) - { + { it->second->Terminate (); // detach m_ECIESx25519Sessions.erase (it); - } + } else { LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists"); @@ -1127,6 +1127,6 @@ namespace garlic if (!m_PayloadBuffer) m_PayloadBuffer = new uint8_t[I2NP_MAX_MESSAGE_SIZE]; return m_PayloadBuffer; - } + } } } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 0d7b8461..bf7a5a0e 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -115,7 +115,7 @@ namespace garlic virtual bool MessageConfirmed (uint32_t msgID); virtual bool IsRatchets () const { return false; }; virtual bool IsReadyToSend () const { return true; }; - virtual bool IsTerminated () const { return !GetOwner (); }; + virtual bool IsTerminated () const { return !GetOwner (); }; virtual uint64_t GetLastActivityTimestamp () const { return 0; }; // non-zero for rathets only void SetLeaseSetUpdated () @@ -251,7 +251,7 @@ namespace garlic void RemoveECIESx25519Session (const uint8_t * staticKey); void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); uint8_t * GetPayloadBuffer (); - + virtual void ProcessGarlicMessage (std::shared_ptr msg); virtual void ProcessDeliveryStatusMessage (std::shared_ptr msg); virtual void SetLeaseSetUpdated (); diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index 6ad245f0..c5792a37 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -14,9 +14,9 @@ #include "Base.h" #include "HTTP.h" -namespace i2p +namespace i2p { -namespace http +namespace http { const std::vector HTTP_METHODS = { "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "CONNECT", // HTTP basic methods @@ -476,14 +476,14 @@ namespace http return ptr; } - std::string UrlDecode(const std::string& data, bool allow_null) + std::string UrlDecode(const std::string& data, bool allow_null) { std::string decoded(data); size_t pos = 0; - while ((pos = decoded.find('%', pos)) != std::string::npos) + while ((pos = decoded.find('%', pos)) != std::string::npos) { char c = strtol(decoded.substr(pos + 1, 2).c_str(), NULL, 16); - if (c == '\0' && !allow_null) + if (c == '\0' && !allow_null) { pos += 3; continue; @@ -494,10 +494,10 @@ namespace http return decoded; } - bool MergeChunkedResponse (std::istream& in, std::ostream& out) + bool MergeChunkedResponse (std::istream& in, std::ostream& out) { std::string hexLen; - while (!in.eof ()) + while (!in.eof ()) { std::getline (in, hexLen); errno = 0; @@ -522,6 +522,6 @@ namespace http if (user.empty () && pass.empty ()) return ""; return "Basic " + i2p::data::ToBase64Standard (user + ":" + pass); } - + } // http } // i2p diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index 1d73461e..6a322c18 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -167,8 +167,8 @@ namespace http */ bool MergeChunkedResponse (std::istream& in, std::ostream& out); - std::string CreateBasicAuthorizationString (const std::string& user, const std::string& pass); - + std::string CreateBasicAuthorizationString (const std::string& user, const std::string& pass); + } // http } // i2p diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 6cbf9b12..229bfbf3 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -170,8 +170,8 @@ namespace i2p std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, const std::set& excludedFloodfills, - std::shared_ptr replyTunnel, const uint8_t * replyKey, - const uint8_t * replyTag, bool replyECIES) + std::shared_ptr replyTunnel, const uint8_t * replyKey, + const uint8_t * replyTag, bool replyECIES) { int cnt = excludedFloodfills.size (); auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage (); @@ -243,8 +243,8 @@ namespace i2p return m; } - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router, - uint32_t replyToken, std::shared_ptr replyTunnel) + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router, + uint32_t replyToken, std::shared_ptr replyTunnel) { if (!router) // we send own RouterInfo router = context.GetSharedRouterInfo (); @@ -398,7 +398,7 @@ namespace i2p retCode = 30; // always reject with bandwidth reason (30) memset (record + ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options - record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode; + record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode; // encrypt reply i2p::crypto::CBCEncryption encryption; for (int j = 0; j < num; j++) @@ -409,7 +409,7 @@ namespace i2p uint8_t nonce[12]; memset (nonce, 0, 12); auto& noiseState = i2p::context.GetCurrentNoiseState (); - if (!i2p::crypto::AEADChaCha20Poly1305 (reply, TUNNEL_BUILD_RECORD_SIZE - 16, + if (!i2p::crypto::AEADChaCha20Poly1305 (reply, TUNNEL_BUILD_RECORD_SIZE - 16, noiseState.m_H, 32, noiseState.m_CK, nonce, reply, TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt { LogPrint (eLogWarning, "I2NP: Reply AEAD encryption failed"); @@ -547,7 +547,7 @@ namespace i2p { LogPrint (eLogDebug, "I2NP: Short request record ", i, " is ours"); uint8_t clearText[SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE]; - if (!i2p::context.DecryptTunnelShortRequestRecord (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) + if (!i2p::context.DecryptTunnelShortRequestRecord (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) { LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i); return; @@ -558,10 +558,10 @@ namespace i2p return; } auto& noiseState = i2p::context.GetCurrentNoiseState (); - uint8_t replyKey[32], layerKey[32], ivKey[32]; + uint8_t replyKey[32], layerKey[32], ivKey[32]; i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK); memcpy (replyKey, noiseState.m_CK + 32, 32); - i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK); + i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK); memcpy (layerKey, noiseState.m_CK + 32, 32); bool isEndpoint = clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG; if (isEndpoint) @@ -602,8 +602,8 @@ namespace i2p if (j == i) { memset (reply + SHORT_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options - reply[SHORT_RESPONSE_RECORD_RET_OFFSET] = retCode; - if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16, + reply[SHORT_RESPONSE_RECORD_RET_OFFSET] = retCode; + if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16, noiseState.m_H, 32, replyKey, nonce, reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt { LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed"); @@ -611,7 +611,7 @@ namespace i2p } } else - i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, reply); + i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, reply); reply += SHORT_TUNNEL_BUILD_RECORD_SIZE; } // send reply @@ -620,10 +620,10 @@ namespace i2p auto replyMsg = NewI2NPShortMessage (); replyMsg->Concat (buf, len); replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); - if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), + if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local? { - i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "RGarlicKeyAndTag", noiseState.m_CK); + i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "RGarlicKeyAndTag", noiseState.m_CK); uint64_t tag; memcpy (&tag, noiseState.m_CK, 8); // we send it to reply tunnel diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index c8bf1697..f55975c4 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -56,7 +56,7 @@ namespace i2p // TunnelBuild const size_t TUNNEL_BUILD_RECORD_SIZE = 528; const size_t SHORT_TUNNEL_BUILD_RECORD_SIZE = 218; - + // BuildRequestRecordEncrypted const size_t BUILD_REQUEST_RECORD_TO_PEER_OFFSET = 0; const size_t BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET = BUILD_REQUEST_RECORD_TO_PEER_OFFSET + 16; @@ -98,7 +98,7 @@ namespace i2p // ShortResponseRecord const size_t SHORT_RESPONSE_RECORD_OPTIONS_OFFSET = 0; const size_t SHORT_RESPONSE_RECORD_RET_OFFSET = 201; - + enum I2NPMessageType { eI2NPDummyMsg = 0, @@ -273,8 +273,8 @@ namespace tunnel std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, uint32_t replyTunnelID, bool exploratory = false, std::set * excludedPeers = nullptr); std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, - const std::set& excludedFloodfills, - std::shared_ptr replyTunnel, + const std::set& excludedFloodfills, + std::shared_ptr replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false); std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector routers); diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index b3a49d4e..8aacf4de 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -53,9 +53,9 @@ namespace data { memcpy (m_StandardIdentity.publicKey, publicKey, 32); RAND_bytes (m_StandardIdentity.publicKey + 32, 224); - } - else - memcpy (m_StandardIdentity.publicKey, publicKey, 256); + } + else + memcpy (m_StandardIdentity.publicKey, publicKey, 256); if (type != SIGNING_KEY_TYPE_DSA_SHA1) { size_t excessLen = 0; @@ -128,7 +128,7 @@ namespace data { LogPrint (eLogError, "Identity: Unexpected excessive signing key len ", excessLen); excessLen = MAX_EXTENDED_BUFFER_SIZE - 4; - } + } memcpy (m_ExtendedBuffer + 4, excessBuf, excessLen); delete[] excessBuf; } @@ -480,7 +480,7 @@ namespace data size_t ret = m_Public->FromBuffer (buf, len); auto cryptoKeyLen = GetPrivateKeyLen (); if (!ret || ret + cryptoKeyLen > len) return 0; // overflow - memcpy (m_PrivateKey, buf + ret, cryptoKeyLen); + memcpy (m_PrivateKey, buf + ret, cryptoKeyLen); ret += cryptoKeyLen; size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); if(signingPrivateKeySize + ret > len || signingPrivateKeySize > 128) return 0; // overflow @@ -654,9 +654,9 @@ namespace data size_t PrivateKeys::GetPrivateKeyLen () const { // private key length always 256, but type 4 - return (m_Public->GetCryptoKeyType () == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) ? 32 : 256; - } - + return (m_Public->GetCryptoKeyType () == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) ? 32 : 256; + } + uint8_t * PrivateKeys::GetPadding() { if(m_Public->GetSigningKeyType () == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519) @@ -681,7 +681,7 @@ namespace data break; case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return std::make_shared(key); - break; + break; case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST: return std::make_shared(key); diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index f96d5f41..8f35845d 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -84,9 +84,9 @@ namespace data typedef uint16_t SigningKeyType; typedef uint16_t CryptoKeyType; - const size_t MAX_EXTENDED_BUFFER_SIZE = 8; // cryptoKeyType + signingKeyType + 4 extra bytes of P521 + const size_t MAX_EXTENDED_BUFFER_SIZE = 8; // cryptoKeyType + signingKeyType + 4 extra bytes of P521 class IdentityEx - { + { public: IdentityEx (); @@ -138,7 +138,7 @@ namespace data mutable i2p::crypto::Verifier * m_Verifier = nullptr; mutable std::mutex m_VerifierMutex; size_t m_ExtendedLen; - uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE]; + uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE]; }; class PrivateKeys // for eepsites diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index c74a6f13..0af06377 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -77,7 +77,7 @@ namespace data LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen); m_IsValid = false; return; - } + } uint8_t num = m_Buffer[size]; size++; // num LogPrint (eLogDebug, "LeaseSet: Read num=", (int)num); @@ -87,13 +87,13 @@ namespace data m_IsValid = false; return; } - if (size + num*LEASE_SIZE > m_BufferLen) - { + if (size + num*LEASE_SIZE > m_BufferLen) + { LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen); m_IsValid = false; return; - } - + } + UpdateLeasesBegin (); // process leases m_ExpirationTime = 0; @@ -121,13 +121,13 @@ namespace data // verify if (verifySignature) - { + { auto signedSize = leases - m_Buffer; if (signedSize + m_Identity->GetSignatureLen () > m_BufferLen) { LogPrint (eLogError, "LeaseSet: Signature exceeds buffer size ", m_BufferLen); m_IsValid = false; - } + } else if (!m_Identity->Verify (m_Buffer, signedSize, leases)) { LogPrint (eLogWarning, "LeaseSet: Verification failed"); @@ -863,17 +863,17 @@ namespace data } // update expiration if (expirationTime) - { + { SetExpirationTime (expirationTime*1000LL); auto expires = (int)expirationTime - timestamp; htobe16buf (expiresBuf, expires > 0 ? expires : 0); - } + } else { // no tunnels or withdraw SetExpirationTime (timestamp*1000LL); memset (expiresBuf, 0, 2); // expires immeditely - } + } // sign keys.Sign (m_Buffer, offset, m_Buffer + offset); // LS + leading store type } @@ -916,7 +916,7 @@ namespace data { LogPrint (eLogError, "LeaseSet2: Can't create blinded signer for signature type ", blindedKey.GetSigType ()); return; - } + } auto offset = 1; htobe16buf (m_Buffer + offset, blindedKey.GetBlindedSigType ()); offset += 2; // Blinded Public Key Sig Type memcpy (m_Buffer + offset, blindedPub, publicKeyLen); offset += publicKeyLen; // Blinded Public Key diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 1d1b84f8..487cf680 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -329,7 +329,7 @@ namespace transport m_SendSipKey (nullptr), m_ReceiveSipKey (nullptr), #endif m_NextReceivedLen (0), m_NextReceivedBuffer (nullptr), m_NextSendBuffer (nullptr), - m_NextReceivedBufferSize (0), m_ReceiveSequenceNumber (0), m_SendSequenceNumber (0), + m_NextReceivedBufferSize (0), m_ReceiveSequenceNumber (0), m_SendSequenceNumber (0), m_IsSending (false), m_IsReceiving (false), m_NextPaddingSize (16) { if (in_RemoteRouter) // Alice @@ -401,7 +401,7 @@ namespace transport } void NTCP2Session::CreateNextReceivedBuffer (size_t size) - { + { if (m_NextReceivedBuffer) { if (size <= m_NextReceivedBufferSize) @@ -411,19 +411,19 @@ namespace transport } m_NextReceivedBuffer = new uint8_t[size]; m_NextReceivedBufferSize = size; - } + } void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts) { - if (m_NextReceivedBuffer && !m_IsReceiving && + if (m_NextReceivedBuffer && !m_IsReceiving && ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT) { delete[] m_NextReceivedBuffer; m_NextReceivedBuffer = nullptr; m_NextReceivedBufferSize = 0; - } - } - + } + } + void NTCP2Session::KeyDerivationFunctionDataPhase () { uint8_t k[64]; @@ -716,7 +716,7 @@ namespace transport EVP_DigestSignInit (m_SendMDCtx, &ctx, nullptr, nullptr, sipKey); EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr); EVP_PKEY_free (sipKey); - + sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, receiveSipKey, 16); m_ReceiveMDCtx = EVP_MD_CTX_create (); ctx = nullptr; @@ -879,11 +879,11 @@ namespace transport auto nextMsg = (frame[offset] == eI2NPTunnelData) ? NewI2NPTunnelMessage (true) : NewI2NPMessage (size); nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header if (nextMsg->len <= nextMsg->maxLen) - { + { memcpy (nextMsg->GetNTCP2Header (), frame + offset, size); nextMsg->FromNTCP2 (); m_Handler.PutNextMessage (std::move (nextMsg)); - } + } else LogPrint (eLogError, "NTCP2: I2NP block is too long for I2NP message"); break; @@ -914,7 +914,7 @@ namespace transport EVP_DigestSignInit (m_SendMDCtx, nullptr, nullptr, nullptr, nullptr); EVP_DigestSignUpdate (m_SendMDCtx, m_SendIV.buf, 8); size_t l = 8; - EVP_DigestSignFinal (m_SendMDCtx, m_SendIV.buf, &l); + EVP_DigestSignFinal (m_SendMDCtx, m_SendIV.buf, &l); #else i2p::crypto::Siphash<8> (m_SendIV.buf, m_SendIV.buf, 8, m_SendSipKey); #endif @@ -1081,15 +1081,15 @@ namespace transport size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100; if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; if (paddingSize > len) paddingSize = len; - if (paddingSize) + if (paddingSize) { if (m_NextPaddingSize >= 16) { RAND_bytes ((uint8_t *)m_PaddingSizes, sizeof (m_PaddingSizes)); m_NextPaddingSize = 0; - } + } paddingSize = m_PaddingSizes[m_NextPaddingSize++] % paddingSize; - } + } buf[0] = eNTCP2BlkPadding; // blk htobe16buf (buf + 1, paddingSize); // size memset (buf + 3, 0, paddingSize); @@ -1120,7 +1120,7 @@ namespace transport !m_SendMDCtx #else !m_SendSipKey -#endif +#endif ) return; m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block // termination block diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 3516ce6a..7a513774 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -42,7 +42,7 @@ namespace transport const int NTCP2_CLOCK_SKEW = 60; // in seconds const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up - + enum NTCP2BlockType { eNTCP2BlkDateTime = 0, @@ -118,7 +118,7 @@ namespace transport i2p::data::IdentHash m_RemoteIdentHash; uint16_t m3p2Len; - uint8_t m_SessionRequestBuffer[NTCP2_SESSION_REQUEST_MAX_SIZE], + uint8_t m_SessionRequestBuffer[NTCP2_SESSION_REQUEST_MAX_SIZE], m_SessionCreatedBuffer[NTCP2_SESSION_CREATED_MAX_SIZE], * m_SessionConfirmedBuffer; size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen; @@ -137,7 +137,7 @@ namespace transport void Done (); void Close () { m_Socket.close (); }; // for accept void DeleteNextReceiveBuffer (uint64_t ts); - + boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; const boost::asio::ip::tcp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; void SetRemoteEndpoint (const boost::asio::ip::tcp::endpoint& ep) { m_RemoteEndpoint = ep; }; @@ -226,7 +226,7 @@ namespace transport uint64_t m_NextRouterInfoResendTime; // seconds since epoch uint16_t m_PaddingSizes[16]; - int m_NextPaddingSize; + int m_NextPaddingSize; }; class NTCP2Server: private i2p::util::RunnableServiceWithWork @@ -258,7 +258,7 @@ namespace transport void UseProxy(ProxyType proxy, const std::string& address, uint16_t port, const std::string& user, const std::string& pass); void SetLocalAddress (const boost::asio::ip::address& localAddress); - + private: void HandleAccept (std::shared_ptr conn, const boost::system::error_code& error); @@ -267,7 +267,7 @@ namespace transport void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer); void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer); void AfterSocksHandshake(std::shared_ptr conn, std::shared_ptr timer); - + // timer void ScheduleTermination (); void HandleTerminationTimer (const boost::system::error_code& ecode); @@ -285,7 +285,7 @@ namespace transport boost::asio::ip::tcp::resolver m_Resolver; std::unique_ptr m_ProxyEndpoint; std::shared_ptr m_Address4, m_Address6, m_YggdrasilAddress; - + public: // for HTTP/I2PControl diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 228eac71..4ed51312 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -56,9 +56,9 @@ namespace data uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold); if (m_RouterInfos.size () < threshold || m_Floodfills.size () < NETDB_MIN_FLOODFILLS) // reseed if # of router less than threshold or too few floodfiils - { + { Reseed (); - } + } else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false)) Reseed (); // we don't have a router we can connect to. Trying to reseed @@ -73,7 +73,7 @@ namespace data m_RouterInfos.emplace (i2p::context.GetIdentHash (), i2p::context.GetSharedRouterInfo ()); if (i2p::context.IsFloodfill ()) m_Floodfills.push_back (i2p::context.GetSharedRouterInfo ()); - + i2p::config::GetOption("persist.profiles", m_PersistProfiles); m_IsRunning = true; @@ -148,7 +148,7 @@ namespace data } if (!m_IsRunning) break; if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline - + uint64_t ts = i2p::util::GetSecondsSinceEpoch (); if (ts - lastManageRequest >= 15) // manage requests every 15 seconds { @@ -170,8 +170,8 @@ namespace data lastDestinationCleanup = ts; } - // publish - if (!m_HiddenMode && i2p::transport::transports.IsOnline ()) + // publish + if (!m_HiddenMode && i2p::transport::transports.IsOnline ()) { bool publish = false; if (m_PublishReplyToken) @@ -179,15 +179,15 @@ namespace data // next publishing attempt if (ts - lastPublish >= NETDB_PUBLISH_CONFIRMATION_TIMEOUT) publish = true; } - else if (i2p::context.GetLastUpdateTime () > lastPublish || - ts - lastPublish >= NETDB_PUBLISH_INTERVAL) - { + else if (i2p::context.GetLastUpdateTime () > lastPublish || + ts - lastPublish >= NETDB_PUBLISH_INTERVAL) + { // new publish m_PublishExcluded.clear (); if (i2p::context.IsFloodfill ()) m_PublishExcluded.insert (i2p::context.GetIdentHash ()); // do publish to ourselves publish = true; - } + } if (publish) // update timestamp and publish { i2p::context.UpdateTimestamp (ts); @@ -290,7 +290,7 @@ namespace data if (inserted) { LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); - if (r->IsFloodfill () && r->IsEligibleFloodfill ()) + if (r->IsFloodfill () && r->IsEligibleFloodfill ()) { std::unique_lock l(m_FloodfillsMutex); m_Floodfills.push_back (r); @@ -476,14 +476,14 @@ namespace data { auto r = std::make_shared(path); if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses ()) - { + { r->DeleteBuffer (); r->ClearProperties (); // properties are not used for regular routers if (m_RouterInfos.emplace (r->GetIdentHash (), r).second) - { + { if (r->IsFloodfill () && r->IsEligibleFloodfill ()) m_Floodfills.push_back (r); - } + } } else { @@ -591,7 +591,7 @@ namespace data expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL : NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; - auto own = i2p::context.GetSharedRouterInfo (); + auto own = i2p::context.GetSharedRouterInfo (); for (auto& it: m_RouterInfos) { if (it.second == own) continue; // skip own @@ -608,8 +608,8 @@ namespace data } // make router reachable back if too few routers or floodfills if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || - (it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS))) - it.second->SetUnreachable (false); + (it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS))) + it.second->SetUnreachable (false); // find & mark expired routers if (!it.second->IsReachable () && it.second->IsSSU (false)) { @@ -626,7 +626,7 @@ namespace data // delete RI file m_Storage.Remove(ident); deletedCount++; - if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false; + if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false; } } // m_RouterInfos iteration @@ -674,7 +674,7 @@ namespace data if (floodfill) { if (direct && !floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) && - !i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) + !i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) direct = false; // floodfill can't be reached directly if (direct) transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); @@ -688,10 +688,10 @@ namespace data else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found"); - m_Requests.RequestComplete (destination, nullptr); - } - } - } + m_Requests.RequestComplete (destination, nullptr); + } + } + } else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found"); @@ -1051,8 +1051,8 @@ namespace data m_PublishExcluded.clear (); m_PublishReplyToken = 0; } - } - + } + void NetDb::Explore (int numDestinations) { // new requests @@ -1112,7 +1112,7 @@ namespace data LogPrint (eLogError, "NetDb: Couldn't publish our RouterInfo to ", NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS, " closest routers. Try again"); m_PublishExcluded.clear (); } - + auto floodfill = GetClosestFloodfill (i2p::context.GetIdentHash (), m_PublishExcluded); if (floodfill) { @@ -1122,19 +1122,19 @@ namespace data m_PublishExcluded.insert (floodfill->GetIdentHash ()); m_PublishReplyToken = replyToken; if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect? - i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ? + i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ? // send directly transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); else { - // otherwise through exploratory + // otherwise through exploratory auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr; - auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; + auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; if (inbound && outbound) - outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, - CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound)); - } + outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, + CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound)); + } } } @@ -1174,7 +1174,7 @@ namespace data { return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : - router->IsReachableFrom (*compatibleWith)) && + router->IsReachableFrom (*compatibleWith)) && router->IsECIES (); }); } @@ -1184,7 +1184,7 @@ namespace data return GetRandomRouter ( [v4, &excluded](std::shared_ptr router)->bool { - return !router->IsHidden () && router->IsECIES () && + return !router->IsHidden () && router->IsECIES () && router->IsPeerTesting (v4) && !excluded.count (router->GetIdentHash ()); }); } @@ -1216,7 +1216,7 @@ namespace data return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : router->IsReachableFrom (*compatibleWith)) && - (router->GetCaps () & RouterInfo::eHighBandwidth) && + (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && router->IsECIES (); }); @@ -1238,12 +1238,12 @@ namespace data return it->second; // try some routers around auto it1 = m_RouterInfos.begin (); - if (inds[0]) + if (inds[0]) { // before - inds[1] %= inds[0]; + inds[1] %= inds[0]; std::advance (it1, (inds[1] + inds[0])/2); - } + } else it1 = it; auto it2 = it; @@ -1254,7 +1254,7 @@ namespace data std::advance (it2, inds[2]); } // it1 - from, it2 - to - it = it1; + it = it1; while (it != it2 && it != m_RouterInfos.end ()) { if (!it->second->IsUnreachable () && filter (it->second)) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 097f92e7..ddac573e 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -43,7 +43,7 @@ namespace data const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours const int NETDB_PUBLISH_INTERVAL = 60 * 40; const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds - const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; + const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 36); // 0.9.36 const int NETDB_MIN_FLOODFILL_VERSION = MAKE_VERSION_NUMBER(0, 9, 38); // 0.9.38 const int NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 08e99a18..0e97cc5d 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -84,15 +84,15 @@ namespace data { bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool ipv4; i2p::config::GetOption("ipv4", ipv4); - + std::vector httpsReseedHostList; if (ipv4 || ipv6) - { + { std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs); if (!reseedURLs.empty ()) boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on); } - + std::vector yggReseedHostList; if (!i2p::util::net::GetYggdrasilAddress ().is_unspecified ()) { @@ -100,7 +100,7 @@ namespace data std::string yggReseedURLs; i2p::config::GetOption("reseed.yggurls", yggReseedURLs); if (!yggReseedURLs.empty ()) boost::split(yggReseedHostList, yggReseedURLs, boost::is_any_of(","), boost::token_compress_on); - } + } if (httpsReseedHostList.empty () && yggReseedHostList.empty()) { @@ -113,7 +113,7 @@ namespace data { auto ind = rand () % (httpsReseedHostList.size () + yggReseedHostList.size ()); bool isHttps = ind < httpsReseedHostList.size (); - std::string reseedUrl = isHttps ? httpsReseedHostList[ind] : + std::string reseedUrl = isHttps ? httpsReseedHostList[ind] : yggReseedHostList[ind - httpsReseedHostList.size ()]; reseedUrl += "i2pseeds.su3"; auto num = ReseedFromSU3Url (reseedUrl, isHttps); @@ -680,30 +680,30 @@ namespace data auto it = boost::asio::ip::tcp::resolver(service).resolve ( boost::asio::ip::tcp::resolver::query (url.host, std::to_string(url.port)), ecode); if (!ecode) - { + { bool connected = false; boost::asio::ip::tcp::resolver::iterator end; while (it != end) - { + { boost::asio::ip::tcp::endpoint ep = *it; if ((ep.address ().is_v4 () && i2p::context.SupportsV4 ()) || (ep.address ().is_v6 () && i2p::context.SupportsV6 ())) - { + { s.lowest_layer().connect (ep, ecode); if (!ecode) { connected = true; break; - } - } + } + } it++; } if (!connected) { LogPrint(eLogError, "Reseed: Failed to connect to ", url.host); return ""; - } - } + } + } } if (!ecode) { @@ -762,12 +762,12 @@ namespace data data = out.str(); } return data; - } + } std::string Reseeder::YggdrasilRequest (const std::string& address) { i2p::http::URL url; - if (!url.parse(address)) + if (!url.parse(address)) { LogPrint(eLogError, "Reseed: Failed to parse url: ", address); return ""; @@ -776,7 +776,7 @@ namespace data if (!url.port) url.port = 80; boost::system::error_code ecode; - boost::asio::io_service service; + boost::asio::io_service service; boost::asio::ip::tcp::socket s(service, boost::asio::ip::tcp::v6()); if (url.host.length () < 2) return ""; // assume [] @@ -789,9 +789,9 @@ namespace data return ReseedRequest (s, url.to_string()); } else - LogPrint (eLogError, "Reseed: Couldn't connect to Yggdrasil ", url.host, ": ", ecode.message ()); - + LogPrint (eLogError, "Reseed: Couldn't connect to Yggdrasil ", url.host, ": ", ecode.message ()); + return ""; - } + } } } diff --git a/libi2pd/Reseed.h b/libi2pd/Reseed.h index 8039c07e..a6de6fa4 100644 --- a/libi2pd/Reseed.h +++ b/libi2pd/Reseed.h @@ -49,8 +49,8 @@ namespace data std::string HttpsRequest (const std::string& address); std::string YggdrasilRequest (const std::string& address); template - std::string ReseedRequest (Stream& s, const std::string& uri); - + std::string ReseedRequest (Stream& s, const std::string& uri); + private: std::map m_SigningKeys; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 3710092b..cc08006a 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -566,10 +566,10 @@ namespace i2p { bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); - if (ntcp2) + if (ntcp2) { if (ntcp2Published) - { + { std::string ntcp2Host; if (!i2p::config::IsDefault ("ntcp2.addressv6")) i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host); @@ -578,7 +578,7 @@ namespace i2p uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); if (!ntcp2Port) ntcp2Port = port; m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port); - } + } else m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address(), 0, i2p::data::RouterInfo::eV6); } @@ -839,13 +839,13 @@ namespace i2p } buf += 4; if (!HandleECIESx25519TagMessage (buf, len)) // try tag first - { + { // then Noise_N one-time decryption if (m_ECIESSession) m_ECIESSession->HandleNextMessage (buf, len); else LogPrint (eLogError, "Router: Session is not set for ECIES router"); - } + } } void RouterContext::ProcessDeliveryStatusMessage (std::shared_ptr msg) @@ -881,7 +881,7 @@ namespace i2p } bool RouterContext::DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize) - { + { // m_InitialNoiseState is h = SHA256(h || hepk) m_CurrentNoiseState = m_InitialNoiseState; m_CurrentNoiseState.MixHash (encrypted, 32); // h = SHA256(h || sepk) @@ -895,7 +895,7 @@ namespace i2p encrypted += 32; uint8_t nonce[12]; memset (nonce, 0, 12); - if (!i2p::crypto::AEADChaCha20Poly1305 (encrypted, clearTextSize, m_CurrentNoiseState.m_H, 32, + if (!i2p::crypto::AEADChaCha20Poly1305 (encrypted, clearTextSize, m_CurrentNoiseState.m_H, 32, m_CurrentNoiseState.m_CK + 32, nonce, data, clearTextSize, false)) // decrypt { LogPrint (eLogWarning, "Router: Tunnel record AEAD decryption failed"); @@ -908,8 +908,8 @@ namespace i2p bool RouterContext::DecryptTunnelShortRequestRecord (const uint8_t * encrypted, uint8_t * data) { return DecryptECIESTunnelBuildRecord (encrypted, data, SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE); - } - + } + i2p::crypto::X25519Keys& RouterContext::GetStaticKeys () { if (!m_StaticKeys) diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 647c1a7f..e237a1b9 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -67,7 +67,7 @@ namespace garlic void Init (); const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; - i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; }; + i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; }; std::shared_ptr GetSharedRouterInfo () { return std::shared_ptr (&m_RouterInfo, @@ -97,7 +97,7 @@ namespace garlic void SetNetID (int netID) { m_NetID = netID; }; bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data); bool DecryptTunnelShortRequestRecord (const uint8_t * encrypted, uint8_t * data); - + void UpdatePort (int port); // called from Daemon void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon void PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg); @@ -160,7 +160,7 @@ namespace garlic void SaveKeys (); bool DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize); - + private: i2p::data::RouterInfo m_RouterInfo; diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 2df7ba99..36437cc1 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -194,7 +194,7 @@ namespace data // read addresses auto addresses = boost::make_shared(); uint8_t numAddresses; - s.read ((char *)&numAddresses, sizeof (numAddresses)); + s.read ((char *)&numAddresses, sizeof (numAddresses)); addresses->reserve (numAddresses); for (int i = 0; i < numAddresses; i++) { @@ -207,10 +207,10 @@ namespace data char transportStyle[6]; ReadString (transportStyle, 6, s); if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2 - { + { address->transportStyle = eTransportNTCP; address->ntcp2.reset (new NTCP2Ext ()); - } + } else if (!strcmp (transportStyle, "SSU")) { address->transportStyle = eTransportSSU; @@ -283,11 +283,11 @@ namespace data if (s) continue; else return; } if (index >= address->ssu->introducers.size ()) - { + { if (address->ssu->introducers.empty ()) // first time address->ssu->introducers.reserve (3); address->ssu->introducers.resize (index + 1); - } + } Introducer& introducer = address->ssu->introducers.at (index); if (!strcmp (key, "ihost")) { @@ -308,39 +308,39 @@ namespace data if (address->transportStyle == eTransportNTCP) { if (isStaticKey) - { + { if (isHost) { if (address->host.is_v6 ()) supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6); else - supportedTransports |= eNTCP2V4; + supportedTransports |= eNTCP2V4; m_ReachableTransports |= supportedTransports; - } + } else if (!address->published) { if (address->caps) - { + { if (address->caps & AddressCaps::eV4) supportedTransports |= eNTCP2V4; if (address->caps & AddressCaps::eV6) supportedTransports |= eNTCP2V6; } else supportedTransports |= eNTCP2V4; // most likely, since we don't have host - } + } } - } + } else if (address->transportStyle == eTransportSSU) { if (isIntroKey) { if (isHost) supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6; - else if (address->caps & AddressCaps::eV6) - { + else if (address->caps & AddressCaps::eV6) + { supportedTransports |= eSSUV6; if (address->caps & AddressCaps::eV4) supportedTransports |= eSSUV4; // in additional to v6 - } - else + } + else supportedTransports |= eSSUV4; // in case if host or 6 caps is not preasented, we assume 4 if (address->ssu && !address->ssu->introducers.empty ()) { @@ -350,24 +350,24 @@ namespace data for (auto& it: address->ssu->introducers) { if (!it.iExp) it.iExp = m_Timestamp/1000 + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT; - if (ts <= it.iExp && it.iPort > 0 && - ((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ()))) + if (ts <= it.iExp && it.iPort > 0 && + ((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ()))) numValid++; else it.iPort = 0; - } + } if (numValid) m_ReachableTransports |= supportedTransports; - else + else address->ssu->introducers.resize (0); - } + } else if (isHost && address->port) - { + { address->published = true; m_ReachableTransports |= supportedTransports; - } - } - } + } + } + } if (supportedTransports) { addresses->push_back(address); @@ -492,10 +492,10 @@ namespace data { case CAPS_FLAG_V4: caps |= AddressCaps::eV4; - break; + break; case CAPS_FLAG_V6: caps |= AddressCaps::eV6; - break; + break; case CAPS_FLAG_SSU_TESTING: caps |= AddressCaps::eSSUTesting; break; @@ -508,7 +508,7 @@ namespace data } return caps; } - + void RouterInfo::UpdateCapsProperty () { std::string caps; @@ -559,7 +559,7 @@ namespace data if (address.transportStyle == eTransportNTCP) { if (address.IsNTCP2 ()) - { + { WriteString ("NTCP2", s); if (address.IsPublishedNTCP2 () && !address.host.is_unspecified () && address.port) isPublished = true; @@ -573,45 +573,45 @@ namespace data if (caps.empty ()) caps += CAPS_FLAG_V4; WriteString (caps, properties); properties << ';'; - } - } + } + } else continue; // don't write NTCP address - } + } else if (address.transportStyle == eTransportSSU) { WriteString ("SSU", s); // caps WriteString ("caps", properties); properties << '='; - std::string caps; + std::string caps; if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING; if (address.host.is_v4 ()) - { + { if (address.published) - { + { isPublished = true; if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; - } + } else caps += CAPS_FLAG_V4; } else if (address.host.is_v6 ()) - { + { if (address.published) - { + { isPublished = true; if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; - } + } else caps += CAPS_FLAG_V6; - } + } else { if (address.IsV4 ()) caps += CAPS_FLAG_V4; if (address.IsV6 ()) caps += CAPS_FLAG_V6; if (caps.empty ()) caps += CAPS_FLAG_V4; - } + } WriteString (caps, properties); properties << ';'; } @@ -789,7 +789,7 @@ namespace data bool RouterInfo::SaveToFile (const std::string& fullPath) { - if (!m_Buffer) + if (!m_Buffer) { LogPrint (eLogError, "RouterInfo: Can't save, m_Buffer == NULL"); return false; @@ -851,13 +851,13 @@ namespace data m_Addresses->push_back(std::move(addr)); } - void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, + void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host, int port, uint8_t caps) { auto addr = std::make_shared
(); addr->host = host; addr->port = port; - addr->transportStyle = eTransportNTCP; + addr->transportStyle = eTransportNTCP; addr->caps = caps; addr->date = 0; addr->ntcp2.reset (new NTCP2Ext ()); @@ -868,12 +868,12 @@ namespace data { m_SupportedTransports |= eNTCP2V4; if (addr->published) m_ReachableTransports |= eNTCP2V4; - } + } if (addr->IsV6 ()) { m_SupportedTransports |= eNTCP2V6; if (addr->published) m_ReachableTransports |= eNTCP2V6; - } + } m_Addresses->push_back(std::move(addr)); } @@ -881,7 +881,7 @@ namespace data { for (auto& addr : *m_Addresses) { - if (addr->transportStyle == eTransportSSU && + if (addr->transportStyle == eTransportSSU && ((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ()))) { for (auto& intro: addr->ssu->introducers) @@ -898,7 +898,7 @@ namespace data { for (auto& addr: *m_Addresses) { - if (addr->transportStyle == eTransportSSU && + if (addr->transportStyle == eTransportSSU && ((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ()))) { for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) @@ -969,8 +969,8 @@ namespace data bool RouterInfo::IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; - } - + } + bool RouterInfo::IsV6 () const { return m_SupportedTransports & (eSSUV6 | eNTCP2V6); @@ -984,28 +984,28 @@ namespace data bool RouterInfo::IsMesh () const { return m_SupportedTransports & eNTCP2V6Mesh; - } - + } + void RouterInfo::EnableV6 () { if (!IsV6 ()) - { + { uint8_t addressCaps = AddressCaps::eV6; if (IsV4 ()) addressCaps |= AddressCaps::eV4; SetUnreachableAddressesTransportCaps (addressCaps); UpdateSupportedTransports (); - } + } } void RouterInfo::EnableV4 () { if (!IsV4 ()) - { + { uint8_t addressCaps = AddressCaps::eV4; if (IsV6 ()) addressCaps |= AddressCaps::eV6; SetUnreachableAddressesTransportCaps (addressCaps); UpdateSupportedTransports (); - } + } } @@ -1017,15 +1017,15 @@ namespace data { auto addr = *it; if (addr->IsV6 ()) - { + { if (addr->IsV4 ()) - { + { addr->caps &= ~AddressCaps::eV6; ++it; - } + } else it = m_Addresses->erase (it); - } + } else ++it; } @@ -1041,15 +1041,15 @@ namespace data { auto addr = *it; if (addr->IsV4 ()) - { + { if (addr->IsV6 ()) - { + { addr->caps &= ~AddressCaps::eV4; ++it; - } + } else it = m_Addresses->erase (it); - } + } else ++it; } @@ -1060,14 +1060,14 @@ namespace data void RouterInfo::EnableMesh () { if (!IsMesh ()) - { + { m_SupportedTransports |= eNTCP2V6Mesh; m_ReachableTransports |= eNTCP2V6Mesh; - } + } } - + void RouterInfo::DisableMesh () - { + { if (IsMesh ()) { m_SupportedTransports &= ~eNTCP2V6Mesh; @@ -1080,8 +1080,8 @@ namespace data else ++it; } - } - } + } + } std::shared_ptr RouterInfo::GetSSUAddress (bool v4only) const { @@ -1121,7 +1121,7 @@ namespace data if (!key) return nullptr; return GetAddress ( [key](std::shared_ptr address)->bool - { + { return address->IsNTCP2 () && !memcmp (address->ntcp2->staticKey, key, 32); }); } @@ -1134,16 +1134,16 @@ namespace data return address->IsPublishedNTCP2 () && address->host.is_v4 (); }); } - + std::shared_ptr RouterInfo::GetPublishedNTCP2V6Address () const { return GetAddress ( [](std::shared_ptr address)->bool { - return address->IsPublishedNTCP2 () && address->host.is_v6 () && + return address->IsPublishedNTCP2 () && address->host.is_v6 () && !i2p::util::net::IsYggdrasilAddress (address->host); }); - } + } std::shared_ptr RouterInfo::GetYggdrasilAddress () const { @@ -1152,8 +1152,8 @@ namespace data { return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host); }); - } - + } + std::shared_ptr RouterInfo::GetProfile () const { if (!m_Profile) @@ -1168,34 +1168,34 @@ namespace data encryptor->Encrypt (data, encrypted); } - bool RouterInfo::IsEligibleFloodfill () const + bool RouterInfo::IsEligibleFloodfill () const { // floodfill must be reachable by ipv4, >= 0.9.38 and not DSA return IsReachableBy (eNTCP2V4 | eSSUV4) && m_Version >= NETDB_MIN_FLOODFILL_VERSION && - GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1; - } + GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1; + } bool RouterInfo::IsPeerTesting (bool v4) const { - if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; + if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; return (bool)GetAddress ( [v4](std::shared_ptr address)->bool - { + { return (address->transportStyle == eTransportSSU) && address->IsPeerTesting () && ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU (); - }); + }); } bool RouterInfo::IsIntroducer (bool v4) const { - if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; + if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; return (bool)GetAddress ( [v4](std::shared_ptr address)->bool - { + { return (address->transportStyle == eTransportSSU) && address->IsIntroducer () && ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified (); }); - } + } void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports) { @@ -1220,7 +1220,7 @@ namespace data if (addr->transportStyle == eTransportNTCP) { if (addr->IsV4 ()) transports |= eNTCP2V4; - if (addr->IsV6 ()) + if (addr->IsV6 ()) transports |= (i2p::util::net::IsYggdrasilAddress (addr->host) ? eNTCP2V6Mesh : eNTCP2V6); if (addr->IsPublishedNTCP2 ()) m_ReachableTransports |= transports; @@ -1231,9 +1231,9 @@ namespace data if (addr->IsV6 ()) transports |= eSSUV6; if (addr->IsReachableSSU ()) m_ReachableTransports |= transports; - } + } m_SupportedTransports |= transports; } - } + } } } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index de1fe235..2a341be8 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -52,7 +52,7 @@ namespace data const uint8_t COST_NTCP2_NON_PUBLISHED = 14; const uint8_t COST_SSU_DIRECT = 9; const uint8_t COST_SSU_THROUGH_INTRODUCERS = 11; - + const int MAX_RI_BUFFER_SIZE = 2048; // if RouterInfo exceeds 2048 we consider it as malformed, might be changed later class RouterInfo: public RoutingDestination { @@ -68,7 +68,7 @@ namespace data eAllTransports = 0xFF }; typedef uint8_t CompatibleTransports; - + enum Caps { eFloodfill = 0x01, @@ -86,7 +86,7 @@ namespace data eSSUTesting = 0x04, eSSUIntroducer = 0x08 }; - + enum TransportStyle { eTransportUnknown = 0, @@ -150,7 +150,7 @@ namespace data bool IsPublishedNTCP2 () const { return IsNTCP2 () && published; }; bool IsReachableSSU () const { return (bool)ssu && (published || !ssu->introducers.empty ()); }; bool UsesIntroducer () const { return (bool)ssu && !ssu->introducers.empty (); }; - + bool IsIntroducer () const { return caps & eSSUIntroducer; }; bool IsPeerTesting () const { return caps & eSSUTesting; }; @@ -173,14 +173,14 @@ namespace data int GetVersion () const { return m_Version; }; Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr std::shared_ptr GetNTCP2AddressWithStaticKey (const uint8_t * key) const; - std::shared_ptr GetPublishedNTCP2V4Address () const; - std::shared_ptr GetPublishedNTCP2V6Address () const; + std::shared_ptr GetPublishedNTCP2V4Address () const; + std::shared_ptr GetPublishedNTCP2V6Address () const; std::shared_ptr GetSSUAddress (bool v4only = true) const; std::shared_ptr GetSSUV6Address () const; std::shared_ptr GetYggdrasilAddress () const; void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0); - void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, + void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0, uint8_t caps = 0); bool AddIntroducer (const Introducer& introducer); bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e); @@ -196,28 +196,28 @@ namespace data bool IsSSU (bool v4only = true) const; bool IsSSUV6 () const; bool IsNTCP2 (bool v4only = true) const; - bool IsNTCP2V6 () const; + bool IsNTCP2V6 () const; bool IsV6 () const; bool IsV4 () const; - bool IsMesh () const; + bool IsMesh () const; void EnableV6 (); void DisableV6 (); void EnableV4 (); void DisableV4 (); void EnableMesh (); - void DisableMesh (); - bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; - bool IsReachableFrom (const RouterInfo& other) const { return m_ReachableTransports & other.m_SupportedTransports; }; + void DisableMesh (); + bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; + bool IsReachableFrom (const RouterInfo& other) const { return m_ReachableTransports & other.m_SupportedTransports; }; bool IsReachableBy (CompatibleTransports transports) const { return m_ReachableTransports & transports; }; - CompatibleTransports GetCompatibleTransports (bool incoming) const { return incoming ? m_ReachableTransports : m_SupportedTransports; }; - bool HasValidAddresses () const { return m_SupportedTransports; }; + CompatibleTransports GetCompatibleTransports (bool incoming) const { return incoming ? m_ReachableTransports : m_SupportedTransports; }; + bool HasValidAddresses () const { return m_SupportedTransports; }; bool IsHidden () const { return m_Caps & eHidden; }; bool IsHighBandwidth () const { return m_Caps & RouterInfo::eHighBandwidth; }; bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; }; bool IsEligibleFloodfill () const; - bool IsPeerTesting (bool v4) const; - bool IsIntroducer (bool v4) const; - + bool IsPeerTesting (bool v4) const; + bool IsIntroducer (bool v4) const; + uint8_t GetCaps () const { return m_Caps; }; void SetCaps (uint8_t caps); void SetCaps (const char * caps); diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp index 212bbc7e..56da56d6 100644 --- a/libi2pd/SSU.cpp +++ b/libi2pd/SSU.cpp @@ -923,7 +923,7 @@ namespace transport m_FragmentsPool.CleanUp (); m_IncompleteMessagesPool.CleanUp (); m_SentMessagesPool.CleanUp (); - + SchedulePeerTestsCleanupTimer (); } } diff --git a/libi2pd/SSU.h b/libi2pd/SSU.h index b97cacb4..f763c671 100644 --- a/libi2pd/SSU.h +++ b/libi2pd/SSU.h @@ -67,17 +67,17 @@ namespace transport i2p::util::MemoryPool& GetFragmentsPool () { return m_FragmentsPool; }; i2p::util::MemoryPool& GetIncompleteMessagesPool () { return m_IncompleteMessagesPool; }; i2p::util::MemoryPool& GetSentMessagesPool () { return m_SentMessagesPool; }; - + uint16_t GetPort () const { return m_Endpoint.port (); }; void SetLocalAddress (const boost::asio::ip::address& localAddress); - + void Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); void AddRelay (uint32_t tag, std::shared_ptr relay); void RemoveRelay (uint32_t tag); std::shared_ptr FindRelaySession (uint32_t tag); void RescheduleIntroducersUpdateTimer (); void RescheduleIntroducersUpdateTimerV6 (); - + void NewPeerTest (uint32_t nonce, PeerTestParticipant role, std::shared_ptr session = nullptr); PeerTestParticipant GetPeerTestParticipant (uint32_t nonce); std::shared_ptr GetPeerTestSession (uint32_t nonce); @@ -98,7 +98,7 @@ namespace transport void HandleReceivedPackets (std::vector packets, std::map >* sessions); - void CreateSessionThroughIntroducer (std::shared_ptr router, + void CreateSessionThroughIntroducer (std::shared_ptr router, std::shared_ptr address, bool peerTest = false); template std::shared_ptr GetRandomV4Session (Filter filter); @@ -134,7 +134,7 @@ namespace transport boost::asio::io_service::work m_Work, m_ReceiversWork, m_ReceiversWorkV6; boost::asio::ip::udp::endpoint m_Endpoint, m_EndpointV6; boost::asio::ip::udp::socket m_Socket, m_SocketV6; - boost::asio::deadline_timer m_IntroducersUpdateTimer, m_IntroducersUpdateTimerV6, + boost::asio::deadline_timer m_IntroducersUpdateTimer, m_IntroducersUpdateTimerV6, m_PeerTestsCleanupTimer, m_TerminationTimer, m_TerminationTimerV6; std::list m_Introducers, m_IntroducersV6; // introducers we are connected to std::map > m_Sessions, m_SessionsV6; @@ -145,7 +145,7 @@ namespace transport i2p::util::MemoryPool m_IncompleteMessagesPool; i2p::util::MemoryPool m_SentMessagesPool; i2p::util::MemoryPoolMt m_PacketsPool; - + public: // for HTTP only const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index 2f93218e..3e564373 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -188,7 +188,7 @@ namespace transport incompleteMessage->receivedFragmentsBits |= (uint64_t(0x01) << fragmentNum); else LogPrint (eLogWarning, "SSU: Fragment number ", fragmentNum, " exceeds 64"); - + // handle current fragment if (fragmentNum == incompleteMessage->nextFragmentNum) { @@ -223,7 +223,7 @@ namespace transport // missing fragment LogPrint (eLogWarning, "SSU: Missing fragments from ", (int)incompleteMessage->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID); auto savedFragment = m_Session.GetServer ().GetFragmentsPool ().AcquireShared (fragmentNum, buf, fragmentSize, isLast); - if (incompleteMessage->savedFragments.insert (savedFragment).second) + if (incompleteMessage->savedFragments.insert (savedFragment).second) incompleteMessage->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch (); else LogPrint (eLogWarning, "SSU: Fragment ", (int)fragmentNum, " of message ", msgID, " already saved"); @@ -350,11 +350,11 @@ namespace transport size += payload - fragment->buf; uint8_t rem = size & 0x0F; if (rem) // make sure 16 bytes boundary - { + { auto padding = 16 - rem; memset (fragment->buf + size, 0, padding); size += padding; - } + } fragment->len = size; fragments.push_back (fragment); @@ -409,14 +409,14 @@ namespace transport // one ack *(uint32_t *)(payload) = htobe32 (msgID); // msgID payload += 4; - size_t len = 0; + size_t len = 0; while (bits) { *payload = (bits & 0x7F); // next 7 bits bits >>= 7; if (bits) *payload &= 0x80; // 0x80 means non-last payload++; len++; - } + } *payload = 0; // number of fragments len = (len <= 4) ? 48 : 64; // 48 = 37 + 7 + 4 // encrypt message with session key @@ -450,7 +450,7 @@ namespace transport if (f) { try - { + { m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, f->buf, f->len, buf); m_Session.Send (buf, f->len); // resend numResent++; @@ -497,21 +497,21 @@ namespace transport else ++it; } - + if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES || ts > m_LastMessageReceivedTime + DECAY_INTERVAL) // decay m_ReceivedMessages.clear (); else { - // delete old received messages + // delete old received messages for (auto it = m_ReceivedMessages.begin (); it != m_ReceivedMessages.end ();) { if (ts > it->second + RECEIVED_MESSAGES_CLEANUP_TIMEOUT) it = m_ReceivedMessages.erase (it); else ++it; - } - } - } + } + } + } } } diff --git a/libi2pd/SSUData.h b/libi2pd/SSUData.h index 8fe33a33..3fbd6d00 100644 --- a/libi2pd/SSUData.h +++ b/libi2pd/SSUData.h @@ -79,7 +79,7 @@ namespace transport uint64_t receivedFragmentsBits; std::set, FragmentCmp> savedFragments; - IncompleteMessage (std::shared_ptr m): msg (m), nextFragmentNum (0), + IncompleteMessage (std::shared_ptr m): msg (m), nextFragmentNum (0), lastFragmentInsertTime (0), receivedFragmentsBits (0) {}; void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize); }; @@ -102,7 +102,7 @@ namespace transport void Start (); void Stop (); void CleanUp (uint64_t ts); - + void ProcessMessage (uint8_t * buf, size_t len); void FlushReceivedMessage (); void Send (std::shared_ptr msg); diff --git a/libi2pd/SSUSession.cpp b/libi2pd/SSUSession.cpp index 45c08433..54ad5604 100644 --- a/libi2pd/SSUSession.cpp +++ b/libi2pd/SSUSession.cpp @@ -230,7 +230,7 @@ namespace transport auto pair = std::make_shared (); pair->GenerateKeys (); m_DHKeysPair = pair; - } + } CreateAESandMacKey (buf + headerSize); SendSessionCreated (buf + headerSize, sendRelayTag); } @@ -259,7 +259,7 @@ namespace transport s.Insert (y, 256); // y payload += 256; boost::asio::ip::address ourIP; - uint16_t ourPort = 0; + uint16_t ourPort = 0; auto addressAndPortLen = ExtractIPAddressAndPort (payload, len, ourIP, ourPort); if (!addressAndPortLen) return; uint8_t * ourAddressAndPort = payload + 1; @@ -297,15 +297,15 @@ namespace transport { LogPrint (eLogInfo, "SSU: Our external address is ", ourIP.to_string (), ":", ourPort); if (!i2p::util::net::IsInReservedRange (ourIP)) - { + { i2p::context.UpdateAddress (ourIP); - SendSessionConfirmed (y, ourAddressAndPort, addressAndPortLen); - } + SendSessionConfirmed (y, ourAddressAndPort, addressAndPortLen); + } else - { + { LogPrint (eLogError, "SSU: External address ", ourIP.to_string (), " is in reserved range"); Failed (); - } + } } else { @@ -317,7 +317,7 @@ namespace transport void SSUSession::ProcessSessionConfirmed (const uint8_t * buf, size_t len) { LogPrint (eLogDebug, "SSU: Session confirmed received"); - m_ConnectTimer.cancel (); + m_ConnectTimer.cancel (); auto headerSize = GetSSUHeaderSize (buf); if (headerSize >= len) { @@ -331,7 +331,7 @@ namespace transport { LogPrint (eLogError, "SSU: Session confirmed identity size ", identitySize, " exceeds packet length ", len); return; - } + } payload += 2; // size of identity fragment auto identity = std::make_shared (payload, identitySize); auto existing = i2p::data::netdb.FindRouter (identity->GetIdentHash ()); // check if exists already @@ -357,7 +357,7 @@ namespace transport { LogPrint (eLogError, "SSU: Session confirmed message is too short ", len); return; - } + } // verify signature if (m_SignedData && m_SignedData->Verify (m_RemoteIdentity, payload)) { @@ -599,19 +599,19 @@ namespace transport uint8_t * payload = buf + sizeof (SSUHeader); // Charlie if (isV4) - { + { *payload = 4; payload++; // size memcpy (payload, to.address ().to_v4 ().to_bytes ().data (), 4); // Charlie's IP V4 payload += 4; // address - } + } else { *payload = 16; payload++; // size memcpy (payload, to.address ().to_v6 ().to_bytes ().data (), 16); // Charlie's IP V6 payload += 16; // address - } + } htobe16buf (payload, to.port ()); // Charlie's port payload += 2; // port // Alice @@ -705,15 +705,15 @@ namespace transport else LogPrint (eLogError, "SSU: External address ", ourIP.to_string (), " is in reserved range"); if (ourIP.is_v4 ()) - { + { if (ourPort != m_Server.GetPort ()) - { + { if (i2p::context.GetStatus () == eRouterStatusTesting) i2p::context.SetError (eRouterErrorSymmetricNAT); } else if (i2p::context.GetStatus () == eRouterStatusError && i2p::context.GetError () == eRouterErrorSymmetricNAT) i2p::context.SetStatus (eRouterStatusTesting); - } + } uint32_t nonce = bufbe32toh (buf); buf += 4; // nonce auto it = m_RelayRequests.find (nonce); @@ -727,7 +727,7 @@ namespace transport // now we do LogPrint (eLogInfo, "SSU: RelayReponse connecting to endpoint ", remoteEndpoint); if ((remoteIP.is_v4 () && i2p::context.GetStatus () == eRouterStatusFirewalled) || - (remoteIP.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled)) + (remoteIP.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled)) m_Server.Send (buf, 0, remoteEndpoint); // send HolePunch // we assume that HolePunch has been sent by this time and our SessionRequest will go through m_Server.CreateDirectSession (it->second.first, remoteEndpoint, false); @@ -803,7 +803,7 @@ namespace transport htobe16buf (out + len + 16, (netid == I2PD_NET_ID) ? encryptedLen : encryptedLen ^ ((netid - 2) << 8)); i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac); } - + void SSUSession::Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey) { if (len < sizeof (SSUHeader)) @@ -1015,7 +1015,7 @@ namespace transport else ++it; } - } + } void SSUSession::ProcessPeerTest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { @@ -1039,17 +1039,17 @@ namespace transport LogPrint (eLogDebug, "SSU: Peer test from Bob. We are Alice"); if (IsV6 ()) { - if (i2p::context.GetStatusV6 () == eRouterStatusTesting) - { + if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + { i2p::context.SetStatusV6 (eRouterStatusFirewalled); m_Server.RescheduleIntroducersUpdateTimerV6 (); - } - } + } + } else if (i2p::context.GetStatus () == eRouterStatusTesting) // still not OK - { + { i2p::context.SetStatus (eRouterStatusFirewalled); m_Server.RescheduleIntroducersUpdateTimer (); - } + } } else { @@ -1058,7 +1058,7 @@ namespace transport LogPrint (eLogWarning, "SSU: First peer test from Charlie through established session. We are Alice"); if (IsV6 ()) i2p::context.SetStatusV6 (eRouterStatusOK); - else + else i2p::context.SetStatus (eRouterStatusOK); m_Server.UpdatePeerTest (nonce, ePeerTestParticipantAlice2); SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, true, false); // to Charlie @@ -1074,8 +1074,8 @@ namespace transport // peer test successive LogPrint (eLogDebug, "SSU: Second peer test from Charlie. We are Alice"); if (IsV6 ()) - i2p::context.SetStatusV6 (eRouterStatusOK); - else + i2p::context.SetStatusV6 (eRouterStatusOK); + else i2p::context.SetStatus (eRouterStatusOK); m_Server.RemovePeerTest (nonce); } @@ -1089,7 +1089,7 @@ namespace transport { const auto& ep = session->GetRemoteEndpoint (); // Alice's endpoint as known to Bob session->SendPeerTest (nonce, ep.address (), ep.port (), introKey, false, true); // send back to Alice - } + } m_Server.RemovePeerTest (nonce); // nonce has been used break; } @@ -1111,10 +1111,10 @@ namespace transport LogPrint (eLogDebug, "SSU: Peer test from Bob. We are Charlie"); Send (PAYLOAD_TYPE_PEER_TEST, buf, len); // back to Bob if (!addr.is_unspecified () && !i2p::util::net::IsInReservedRange(addr)) - { + { m_Server.NewPeerTest (nonce, ePeerTestParticipantCharlie); SendPeerTest (nonce, addr, port, introKey); // to Alice with her address received from Bob - } + } } else { @@ -1281,12 +1281,12 @@ namespace transport if (!len) return 0; uint8_t size = *buf; size_t s = 1 + size + 2; // size + address + port - if (len < s) + if (len < s) { LogPrint (eLogWarning, "SSU: Address is too short ", len); port = 0; return len; - } + } buf++; // size if (size == 4) { @@ -1299,12 +1299,12 @@ namespace transport boost::asio::ip::address_v6::bytes_type bytes; memcpy (bytes.data (), buf, 16); ip = boost::asio::ip::address_v6 (bytes); - } + } else LogPrint (eLogWarning, "SSU: Address size ", int(size), " is not supported"); buf += size; port = bufbe16toh (buf); return s; - } + } } } diff --git a/libi2pd/SSUSession.h b/libi2pd/SSUSession.h index bd4b4b93..4f7fa0f5 100644 --- a/libi2pd/SSUSession.h +++ b/libi2pd/SSUSession.h @@ -90,7 +90,7 @@ namespace transport void Failed (); const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; SSUServer& GetServer () { return m_Server; }; - + bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); }; void SendI2NPMessages (const std::vector >& msgs); void SendPeerTest (); // Alice @@ -104,7 +104,7 @@ namespace transport const i2p::data::RouterInfo::IntroKey& GetIntroKey () const { return m_IntroKey; }; uint32_t GetCreationTime () const { return m_CreationTime; }; void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers - + void FlushData (); void CleanUp (uint64_t ts); @@ -149,7 +149,7 @@ namespace transport void Reset (); static size_t ExtractIPAddressAndPort (const uint8_t * buf, size_t len, boost::asio::ip::address& ip, uint16_t& port); // returns actual buf size - + private: friend class SSUData; // TODO: change in later diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index 28ae5fa6..458a4fd7 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -115,7 +115,7 @@ namespace crypto m_MDCtx = EVP_MD_CTX_create (); EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, pkey); } - EVP_PKEY_free (pkey); + EVP_PKEY_free (pkey); } EDDSA25519Signer::~EDDSA25519Signer () diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index caf9b274..e153e66d 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -340,7 +340,7 @@ namespace crypto void Sign (const uint8_t * buf, int len, uint8_t * signature) const; private: - + EVP_MD_CTX * m_MDCtx; EDDSA25519SignerCompat * m_Fallback; }; diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index df7a7eed..b3c4230f 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -27,12 +27,12 @@ namespace stream void SendBufferQueue::Add (std::shared_ptr buf) { if (buf) - { + { m_Buffers.push_back (buf); m_Size += buf->len; - } - } - + } + } + size_t SendBufferQueue::Get (uint8_t * buf, size_t len) { size_t offset = 0; @@ -277,20 +277,20 @@ namespace stream const uint8_t * optionData = packet->GetOptionData (); size_t optionSize = packet->GetOptionSize (); if (flags & PACKET_FLAG_DELAY_REQUESTED) - { + { if (!m_IsAckSendScheduled) { uint16_t delayRequested = bufbe16toh (optionData); if (delayRequested > 0 && delayRequested < m_RTT) - { + { m_IsAckSendScheduled = true; m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(delayRequested)); m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, shared_from_this (), std::placeholders::_1)); - } + } } optionData += 2; - } + } if (flags & PACKET_FLAG_FROM_INCLUDED) { @@ -391,10 +391,10 @@ namespace stream p.len = payloadLen + 22; SendPackets (std::vector { &p }); LogPrint (eLogDebug, "Streaming: Pong of ", p.len, " bytes sent"); - } + } m_LocalDestination.DeletePacket (packet); - } - + } + void Stream::ProcessAck (Packet * packet) { bool acknowledged = false; @@ -490,7 +490,7 @@ namespace stream handler(boost::system::error_code ()); m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ())); } - + void Stream::SendBuffer () { int numMsgs = m_WindowSize - m_SentPackets.size (); @@ -672,8 +672,8 @@ namespace stream size_t size = 0; htobe32buf (packet, m_RecvStreamID); size += 4; // sendStreamID - memset (packet + size, 0, 14); - size += 14; // all zeroes + memset (packet + size, 0, 14); + size += 14; // all zeroes uint16_t flags = PACKET_FLAG_ECHO | PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_FROM_INCLUDED; bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature (); if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE; @@ -695,12 +695,12 @@ namespace stream memset (signature, 0, signatureLen); // zeroes for now size += signatureLen; // signature htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size - m_LocalDestination.GetOwner ()->Sign (packet, size, signature); + m_LocalDestination.GetOwner ()->Sign (packet, size, signature); p.len = size; SendPackets (std::vector { &p }); LogPrint (eLogDebug, "Streaming: Ping of ", p.len, " bytes sent"); - } - + } + void Stream::Close () { LogPrint(eLogDebug, "Streaming: closing stream with sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID, ", status=", m_Status); @@ -840,7 +840,7 @@ namespace stream auto leaseRouter = i2p::data::netdb.FindRouter (m_CurrentRemoteLease->tunnelGateway); m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (nullptr, leaseRouter ? leaseRouter->GetCompatibleTransports (false) : (i2p::data::RouterInfo::CompatibleTransports)i2p::data::RouterInfo::eAllTransports); - } + } else if (!m_CurrentOutboundTunnel->IsEstablished ()) m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNewOutboundTunnel (m_CurrentOutboundTunnel); if (!m_CurrentOutboundTunnel) @@ -849,7 +849,7 @@ namespace stream m_CurrentRemoteLease = nullptr; return; } - + std::vector msgs; for (const auto& it: packets) { @@ -903,14 +903,14 @@ namespace stream void Stream::ScheduleResend () { if (m_Status != eStreamStatusTerminated) - { + { m_ResendTimer.cancel (); // check for invalid value if (m_RTO <= 0) m_RTO = INITIAL_RTO; m_ResendTimer.expires_from_now (boost::posix_time::milliseconds(m_RTO)); m_ResendTimer.async_wait (std::bind (&Stream::HandleResendTimer, shared_from_this (), std::placeholders::_1)); - } + } } void Stream::HandleResendTimer (const boost::system::error_code& ecode) @@ -1008,16 +1008,16 @@ namespace stream { LogPrint (eLogWarning, "Streaming: LeaseSet ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), m_RemoteLeaseSet ? " expired" : " not found"); if (m_RemoteLeaseSet && m_RemoteLeaseSet->IsPublishedEncrypted ()) - { + { m_LocalDestination.GetOwner ()->RequestDestinationWithEncryptedLeaseSet ( std::make_shared(m_RemoteIdentity)); return; // we keep m_RemoteLeaseSet for possible next request - } - else - { - m_RemoteLeaseSet = nullptr; + } + else + { + m_RemoteLeaseSet = nullptr; m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ()); // try to request for a next attempt - } + } } else { @@ -1113,7 +1113,7 @@ namespace stream it.second->Terminate (false); // we delete here m_Streams.clear (); m_IncomingStreams.clear (); - m_LastStream = nullptr; + m_LastStream = nullptr; } } @@ -1123,7 +1123,7 @@ namespace stream if (sendStreamID) { if (!m_LastStream || sendStreamID != m_LastStream->GetRecvStreamID ()) - { + { auto it = m_Streams.find (sendStreamID); if (it != m_Streams.end ()) m_LastStream = it->second; @@ -1138,7 +1138,7 @@ namespace stream LogPrint (eLogInfo, "Streaming: Ping received sSID=", sendStreamID); auto s = std::make_shared (m_Owner->GetService (), *this); s->HandlePing (packet); - } + } else { LogPrint (eLogInfo, "Streaming: Unknown stream sSID=", sendStreamID); @@ -1153,7 +1153,7 @@ namespace stream LogPrint (eLogInfo, "Streaming: Pong received rSID=", packet->GetReceiveStreamID ()); DeletePacket (packet); return; - } + } if (packet->IsSYN () && !packet->GetSeqn ()) // new incoming stream { uint32_t receiveStreamID = packet->GetReceiveStreamID (); @@ -1252,8 +1252,8 @@ namespace stream { auto s = std::make_shared (m_Owner->GetService (), *this, remote, 0); s->SendPing (); - } - + } + std::shared_ptr StreamingDestination::CreateNewIncomingStream (uint32_t receiveStreamID) { auto s = std::make_shared (m_Owner->GetService (), *this); diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 7e279623..f2ed3002 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -112,10 +112,10 @@ namespace stream memcpy (buf, b, len); } SendBuffer (size_t l): // create empty buffer - len(l), offset (0) + len(l), offset (0) { buf = new uint8_t[len]; - } + } ~SendBuffer () { delete[] buf; @@ -180,7 +180,7 @@ namespace stream size_t Send (const uint8_t * buf, size_t len); void AsyncSend (const uint8_t * buf, size_t len, SendHandler handler); void SendPing (); - + template void AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout = 0); size_t ReadSome (uint8_t * buf, size_t len) { return ConcatenatePackets (buf, len); }; diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index ec0c25f2..3673a58c 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -48,7 +48,7 @@ namespace util return std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count (); } - + static uint32_t GetLocalHoursSinceEpoch () { return std::chrono::duration_cast( @@ -70,23 +70,23 @@ namespace util boost::asio::ip::udp::resolver::iterator end; boost::asio::ip::udp::endpoint ep; while (it != end) - { + { ep = *it; if (!ep.address ().is_unspecified ()) { if (ep.address ().is_v4 ()) - { - if (i2p::context.SupportsV4 ()) found = true; + { + if (i2p::context.SupportsV4 ()) found = true; } else if (ep.address ().is_v6 ()) { if (i2p::util::net::IsYggdrasilAddress (ep.address ())) { if (i2p::context.SupportsMesh ()) found = true; - } + } else if (i2p::context.SupportsV6 ()) found = true; } - } + } if (found) break; it++; } @@ -94,8 +94,8 @@ namespace util { LogPrint (eLogError, "Timestamp: can't find compatible address for ", address); return; - } - + } + boost::asio::ip::udp::socket socket (service); socket.open (ep.protocol (), ec); if (!ec) @@ -220,13 +220,13 @@ namespace util uint64_t GetSecondsSinceEpoch () { return GetLocalSecondsSinceEpoch () + g_TimeOffset; - } - + } + uint32_t GetMinutesSinceEpoch () { return GetLocalMinutesSinceEpoch () + g_TimeOffset/60; } - + uint32_t GetHoursSinceEpoch () { return GetLocalHoursSinceEpoch () + g_TimeOffset/3600; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index ae2808e0..5f4b3425 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -204,7 +204,7 @@ namespace transport // create SSU server int ssuPort = 0; if (enableSSU) - { + { auto& addresses = context.GetRouterInfo ().GetAddresses (); for (const auto& address: addresses) { @@ -216,39 +216,39 @@ namespace transport break; } } - } - + } + // bind to interfaces bool ipv4; i2p::config::GetOption("ipv4", ipv4); if (ipv4) { std::string address; i2p::config::GetOption("address4", address); if (!address.empty ()) - { + { boost::system::error_code ec; auto addr = boost::asio::ip::address::from_string (address, ec); if (!ec) - { + { if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr); if (m_SSUServer) m_SSUServer->SetLocalAddress (addr); - } - } - } + } + } + } bool ipv6; i2p::config::GetOption("ipv6", ipv6); if (ipv6) { std::string address; i2p::config::GetOption("address6", address); if (!address.empty ()) - { + { boost::system::error_code ec; auto addr = boost::asio::ip::address::from_string (address, ec); - if (!ec) - { + if (!ec) + { if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr); if (m_SSUServer) m_SSUServer->SetLocalAddress (addr); - } - } + } + } } bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); @@ -256,12 +256,12 @@ namespace transport { std::string address; i2p::config::GetOption("meshnets.yggaddress", address); if (!address.empty ()) - { + { boost::system::error_code ec; auto addr = boost::asio::ip::address::from_string (address, ec); if (!ec && m_NTCP2Server && i2p::util::net::IsYggdrasilAddress (addr)) m_NTCP2Server->SetLocalAddress (addr); - } + } } // start servers @@ -269,11 +269,11 @@ namespace transport if (m_SSUServer) { LogPrint (eLogInfo, "Transports: Start listening UDP port ", ssuPort); - try + try { m_SSUServer->Start (); - } - catch (std::exception& ex ) + } + catch (std::exception& ex ) { LogPrint(eLogError, "Transports: Failed to bind to UDP port", ssuPort); m_SSUServer->Stop (); @@ -281,8 +281,8 @@ namespace transport m_SSUServer = nullptr; } if (m_SSUServer) DetectExternalIP (); - } - + } + m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5*SESSION_CREATION_TIMEOUT)); m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1)); @@ -448,23 +448,23 @@ namespace transport if (!peer.numAttempts) // NTCP2 ipv6 { if (context.GetRouterInfo ().IsNTCP2V6 () && peer.router->IsReachableBy (RouterInfo::eNTCP2V6)) - { + { address = peer.router->GetPublishedNTCP2V6Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; - } + } peer.numAttempts++; } - if (!address && peer.numAttempts == 1) // NTCP2 ipv4 - { + if (!address && peer.numAttempts == 1) // NTCP2 ipv4 + { if (context.GetRouterInfo ().IsNTCP2 (true) && peer.router->IsReachableBy (RouterInfo::eNTCP2V4)) - { + { address = peer.router->GetPublishedNTCP2V4Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; - } + } peer.numAttempts++; - } + } if (address) { auto s = std::make_shared (*m_NTCP2Server, peer.router, address); @@ -478,10 +478,10 @@ namespace transport else peer.numAttempts = 2; // switch to SSU } - if (peer.numAttempts == 2 || peer.numAttempts == 3) // SSU + if (peer.numAttempts == 2 || peer.numAttempts == 3) // SSU { if (m_SSUServer) - { + { std::shared_ptr address; if (peer.numAttempts == 2) // SSU ipv6 { @@ -507,7 +507,7 @@ namespace transport { if (m_SSUServer->CreateSession (peer.router, address)) return true; - } + } } else peer.numAttempts += 2; // switch to Mesh @@ -523,8 +523,8 @@ namespace transport auto s = std::make_shared (*m_NTCP2Server, peer.router, address); m_NTCP2Server->Connect (s); return true; - } - } + } + } } LogPrint (eLogInfo, "Transports: No compatble NTCP2 or SSU addresses available"); i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed @@ -591,7 +591,7 @@ namespace transport bool statusChanged = false; for (int i = 0; i < 5; i++) { - auto router = i2p::data::netdb.GetRandomPeerTestRouter (true, excluded); // v4 + auto router = i2p::data::netdb.GetRandomPeerTestRouter (true, excluded); // v4 if (router) { auto addr = router->GetSSUAddress (true); // ipv4 @@ -602,8 +602,8 @@ namespace transport statusChanged = true; i2p::context.SetStatus (eRouterStatusTesting); // first time only } - m_SSUServer->CreateSession (router, addr, true); // peer test v4 - } + m_SSUServer->CreateSession (router, addr, true); // peer test v4 + } excluded.insert (router->GetIdentHash ()); } } @@ -622,20 +622,20 @@ namespace transport { auto addr = router->GetSSUV6Address (); if (addr && !i2p::util::net::IsInReservedRange(addr->host)) - { + { if (!statusChanged) { statusChanged = true; i2p::context.SetStatusV6 (eRouterStatusTesting); // first time only } m_SSUServer->CreateSession (router, addr, true); // peer test v6 - } + } excluded.insert (router->GetIdentHash ()); } } if (!statusChanged) LogPrint (eLogWarning, "Transports: Can't find routers for peer test IPv6"); - } + } } std::shared_ptr Transports::GetNextX25519KeysPair () @@ -780,7 +780,7 @@ namespace transport std::advance (it, rand () % m_Peers.size ()); if (it == m_Peers.end () || it->second.router) return nullptr; // not connected ident = it->first; - } + } return i2p::data::netdb.FindRouter (ident); } void Transports::RestrictRoutesToFamilies(std::set families) diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 9377286c..44790e6a 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -60,7 +60,7 @@ namespace transport std::mutex m_AcquiredMutex; }; typedef EphemeralKeysSupplier X25519KeysPairSupplier; - + struct Peer { int numAttempts; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 20672d4b..c6733649 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -31,7 +31,7 @@ namespace tunnel { Tunnel::Tunnel (std::shared_ptr config): TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()), - m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr), + m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr), m_State (eTunnelStatePending), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports), m_IsRecreated (false), m_Latency (0) { @@ -47,7 +47,7 @@ namespace tunnel const int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS; auto msg = numRecords <= STANDARD_NUM_RECORDS ? NewI2NPShortMessage () : NewI2NPMessage (); *msg->GetPayload () = numRecords; - const size_t recordSize = m_Config->IsShort () ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; + const size_t recordSize = m_Config->IsShort () ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; msg->len += numRecords*recordSize + 1; // shuffle records std::vector recordIndicies; @@ -98,13 +98,13 @@ namespace tunnel { auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr; if (ident && ident->GetIdentHash () != outboundTunnel->GetNextIdentHash ()) // don't encrypt if IBGW = OBEP - { + { auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ()); if (msg1) msg = msg1; - } - } + } + } outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg); - } + } else { if (m_Config->IsShort () && m_Config->GetLastHop () && @@ -115,11 +115,11 @@ namespace tunnel uint64_t tag = m_Config->GetLastHop ()->GetGarlicKey (key); if (m_Pool && m_Pool->GetLocalDestination ()) m_Pool->GetLocalDestination ()->AddECIESx25519Key (key, tag); - else + else i2p::context.AddECIESx25519Key (key, tag); - } + } i2p::transport::transports.SendMessage (GetNextIdentHash (), msg); - } + } } bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len) @@ -134,14 +134,14 @@ namespace tunnel { if (!hop->DecryptBuildResponseRecord (msg + 1)) return false; - } + } else { LogPrint (eLogWarning, "Tunnel: Hop index ", hop->recordIndex, " is out of range"); return false; - } - - // decrypt records before current hop + } + + // decrypt records before current hop TunnelHopConfig * hop1 = hop->prev; while (hop1) { @@ -176,7 +176,7 @@ namespace tunnel // create tunnel decryptions from layer and iv keys in reverse order m_Hops.resize (numHops); hop = m_Config->GetLastHop (); - int i = 0; + int i = 0; while (hop) { m_Hops[i].ident = hop->ident; @@ -535,7 +535,7 @@ namespace tunnel case eI2NPShortTunnelBuild: case eI2NPShortTunnelBuildReply: case eI2NPTunnelBuild: - case eI2NPTunnelBuildReply: + case eI2NPTunnelBuildReply: HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ()); break; default: @@ -566,14 +566,14 @@ namespace tunnel { ManageTunnelPools (ts); lastPoolsTs = ts; - } + } if (ts - lastMemoryPoolTs >= 120) // manage memory pool every 2 minutes { m_I2NPTunnelEndpointMessagesMemoryPool.CleanUpMt (); m_I2NPTunnelMessagesMemoryPool.CleanUpMt (); lastMemoryPoolTs = ts; - } - } + } + } } catch (std::exception& ex) { @@ -848,7 +848,7 @@ namespace tunnel } template - std::shared_ptr Tunnels::CreateTunnel (std::shared_ptr config, + std::shared_ptr Tunnels::CreateTunnel (std::shared_ptr config, std::shared_ptr pool, std::shared_ptr outboundTunnel) { auto newTunnel = std::make_shared (config); @@ -860,7 +860,7 @@ namespace tunnel return newTunnel; } - std::shared_ptr Tunnels::CreateInboundTunnel (std::shared_ptr config, + std::shared_ptr Tunnels::CreateInboundTunnel (std::shared_ptr config, std::shared_ptr pool, std::shared_ptr outboundTunnel) { if (config) @@ -924,7 +924,7 @@ namespace tunnel } - std::shared_ptr Tunnels::CreateZeroHopsInboundTunnel (std::shared_ptr pool) + std::shared_ptr Tunnels::CreateZeroHopsInboundTunnel (std::shared_ptr pool) { auto inboundTunnel = std::make_shared (); inboundTunnel->SetTunnelPool (pool); @@ -947,21 +947,21 @@ namespace tunnel std::shared_ptr Tunnels::NewI2NPTunnelMessage (bool endpoint) { if (endpoint) - { + { // should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet - auto msg = m_I2NPTunnelEndpointMessagesMemoryPool.AcquireSharedMt (); + auto msg = m_I2NPTunnelEndpointMessagesMemoryPool.AcquireSharedMt (); msg->Align (6); msg->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header return msg; - } + } else { - auto msg = m_I2NPTunnelMessagesMemoryPool.AcquireSharedMt (); + auto msg = m_I2NPTunnelMessagesMemoryPool.AcquireSharedMt (); msg->Align (12); return msg; - } - } - + } + } + int Tunnels::GetTransitTunnelsExpirationTimeout () { int timeout = 0; diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index cfd54d26..72414ed0 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -40,10 +40,10 @@ namespace tunnel const int STANDARD_NUM_RECORDS = 4; // in VariableTunnelBuild message const int MAX_NUM_RECORDS = 8; const int HIGH_LATENCY_PER_HOP = 250; // in milliseconds - + const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12 - const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6 - + const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6 + enum TunnelState { eTunnelStatePending, @@ -106,7 +106,7 @@ namespace tunnel bool LatencyIsKnown() const { return m_Latency > 0; } bool IsSlow () const { return LatencyIsKnown() && (int)m_Latency > HIGH_LATENCY_PER_HOP*GetNumHops (); } - + protected: void PrintHops (std::stringstream& s) const; @@ -119,7 +119,7 @@ namespace tunnel std::shared_ptr m_Pool; // pool, tunnel belongs to, or null TunnelState m_State; i2p::data::RouterInfo::CompatibleTransports m_FarEndTransports; - bool m_IsRecreated; // if tunnel is replaced by new, or new tunnel requested to replace + bool m_IsRecreated; // if tunnel is replaced by new, or new tunnel requested to replace uint64_t m_Latency; // in milliseconds }; @@ -225,11 +225,11 @@ namespace tunnel void StopTunnelPool (std::shared_ptr pool); std::shared_ptr NewI2NPTunnelMessage (bool endpoint); - + private: template - std::shared_ptr CreateTunnel (std::shared_ptr config, + std::shared_ptr CreateTunnel (std::shared_ptr config, std::shared_ptr pool, std::shared_ptr outboundTunnel = nullptr); template @@ -266,7 +266,7 @@ namespace tunnel i2p::util::Queue > m_Queue; i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; - + // some stats int m_NumSuccesiveTunnelCreations, m_NumFailedTunnelCreations; diff --git a/libi2pd/TunnelConfig.cpp b/libi2pd/TunnelConfig.cpp index 4592c663..7801f20f 100644 --- a/libi2pd/TunnelConfig.cpp +++ b/libi2pd/TunnelConfig.cpp @@ -81,34 +81,34 @@ namespace tunnel decryption.SetKey (replyKey); decryption.SetIV (replyIV); decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record); - } + } void ECIESTunnelHopConfig::EncryptECIES (const uint8_t * plainText, size_t len, uint8_t * encrypted) { if (!ident) return; i2p::crypto::InitNoiseNState (*this, ident->GetEncryptionPublicKey ()); auto ephemeralKeys = i2p::transport::transports.GetNextX25519KeysPair (); - memcpy (encrypted, ephemeralKeys->GetPublicKey (), 32); + memcpy (encrypted, ephemeralKeys->GetPublicKey (), 32); MixHash (encrypted, 32); // h = SHA256(h || sepk) encrypted += 32; uint8_t sharedSecret[32]; ephemeralKeys->Agree (ident->GetEncryptionPublicKey (), sharedSecret); // x25519(sesk, hepk) - MixKey (sharedSecret); + MixKey (sharedSecret); uint8_t nonce[12]; memset (nonce, 0, 12); if (!i2p::crypto::AEADChaCha20Poly1305 (plainText, len, m_H, 32, m_CK + 32, nonce, encrypted, len + 16, true)) // encrypt - { + { LogPrint (eLogWarning, "Tunnel: Plaintext AEAD encryption failed"); return; - } + } MixHash (encrypted, len + 16); // h = SHA256(h || ciphertext) - } + } bool ECIESTunnelHopConfig::DecryptECIES (const uint8_t * key, const uint8_t * nonce, const uint8_t * encrypted, size_t len, uint8_t * clearText) const { return i2p::crypto::AEADChaCha20Poly1305 (encrypted, len - 16, m_H, 32, key, nonce, clearText, len - 16, false); // decrypt - } - + } + void LongECIESTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) { // generate keys @@ -119,7 +119,7 @@ namespace tunnel // fill clear text uint8_t flag = 0; if (isGateway) flag |= TUNNEL_BUILD_RECORD_GATEWAY_FLAG; - if (isEndpoint) flag |= TUNNEL_BUILD_RECORD_ENDPOINT_FLAG; + if (isEndpoint) flag |= TUNNEL_BUILD_RECORD_ENDPOINT_FLAG; uint8_t clearText[ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID); @@ -149,16 +149,16 @@ namespace tunnel { LogPrint (eLogWarning, "Tunnel: Response AEAD decryption failed"); return false; - } + } return true; - } + } void ShortECIESTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) { // fill clear text uint8_t flag = 0; if (isGateway) flag |= TUNNEL_BUILD_RECORD_GATEWAY_FLAG; - if (isEndpoint) flag |= TUNNEL_BUILD_RECORD_ENDPOINT_FLAG; + if (isEndpoint) flag |= TUNNEL_BUILD_RECORD_ENDPOINT_FLAG; uint8_t clearText[SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE ]; htobe32buf (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); htobe32buf (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID); @@ -174,21 +174,21 @@ namespace tunnel uint8_t * record = records + recordIndex*SHORT_TUNNEL_BUILD_RECORD_SIZE; EncryptECIES (clearText, SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE, record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET); // derive keys - i2p::crypto::HKDF (m_CK, nullptr, 0, "SMTunnelReplyKey", m_CK); + i2p::crypto::HKDF (m_CK, nullptr, 0, "SMTunnelReplyKey", m_CK); memcpy (replyKey, m_CK + 32, 32); - i2p::crypto::HKDF (m_CK, nullptr, 0, "SMTunnelLayerKey", m_CK); + i2p::crypto::HKDF (m_CK, nullptr, 0, "SMTunnelLayerKey", m_CK); memcpy (layerKey, m_CK + 32, 32); if (isEndpoint) { - i2p::crypto::HKDF (m_CK, nullptr, 0, "TunnelLayerIVKey", m_CK); - memcpy (ivKey, m_CK + 32, 32); + i2p::crypto::HKDF (m_CK, nullptr, 0, "TunnelLayerIVKey", m_CK); + memcpy (ivKey, m_CK + 32, 32); i2p::crypto::HKDF (m_CK, nullptr, 0, "RGarlicKeyAndTag", m_CK); // OTBRM garlic key m_CK + 32, tag first 8 bytes of m_CK } else memcpy (ivKey, m_CK, 32); // last HKDF memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); } - + bool ShortECIESTunnelHopConfig::DecryptBuildResponseRecord (uint8_t * records) const { uint8_t * record = records + recordIndex*SHORT_TUNNEL_BUILD_RECORD_SIZE; @@ -199,9 +199,9 @@ namespace tunnel { LogPrint (eLogWarning, "Tunnel: Response AEAD decryption failed"); return false; - } + } return true; - } + } void ShortECIESTunnelHopConfig::DecryptRecord (uint8_t * records, int index) const { @@ -210,7 +210,7 @@ namespace tunnel memset (nonce, 0, 12); nonce[4] = index; // nonce is index i2p::crypto::ChaCha20 (record, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, record); - } + } uint64_t ShortECIESTunnelHopConfig::GetGarlicKey (uint8_t * key) const { @@ -218,7 +218,7 @@ namespace tunnel memcpy (&tag, m_CK, 8); memcpy (key, m_CK + 32, 32); return tag; - } + } void TunnelConfig::CreatePeers (const std::vector >& peers) { @@ -236,13 +236,13 @@ namespace tunnel LogPrint (eLogError, "Tunnel: ElGamal router is not supported"); } if (hop) - { + { if (prev) prev->SetNext (hop); else m_FirstHop = hop; prev = hop; - } + } } m_LastHop = prev; } diff --git a/libi2pd/TunnelConfig.h b/libi2pd/TunnelConfig.h index 7934bc6b..88c3addc 100644 --- a/libi2pd/TunnelConfig.h +++ b/libi2pd/TunnelConfig.h @@ -116,8 +116,8 @@ namespace tunnel i2p::data::RouterInfo::CompatibleTransports GetFarEndTransports () const { return m_FarEndTransports; - } - + } + TunnelHopConfig * GetFirstHop () const { return m_FirstHop; diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index ac96ce92..9c294374 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -57,7 +57,7 @@ namespace tunnel // first fragment if (m_CurrentMsgID) AddIncompleteCurrentMessage (); // we have got a new message while previous is not complete - + m_CurrentMessage.deliveryType = (TunnelDeliveryType)((flag >> 5) & 0x03); switch (m_CurrentMessage.deliveryType) { @@ -108,8 +108,8 @@ namespace tunnel { HandleFollowOnFragment (msgID, isLastFragment, fragmentNum, fragment, size); // another m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; - } - } + } + } else { // new message @@ -131,27 +131,27 @@ namespace tunnel } else m_CurrentMessage.data = msg; - + if (isLastFragment) - { + { // single message HandleNextMessage (m_CurrentMessage); m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; - } + } else if (msgID) { // first fragment of a new message m_CurrentMessage.nextFragmentNum = 1; m_CurrentMessage.receiveTime = i2p::util::GetMillisecondsSinceEpoch (); HandleOutOfSequenceFragments (msgID, m_CurrentMessage); - } + } else - { + { LogPrint (eLogError, "TunnelMessage: Message is fragmented, but msgID is not presented"); m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; - } - } - + } + } + fragment += size; } } @@ -159,7 +159,7 @@ namespace tunnel LogPrint (eLogError, "TunnelMessage: Zero not found"); } - void TunnelEndpoint::HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, + void TunnelEndpoint::HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, uint8_t fragmentNum, const uint8_t * fragment, size_t size) { auto it = m_IncompleteMessages.find (msgID); @@ -213,15 +213,15 @@ namespace tunnel msg.data = newMsg; } if (msg.data->Concat (fragment, size) < size) // concatenate fragment - { + { LogPrint (eLogError, "TunnelMessage: I2NP buffer overflow ", msg.data->maxLen); return false; - } + } } else return false; return true; - } + } void TunnelEndpoint::HandleCurrenMessageFollowOnFragment (const uint8_t * fragment, size_t size, bool isLastFragment) { @@ -244,7 +244,7 @@ namespace tunnel LogPrint (eLogError, "TunnelMessage: Fragment ", m_CurrentMessage.nextFragmentNum, " of message ", m_CurrentMsgID, " exceeds max I2NP message size, message dropped"); m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; } - } + } void TunnelEndpoint::AddIncompleteCurrentMessage () { @@ -255,13 +255,13 @@ namespace tunnel LogPrint (eLogError, "TunnelMessage: Incomplete message ", m_CurrentMsgID, " already exists"); m_CurrentMessage.data = nullptr; m_CurrentMsgID = 0; - } - } - + } + } + void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, const uint8_t * fragment, size_t size) { - std::unique_ptr f(new Fragment (isLastFragment, i2p::util::GetMillisecondsSinceEpoch (), size)); + std::unique_ptr f(new Fragment (isLastFragment, i2p::util::GetMillisecondsSinceEpoch (), size)); memcpy (f->data.data (), fragment, size); if (!m_OutOfSequenceFragments.emplace ((uint64_t)msgID << 32 | fragmentNum, std::move (f)).second) LogPrint (eLogInfo, "TunnelMessage: Duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID); @@ -276,10 +276,10 @@ namespace tunnel HandleNextMessage (msg); if (&msg == &m_CurrentMessage) { - m_CurrentMsgID = 0; + m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; - } - else + } + else m_IncompleteMessages.erase (msgID); LogPrint (eLogDebug, "TunnelMessage: All fragments of message ", msgID, " found"); break; diff --git a/libi2pd/TunnelEndpoint.h b/libi2pd/TunnelEndpoint.h index f95eac70..17590a5f 100644 --- a/libi2pd/TunnelEndpoint.h +++ b/libi2pd/TunnelEndpoint.h @@ -49,14 +49,14 @@ namespace tunnel void HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, uint8_t fragmentNum, const uint8_t * fragment, size_t size); bool ConcatFollowOnFragment (TunnelMessageBlockEx& msg, const uint8_t * fragment, size_t size) const; // true if success - void HandleCurrenMessageFollowOnFragment (const uint8_t * fragment, size_t size, bool isLastFragment); + void HandleCurrenMessageFollowOnFragment (const uint8_t * fragment, size_t size, bool isLastFragment); void HandleNextMessage (const TunnelMessageBlock& msg); void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, const uint8_t * fragment, size_t size); bool ConcatNextOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg); // true if something added void HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg); void AddIncompleteCurrentMessage (); - + private: std::unordered_map m_IncompleteMessages; diff --git a/libi2pd/TunnelGateway.cpp b/libi2pd/TunnelGateway.cpp index f4e636dd..12e7652f 100644 --- a/libi2pd/TunnelGateway.cpp +++ b/libi2pd/TunnelGateway.cpp @@ -187,7 +187,7 @@ namespace tunnel RAND_bytes (m_NonZeroRandomBuffer, TUNNEL_DATA_MAX_PAYLOAD_SIZE); for (size_t i = 0; i < TUNNEL_DATA_MAX_PAYLOAD_SIZE; i++) if (!m_NonZeroRandomBuffer[i]) m_NonZeroRandomBuffer[i] = 1; - } + } auto randomOffset = rand () % (TUNNEL_DATA_MAX_PAYLOAD_SIZE - paddingSize + 1); memcpy (buf + 24, m_NonZeroRandomBuffer + randomOffset, paddingSize); } diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 8f607466..1551c45a 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -27,28 +27,28 @@ namespace tunnel void Path::Add (std::shared_ptr r) { if (r) - { + { peers.push_back (r->GetRouterIdentity ()); - if (r->GetVersion () < i2p::data::NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION || + if (r->GetVersion () < i2p::data::NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION || r->GetRouterIdentity ()->GetCryptoKeyType () != i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) isShort = false; - } - } - + } + } + void Path::Reverse () { std::reverse (peers.begin (), peers.end ()); - } - + } + TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels): m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true), m_CustomPeerSelector(nullptr) { - if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY) + if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY) m_NumInboundTunnels = TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY; - if (m_NumOutboundTunnels > TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY) - m_NumOutboundTunnels = TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY; + if (m_NumOutboundTunnels > TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY) + m_NumOutboundTunnels = TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY; m_NextManageTime = i2p::util::GetSecondsSinceEpoch () + rand () % TUNNEL_POOL_MANAGE_INTERVAL; } @@ -114,7 +114,7 @@ namespace tunnel { std::unique_lock l(m_InboundTunnelsMutex); if (createdTunnel->IsRecreated ()) - { + { // find and mark old tunnel as expired createdTunnel->SetRecreated (false); for (auto& it: m_InboundTunnels) @@ -122,8 +122,8 @@ namespace tunnel { it->SetState (eTunnelStateExpiring); break; - } - } + } + } m_InboundTunnels.insert (createdTunnel); } if (m_LocalDestination) @@ -179,10 +179,10 @@ namespace tunnel if (it->IsSlow () && !slowTunnel) slowTunnel = it; else - { + { v.push_back (it); i++; - } + } } } if (slowTunnel && (int)v.size () < (num/2+1)) @@ -205,7 +205,7 @@ namespace tunnel } template - typename TTunnels::value_type TunnelPool::GetNextTunnel (TTunnels& tunnels, + typename TTunnels::value_type TunnelPool::GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type excluded, i2p::data::RouterInfo::CompatibleTransports compatible) const { if (tunnels.empty ()) return nullptr; @@ -216,8 +216,8 @@ namespace tunnel { if (it->IsEstablished () && it != excluded && (compatible & it->GetFarEndTransports ())) { - if (it->IsSlow () || (HasLatencyRequirement() && it->LatencyIsKnown() && - !it->LatencyFitsRange(m_MinLatency, m_MaxLatency))) + if (it->IsSlow () || (HasLatencyRequirement() && it->LatencyIsKnown() && + !it->LatencyFitsRange(m_MinLatency, m_MaxLatency))) { i++; skipped = true; continue; @@ -227,7 +227,7 @@ namespace tunnel } if (i > ind && tunnel) break; } - if (!tunnel && skipped) + if (!tunnel && skipped) { ind = rand () % (tunnels.size ()/2 + 1), i = 0; for (const auto& it: tunnels) @@ -284,12 +284,12 @@ namespace tunnel if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0) { for (auto it: m_OutboundTunnels) - { + { CreatePairedInboundTunnel (it); num++; if (num >= m_NumInboundTunnels) break; - } - } + } + } for (int i = num; i < m_NumInboundTunnels; i++) CreateInboundTunnel (); @@ -371,13 +371,13 @@ namespace tunnel void TunnelPool::ManageTunnels (uint64_t ts) { if (ts > m_NextManageTime) - { + { CreateTunnels (); TestTunnels (); - m_NextManageTime = ts + TUNNEL_POOL_MANAGE_INTERVAL + (rand () % TUNNEL_POOL_MANAGE_INTERVAL)/2; - } - } - + m_NextManageTime = ts + TUNNEL_POOL_MANAGE_INTERVAL + (rand () % TUNNEL_POOL_MANAGE_INTERVAL)/2; + } + } + void TunnelPool::ProcessGarlicMessage (std::shared_ptr msg) { if (m_LocalDestination) @@ -412,19 +412,19 @@ namespace tunnel uint64_t latency = dlt / 2; // restore from test failed state if any if (test.first) - { + { if (test.first->GetState () == eTunnelStateTestFailed) test.first->SetState (eTunnelStateEstablished); // update latency test.first->AddLatencySample(latency); - } + } if (test.second) - { + { if (test.second->GetState () == eTunnelStateTestFailed) test.second->SetState (eTunnelStateEstablished); // update latency test.second->AddLatencySample(latency); - } + } } else { @@ -438,8 +438,8 @@ namespace tunnel bool TunnelPool::IsExploratory () const { return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this (); - } - + } + std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse) const { auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse): @@ -467,7 +467,7 @@ namespace tunnel (inbound && i2p::transport::transports.GetNumPeers () > 25)) { auto r = i2p::transport::transports.GetRandomPeer (); - if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && + if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && (numHops > 1 || (r->IsV4 () && (!inbound || r->IsReachable ())))) // first inbound must be reachable { prevHop = r; @@ -480,11 +480,11 @@ namespace tunnel { auto hop = nextHop (prevHop, inbound); if (!hop && !i) // if no suitable peer found for first hop, try already connected - { + { LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected"); hop = i2p::transport::transports.GetRandomPeer (); if (hop && !hop->IsECIES ()) hop = nullptr; - } + } if (!hop) { LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); @@ -495,7 +495,7 @@ namespace tunnel { auto hop1 = nextHop (prevHop, true); if (hop1) hop = hop1; - } + } prevHop = hop; path.Add (hop); } @@ -523,25 +523,25 @@ namespace tunnel { int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; if (numHops > (int)m_ExplicitPeers->size ()) numHops = m_ExplicitPeers->size (); - if (!numHops) return false; + if (!numHops) return false; for (int i = 0; i < numHops; i++) { auto& ident = (*m_ExplicitPeers)[i]; auto r = i2p::data::netdb.FindRouter (ident); if (r) - { - if (r->IsECIES ()) - { + { + if (r->IsECIES ()) + { path.Add (r); if (i == numHops - 1) path.farEndTransports = r->GetCompatibleTransports (isInbound); - } + } else - { + { LogPrint (eLogError, "Tunnels: ElGamal router ", ident.ToBase64 (), " is not supported"); - return false; - } - } + return false; + } + } else { LogPrint (eLogInfo, "Tunnels: Can't find router for ", ident.ToBase64 ()); @@ -612,14 +612,14 @@ namespace tunnel { LogPrint (eLogError, "Tunnels: Can't create outbound tunnel, no inbound tunnels found"); return; - } - + } + if (m_LocalDestination && !m_LocalDestination->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) path.isShort = false; // because can't handle ECIES encrypted reply - + std::shared_ptr config; if (m_NumOutboundHops > 0) - config = std::make_shared(path.peers, inboundTunnel->GetNextTunnelID (), + config = std::make_shared(path.peers, inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash (), path.isShort, path.farEndTransports); std::shared_ptr tunnel; @@ -628,8 +628,8 @@ namespace tunnel // TODO: implement it better tunnel = tunnels.CreateOutboundTunnel (config, inboundTunnel->GetTunnelPool ()); tunnel->SetTunnelPool (shared_from_this ()); - } - else + } + else tunnel = tunnels.CreateOutboundTunnel (config, shared_from_this ()); if (tunnel && tunnel->IsEstablished ()) // zero hops TunnelCreated (tunnel); @@ -654,7 +654,7 @@ namespace tunnel std::shared_ptr config; if (m_NumOutboundHops > 0 && tunnel->GetPeers().size()) { - config = std::make_shared(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), + config = std::make_shared(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash (), inboundTunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); } if (!m_NumOutboundHops || config) @@ -673,7 +673,7 @@ namespace tunnel LogPrint (eLogDebug, "Tunnels: Creating paired inbound tunnel..."); auto tunnel = tunnels.CreateInboundTunnel ( m_NumOutboundHops > 0 ? std::make_shared(outboundTunnel->GetInvertedPeers (), - outboundTunnel->IsShortBuildMessage ()) : nullptr, + outboundTunnel->IsShortBuildMessage ()) : nullptr, shared_from_this (), outboundTunnel); if (tunnel->IsEstablished ()) // zero hops TunnelCreated (tunnel); diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 41cc400f..4a14ff2f 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -30,7 +30,7 @@ namespace tunnel const int TUNNEL_POOL_MANAGE_INTERVAL = 10; // in seconds const int TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY = 16; const int TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY = 16; - + class Tunnel; class InboundTunnel; class OutboundTunnel; @@ -41,7 +41,7 @@ namespace tunnel std::vector peers; bool isShort = true; i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports; - + void Add (std::shared_ptr r); void Reverse (); }; @@ -56,7 +56,7 @@ namespace tunnel typedef std::function(std::shared_ptr, bool)> SelectHopFunc; bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); - + class TunnelPool: public std::enable_shared_from_this // per local destination { public: @@ -122,7 +122,7 @@ namespace tunnel void CreateOutboundTunnel (); void CreatePairedInboundTunnel (std::shared_ptr outboundTunnel); template - typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels, + typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type excluded, i2p::data::RouterInfo::CompatibleTransports compatible) const; bool SelectPeers (Path& path, bool isInbound); bool SelectExplicitPeers (Path& path, bool isInbound); diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index d3b78515..350b1c92 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -425,14 +425,14 @@ namespace net static bool IsYggdrasilAddress (const uint8_t addr[16]) { return addr[0] == 0x02 || addr[0] == 0x03; - } + } bool IsYggdrasilAddress (const boost::asio::ip::address& addr) { if (!addr.is_v6 ()) return false; return IsYggdrasilAddress (addr.to_v6 ().to_bytes ().data ()); - } - + } + boost::asio::ip::address_v6 GetYggdrasilAddress () { #if defined(_WIN32) @@ -517,11 +517,11 @@ namespace net GetMTUWindows(addr, 0); #else GetMTUUnix(addr, 0); -#endif +#endif return mtu > 0; - } - - bool IsInReservedRange (const boost::asio::ip::address& host) + } + + bool IsInReservedRange (const boost::asio::ip::address& host) { // https://en.wikipedia.org/wiki/Reserved_IP_addresses if (host.is_unspecified ()) return false; diff --git a/libi2pd/util.h b/libi2pd/util.h index d681829c..2c74d4dd 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -58,8 +58,8 @@ namespace util { CleanUp (m_Head); m_Head = nullptr; - } - + } + template T * Acquire (TArgs&&... args) { @@ -104,8 +104,8 @@ namespace util head = static_cast(*(void * *)head); // next ::operator delete ((void *)tmp); } - } - + } + protected: T * m_Head; @@ -152,11 +152,11 @@ namespace util { std::lock_guard l(m_Mutex); head = this->m_Head; - this->m_Head = nullptr; + this->m_Head = nullptr; } if (head) this->CleanUp (head); - } - + } + private: std::mutex m_Mutex; diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 4c0134fe..ba6623b6 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -35,7 +35,7 @@ namespace client class AddressBookFilesystemStorage: public AddressBookStorage { public: - + AddressBookFilesystemStorage (): storage("addressbook", "b", "", "b32") { i2p::config::GetOption("persist.addressbook", m_IsPersist); @@ -62,7 +62,7 @@ namespace client private: i2p::fs::HashedStorage storage; - std::string etagsPath, indexPath, localPath; + std::string etagsPath, indexPath, localPath; bool m_IsPersist; std::string m_HostsFile; // file to dump hosts.txt, empty if not used }; @@ -185,7 +185,7 @@ namespace client int AddressBookFilesystemStorage::Save (const std::map >& addresses) { - if (addresses.empty()) + if (addresses.empty()) { LogPrint(eLogWarning, "Addressbook: Not saving empty addressbook"); return 0; @@ -200,7 +200,7 @@ namespace client for (const auto& it: addresses) { if (it.second->IsValid ()) - { + { f << it.first << ","; if (it.second->IsIdentHash ()) f << it.second->identHash.ToBase32 (); @@ -208,15 +208,15 @@ namespace client f << it.second->blindedPublicKey->ToB33 (); f << std::endl; num++; - } + } else LogPrint (eLogWarning, "Addressbook: Invalid address ", it.first); } LogPrint (eLogInfo, "Addressbook: ", num, " addresses saved"); - } + } else LogPrint (eLogWarning, "Addressbook: Can't open ", indexPath); - } + } if (!m_HostsFile.empty ()) { // dump full hosts.txt @@ -226,18 +226,18 @@ namespace client for (const auto& it: addresses) { std::shared_ptr addr; - if (it.second->IsIdentHash ()) - { + if (it.second->IsIdentHash ()) + { addr = GetAddress (it.second->identHash); if (addr) f << it.first << "=" << addr->ToBase64 () << std::endl; - } - } - } + } + } + } else LogPrint (eLogWarning, "Addressbook: Can't open ", m_HostsFile); - } - + } + return num; } @@ -495,7 +495,7 @@ namespace client if (it != m_Addresses.end ()) // already exists ? { if (it->second->IsIdentHash () && it->second->identHash != ident->GetIdentHash () && // address changed? - ident->GetSigningKeyType () != i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) // don't replace by DSA + ident->GetSigningKeyType () != i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) // don't replace by DSA { it->second->identHash = ident->GetIdentHash (); m_Storage->AddAddress (ident); diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index c10d2285..61c5d531 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -660,7 +660,7 @@ namespace client else SendReplyError ("Local LeaseSet Not found"); } - + void BOBCommandSession::ClearCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: clear"); @@ -786,7 +786,7 @@ namespace client m_CommandHandlers[BOB_COMMAND_INPORT] = &BOBCommandSession::InportCommandHandler; m_CommandHandlers[BOB_COMMAND_QUIET] = &BOBCommandSession::QuietCommandHandler; m_CommandHandlers[BOB_COMMAND_LOOKUP] = &BOBCommandSession::LookupCommandHandler; - m_CommandHandlers[BOB_COMMAND_LOOKUP_LOCAL] = &BOBCommandSession::LookupLocalCommandHandler; + m_CommandHandlers[BOB_COMMAND_LOOKUP_LOCAL] = &BOBCommandSession::LookupLocalCommandHandler; m_CommandHandlers[BOB_COMMAND_CLEAR] = &BOBCommandSession::ClearCommandHandler; m_CommandHandlers[BOB_COMMAND_LIST] = &BOBCommandSession::ListCommandHandler; m_CommandHandlers[BOB_COMMAND_OPTION] = &BOBCommandSession::OptionCommandHandler; diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index e185da8b..b58db037 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -406,7 +406,7 @@ namespace client void ClientContext::CreateNewSharedLocalDestination () { - std::map params + std::map params { { I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, "3" }, { I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, "3" }, @@ -720,10 +720,10 @@ namespace client std::shared_ptr localDestination = nullptr; auto it = destinations.find (keys); if (it != destinations.end ()) - { + { localDestination = it->second; localDestination->SetPublic (true); - } + } else { i2p::data::PrivateKeys k; @@ -767,10 +767,10 @@ namespace client LogPrint(eLogInfo, "Clients: I2P Server Forward created for UDP Endpoint ", host, ":", port, " bound on ", address, " for ",localDestination->GetIdentHash().ToBase32()); } else - { + { ins.first->second->isUpdated = true; LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, " already exists"); - } + } continue; } diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index cb28e40e..7dd6ff82 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -107,7 +107,7 @@ namespace client // i18n std::shared_ptr GetLanguage () { return m_Language; }; void SetLanguage (const std::shared_ptr language) { m_Language = language; }; - + private: void ReadTunnels (); @@ -157,7 +157,7 @@ namespace client // i18n std::shared_ptr m_Language; - + public: // for HTTP diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 437df43b..a86153b9 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -23,7 +23,7 @@ namespace i2p namespace client { - I2CPDestination::I2CPDestination (boost::asio::io_service& service, std::shared_ptr owner, + I2CPDestination::I2CPDestination (boost::asio::io_service& service, std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params): LeaseSetDestination (service, isPublic, ¶ms), m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()), @@ -36,8 +36,8 @@ namespace client LeaseSetDestination::Stop (); m_Owner = nullptr; m_LeaseSetCreationTimer.cancel (); - } - + } + void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key) { m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), key); @@ -46,12 +46,12 @@ namespace client void I2CPDestination::SetECIESx25519EncryptionPrivateKey (const uint8_t * key) { if (!m_ECIESx25519Decryptor || memcmp (m_ECIESx25519PrivateKey, key, 32)) // new key? - { + { m_ECIESx25519Decryptor = std::make_shared(key, true); // calculate public memcpy (m_ECIESx25519PrivateKey, key, 32); - } - } - + } + } + bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const { if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD && m_ECIESx25519Decryptor) @@ -68,14 +68,14 @@ namespace client if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD && m_ECIESx25519Decryptor) return m_ECIESx25519Decryptor->GetPubicKey (); return nullptr; - } + } - bool I2CPDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const - { - return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? (bool)m_ECIESx25519Decryptor : m_EncryptionKeyType == keyType; + bool I2CPDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const + { + return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? (bool)m_ECIESx25519Decryptor : m_EncryptionKeyType == keyType; } - - + + void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len) { uint32_t length = bufbe32toh (buf); @@ -88,25 +88,25 @@ namespace client { GetService ().post (std::bind (&I2CPDestination::PostCreateNewLeaseSet, this, tunnels)); } - + void I2CPDestination::PostCreateNewLeaseSet (std::vector > tunnels) { if (m_IsCreatingLeaseSet) { LogPrint (eLogInfo, "I2CP: LeaseSet is being created"); return; - } + } uint8_t priv[256] = {0}; i2p::data::LocalLeaseSet ls (m_Identity, priv, tunnels); // we don't care about encryption key, we need leases only m_LeaseSetExpirationTime = ls.GetExpirationTime (); uint8_t * leases = ls.GetLeases (); leases[-1] = tunnels.size (); if (m_Owner) - { + { uint16_t sessionID = m_Owner->GetSessionID (); if (sessionID != 0xFFFF) - { - m_IsCreatingLeaseSet = true; + { + m_IsCreatingLeaseSet = true; htobe16buf (leases - 3, sessionID); size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size (); m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); @@ -120,8 +120,8 @@ namespace client if (s->m_Owner) s->m_Owner->Stop (); } }); - } - } + } + } } void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len) @@ -237,18 +237,18 @@ namespace client } } - RunnableI2CPDestination::RunnableI2CPDestination (std::shared_ptr owner, + RunnableI2CPDestination::RunnableI2CPDestination (std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params): RunnableService ("I2CP"), I2CPDestination (GetIOService (), owner, identity, isPublic, params) { - } + } RunnableI2CPDestination::~RunnableI2CPDestination () { if (IsRunning ()) Stop (); - } + } void RunnableI2CPDestination::Start () { @@ -267,9 +267,9 @@ namespace client StopIOService (); } } - + I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): - m_Owner (owner), m_Socket (socket), m_SessionID (0xFFFF), + m_Owner (owner), m_Socket (socket), m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true), m_IsSending (false) { } @@ -307,11 +307,11 @@ namespace client void I2CPSession::ReceiveHeader () { - if (!m_Socket) + if (!m_Socket) { LogPrint (eLogError, "I2CP: Can't receive header"); return; - } + } boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Header, I2CP_HEADER_SIZE), boost::asio::transfer_all (), std::bind (&I2CPSession::HandleReceivedHeader, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); @@ -344,11 +344,11 @@ namespace client void I2CPSession::ReceivePayload () { - if (!m_Socket) - { + if (!m_Socket) + { LogPrint (eLogError, "I2CP: Can't receive payload"); return; - } + } boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Payload, m_PayloadLen), boost::asio::transfer_all (), std::bind (&I2CPSession::HandleReceivedPayload, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); @@ -390,11 +390,11 @@ namespace client if (!m_SendQueue.IsEmpty ()) m_SendQueue.CleanUp (); if (m_SessionID != 0xFFFF) - { + { m_Owner.RemoveSession (GetSessionID ()); LogPrint (eLogDebug, "I2CP: Session ", m_SessionID, " terminated"); m_SessionID = 0xFFFF; - } + } } void I2CPSession::SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len) @@ -404,39 +404,39 @@ namespace client { LogPrint (eLogError, "I2CP: Message to send is too long ", l); return; - } + } auto sendBuf = m_IsSending ? std::make_shared (l) : nullptr; uint8_t * buf = sendBuf ? sendBuf->buf : m_SendBuffer; htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len); buf[I2CP_HEADER_TYPE_OFFSET] = type; memcpy (buf + I2CP_HEADER_SIZE, payload, len); if (sendBuf) - { + { if (m_SendQueue.GetSize () < I2CP_MAX_SEND_QUEUE_SIZE) m_SendQueue.Add (sendBuf); - else - { - LogPrint (eLogWarning, "I2CP: Send queue size exceeds ", I2CP_MAX_SEND_QUEUE_SIZE); - return; - } - } + else + { + LogPrint (eLogWarning, "I2CP: Send queue size exceeds ", I2CP_MAX_SEND_QUEUE_SIZE); + return; + } + } else { auto socket = m_Socket; if (socket) - { + { m_IsSending = true; - boost::asio::async_write (*socket, boost::asio::buffer (m_SendBuffer, l), - boost::asio::transfer_all (), std::bind(&I2CPSession::HandleI2CPMessageSent, + boost::asio::async_write (*socket, boost::asio::buffer (m_SendBuffer, l), + boost::asio::transfer_all (), std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); - } - } + } + } } void I2CPSession::HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) - { + { if (ecode != boost::asio::error::operation_aborted) Terminate (); } @@ -444,19 +444,19 @@ namespace client { auto socket = m_Socket; if (socket) - { + { auto len = m_SendQueue.Get (m_SendBuffer, I2CP_MAX_MESSAGE_LENGTH); - boost::asio::async_write (*socket, boost::asio::buffer (m_SendBuffer, len), - boost::asio::transfer_all (),std::bind(&I2CPSession::HandleI2CPMessageSent, + boost::asio::async_write (*socket, boost::asio::buffer (m_SendBuffer, len), + boost::asio::transfer_all (),std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); - } + } else m_IsSending = false; } else m_IsSending = false; } - + std::string I2CPSession::ExtractString (const uint8_t * buf, size_t len) { uint8_t l = buf[0]; @@ -699,12 +699,12 @@ namespace client m_Destination->SetECIESx25519EncryptionPrivateKey (buf + offset); else { - m_Destination->SetEncryptionType (keyType); + m_Destination->SetEncryptionType (keyType); m_Destination->SetEncryptionPrivateKey (buf + offset); } offset += keyLen; } - + m_Destination->LeaseSet2Created (storeType, ls.GetBuffer (), ls.GetBufferLen ()); } } @@ -885,7 +885,7 @@ namespace client { LogPrint (eLogError, "I2CP: Message to send is too long ", l); return; - } + } auto sendBuf = m_IsSending ? std::make_shared (l) : nullptr; uint8_t * buf = sendBuf ? sendBuf->buf : m_SendBuffer; htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len + 10); @@ -895,26 +895,26 @@ namespace client htobe32buf (buf + I2CP_HEADER_SIZE + 6, len); memcpy (buf + I2CP_HEADER_SIZE + 10, payload, len); if (sendBuf) - { + { if (m_SendQueue.GetSize () < I2CP_MAX_SEND_QUEUE_SIZE) m_SendQueue.Add (sendBuf); - else - { - LogPrint (eLogWarning, "I2CP: Send queue size exceeds ", I2CP_MAX_SEND_QUEUE_SIZE); - return; - } - } + else + { + LogPrint (eLogWarning, "I2CP: Send queue size exceeds ", I2CP_MAX_SEND_QUEUE_SIZE); + return; + } + } else { auto socket = m_Socket; if (socket) - { + { m_IsSending = true; - boost::asio::async_write (*socket, boost::asio::buffer (m_SendBuffer, l), - boost::asio::transfer_all (), std::bind(&I2CPSession::HandleI2CPMessageSent, + boost::asio::async_write (*socket, boost::asio::buffer (m_SendBuffer, l), + boost::asio::transfer_all (), std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); - } - } + } + } } I2CPServer::I2CPServer (const std::string& interface, int port, bool isSingleThread): diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 08a96af6..b2e1d15f 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -27,8 +27,8 @@ namespace client const size_t I2CP_SESSION_BUFFER_SIZE = 4096; const size_t I2CP_MAX_MESSAGE_LENGTH = 65535; const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M - const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds - + const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds + const size_t I2CP_HEADER_LENGTH_OFFSET = 0; const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4; const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; @@ -69,12 +69,12 @@ namespace client { public: - I2CPDestination (boost::asio::io_service& service, std::shared_ptr owner, + I2CPDestination (boost::asio::io_service& service, std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params); ~I2CPDestination () {}; void Stop (); - + void SetEncryptionPrivateKey (const uint8_t * key); void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; }; void SetECIESx25519EncryptionPrivateKey (const uint8_t * key); @@ -84,7 +84,7 @@ namespace client // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const; - bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const; + bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const; const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const; // for 4 only std::shared_ptr GetIdentity () const { return m_Identity; }; @@ -101,7 +101,7 @@ namespace client bool SendMsg (std::shared_ptr msg, std::shared_ptr remote); void PostCreateNewLeaseSet (std::vector > tunnels); - + private: std::shared_ptr m_Owner; @@ -115,18 +115,18 @@ namespace client boost::asio::deadline_timer m_LeaseSetCreationTimer; }; - class RunnableI2CPDestination: private i2p::util::RunnableService, public I2CPDestination + class RunnableI2CPDestination: private i2p::util::RunnableService, public I2CPDestination { public: - RunnableI2CPDestination (std::shared_ptr owner, std::shared_ptr identity, - bool isPublic, const std::map& params); + RunnableI2CPDestination (std::shared_ptr owner, std::shared_ptr identity, + bool isPublic, const std::map& params); ~RunnableI2CPDestination (); void Start (); void Stop (); - }; - + }; + class I2CPServer; class I2CPSession: public std::enable_shared_from_this { @@ -174,9 +174,9 @@ namespace client void HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleMessage (); void Terminate (); - + void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred); - + std::string ExtractString (const uint8_t * buf, size_t len); size_t PutString (uint8_t * buf, size_t len, const std::string& str); void ExtractMapping (const uint8_t * buf, size_t len, std::map& mapping); @@ -198,7 +198,7 @@ namespace client // to client bool m_IsSending; uint8_t m_SendBuffer[I2CP_MAX_MESSAGE_LENGTH]; - i2p::stream::SendBufferQueue m_SendQueue; + i2p::stream::SendBufferQueue m_SendQueue; }; typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len); @@ -213,7 +213,7 @@ namespace client void Stop (); boost::asio::io_service& GetService () { return GetIOService (); }; bool IsSingleThread () const { return m_IsSingleThread; }; - + bool InsertSession (std::shared_ptr session); void RemoveSession (uint16_t sessionID); diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 9715e5c6..afb13a18 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -87,7 +87,7 @@ namespace client boost::system::error_code ec; sock->bind (boost::asio::ip::tcp::endpoint (ourIP, 0), ec); if (ec) - LogPrint (eLogError, "I2PTunnel: Can't bind ourIP to ", ourIP.to_string (), ": ", ec.message ()); + LogPrint (eLogError, "I2PTunnel: Can't bind ourIP to ", ourIP.to_string (), ": ", ec.message ()); } #endif @@ -122,11 +122,11 @@ namespace client boost::system::error_code ec; m_Socket->bind (boost::asio::ip::tcp::endpoint (localAddress, 0), ec); if (ec) - LogPrint (eLogError, "I2PTunnel: Can't bind to ", localAddress.to_string (), ": ", ec.message ()); - } + LogPrint (eLogError, "I2PTunnel: Can't bind to ", localAddress.to_string (), ": ", ec.message ()); + } Connect (false); - } - + } + void I2PTunnelConnection::Terminate () { if (Kill()) return; @@ -177,8 +177,8 @@ namespace client s->Terminate (); }); } - } - + } + void I2PTunnelConnection::HandleWrite (const boost::system::error_code& ecode) { if (ecode) @@ -326,7 +326,7 @@ namespace client I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, const std::string& host): - I2PTunnelConnection (owner, stream, socket, target), m_Host (host), + I2PTunnelConnection (owner, stream, socket, target), m_Host (host), m_HeaderSent (false), m_ResponseHeaderSent (false), m_From (stream->GetRemoteIdentity ()) { } @@ -368,7 +368,7 @@ namespace client m_OutHeader << X_I2P_DEST_HASH << ": " << m_From->GetIdentHash ().ToBase64 () << "\r\n"; m_OutHeader << X_I2P_DEST_B64 << ": " << m_From->ToBase64 () << "\r\n"; } - + m_OutHeader << "\r\n"; // end of header m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header m_InHeader.str (""); @@ -404,11 +404,11 @@ namespace client }; bool matched = false; for (const auto& it: excluded) - if (!line.compare(0, it.length (), it)) + if (!line.compare(0, it.length (), it)) { matched = true; - break; - } + break; + } if (!matched) m_OutHeader << line << "\n"; } @@ -425,12 +425,12 @@ namespace client m_ResponseHeaderSent = true; I2PTunnelConnection::WriteToStream ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ()); m_OutHeader.str (""); - } + } else Receive (); - } + } } - + I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass): @@ -556,8 +556,8 @@ namespace client m_KeepAliveInterval = keepAliveInterval; if (m_KeepAliveInterval) m_KeepAliveTimer.reset (new boost::asio::deadline_timer (GetLocalDestination ()->GetService ())); - } - + } + /* HACK: maybe we should create a caching IdentHash provider in AddressBook */ std::shared_ptr I2PClientTunnel::GetAddress () { @@ -586,24 +586,24 @@ namespace client m_KeepAliveTimer->expires_from_now (boost::posix_time::seconds(m_KeepAliveInterval)); m_KeepAliveTimer->async_wait (std::bind (&I2PClientTunnel::HandleKeepAliveTimer, this, std::placeholders::_1)); - } - } + } + } void I2PClientTunnel::HandleKeepAliveTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) { if (m_Address && m_Address->IsValid ()) - { + { if (m_Address->IsIdentHash ()) GetLocalDestination ()->SendPing (m_Address->identHash); else GetLocalDestination ()->SendPing (m_Address->blindedPublicKey); - } + } ScheduleKeepAliveTimer (); } - } - + } + I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address, int port, std::shared_ptr localDestination, int inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) @@ -643,16 +643,16 @@ namespace client bool found = false; boost::asio::ip::tcp::endpoint ep; if (m_LocalAddress) - { + { boost::asio::ip::tcp::resolver::iterator end; while (it != end) - { + { ep = *it; if (!ep.address ().is_unspecified ()) { if (ep.address ().is_v4 ()) - { - if (m_LocalAddress->is_v4 ()) found = true; + { + if (m_LocalAddress->is_v4 ()) found = true; } else if (ep.address ().is_v6 ()) { @@ -660,26 +660,26 @@ namespace client { if (i2p::util::net::IsYggdrasilAddress (*m_LocalAddress)) found = true; - } - else if (m_LocalAddress->is_v6 ()) + } + else if (m_LocalAddress->is_v6 ()) found = true; } - } + } if (found) break; it++; } - } + } else { found = true; ep = *it; // first available - } + } if (!found) { LogPrint (eLogError, "I2PTunnel: Unable to resolve to compatible address"); return; - } - + } + auto addr = ep.address (); LogPrint (eLogInfo, "I2PTunnel: Server tunnel ", (*it).host_name (), " has been resolved to ", addr); m_Endpoint.address (addr); @@ -703,8 +703,8 @@ namespace client m_LocalAddress.reset (new boost::asio::ip::address (addr)); else LogPrint (eLogError, "I2PTunnel: Can't set local address ", localAddress); - } - + } + void I2PServerTunnel::Accept () { if (m_PortDestination) @@ -738,7 +738,7 @@ namespace client AddHandler (conn); if (m_LocalAddress) conn->Connect (*m_LocalAddress); - else + else conn->Connect (m_IsUniqueLocal); } } @@ -793,9 +793,9 @@ namespace client { m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - } - } - + } + } + void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { std::lock_guard lock(m_SessionsMutex); uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); @@ -883,20 +883,20 @@ namespace client m_Destination->SendRawDatagram(session, m_Buffer, len, LocalPort, RemotePort); size_t numPackets = 0; while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) - { + { boost::system::error_code ec; size_t moreBytes = IPSocket.available(ec); if (ec || !moreBytes) break; len = IPSocket.receive_from (boost::asio::buffer (m_Buffer, I2P_UDP_MAX_MTU), FromEndpoint, 0, ec); - m_Destination->SendRawDatagram (session, m_Buffer, len, LocalPort, RemotePort); + m_Destination->SendRawDatagram (session, m_Buffer, len, LocalPort, RemotePort); numPackets++; - } + } if (numPackets > 0) LogPrint(eLogDebug, "UDPSession: Forward more ", numPackets, "packets B from ", FromEndpoint); m_Destination->FlushSendQueue (session); LastActivity = ts; Receive(); - } + } else LogPrint(eLogError, "UDPSession: ", ecode.message()); } @@ -912,7 +912,7 @@ namespace client m_LocalDest->Start(); auto dgram = m_LocalDest->CreateDatagramDestination(gzip); dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); - dgram->SetRawReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + dgram->SetRawReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); } I2PUDPServerTunnel::~I2PUDPServerTunnel() @@ -1011,9 +1011,9 @@ namespace client { m_LastSession = std::make_shared(boost::asio::ip::udp::endpoint(m_RecvEndpoint), 0); m_Sessions.emplace (remotePort, m_LastSession); - } + } m_LastPort = remotePort; - } + } // send off to remote i2p destination auto ts = i2p::util::GetMillisecondsSinceEpoch(); LogPrint(eLogDebug, "UDP Client: Send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort); @@ -1024,20 +1024,20 @@ namespace client m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); size_t numPackets = 0; while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) - { + { boost::system::error_code ec; size_t moreBytes = m_LocalSocket.available(ec); if (ec || !moreBytes) break; transferred = m_LocalSocket.receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec); remotePort = m_RecvEndpoint.port(); // TODO: check remotePort - m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); + m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); numPackets++; - } + } if (numPackets) LogPrint(eLogDebug, "UDP Client: Sent ", numPackets, " more packets to ", m_RemoteIdent->ToBase32()); m_LocalDest->GetDatagramDestination()->FlushSendQueue (session); - + // mark convo as active if (m_LastSession) m_LastSession->second = ts; @@ -1091,7 +1091,7 @@ namespace client if(itr != m_Sessions.end()) { // found convo - if (len > 0) + if (len > 0) { LogPrint(eLogDebug, "UDP Client: Got ", len, "B from ", m_RemoteIdent ? m_RemoteIdent->ToBase32() : ""); m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second->first); diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index d21b2e11..53e893af 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -49,7 +49,7 @@ namespace client void I2PConnect (const uint8_t * msg = nullptr, size_t len = 0); void Connect (bool isUniqueLocal = true); void Connect (const boost::asio::ip::address& localAddress); - + protected: void Terminate (); @@ -59,7 +59,7 @@ namespace client virtual void Write (const uint8_t * buf, size_t len); // can be overloaded void HandleWrite (const boost::system::error_code& ecode); virtual void WriteToStream (const uint8_t * buf, size_t len); // can be overloaded - + void StreamReceive (); void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleConnect (const boost::system::error_code& ecode); @@ -105,7 +105,7 @@ namespace client protected: void Write (const uint8_t * buf, size_t len); - void WriteToStream (const uint8_t * buf, size_t len); + void WriteToStream (const uint8_t * buf, size_t len); private: @@ -154,11 +154,11 @@ namespace client const char* GetName() { return m_Name.c_str (); } void SetKeepAliveInterval (uint32_t keepAliveInterval); - + private: std::shared_ptr GetAddress (); - + void ScheduleKeepAliveTimer (); void HandleKeepAliveTimer (const boost::system::error_code& ecode); @@ -174,8 +174,8 @@ namespace client /** 2 minute timeout for udp sessions */ const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2; - const uint64_t I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL = 100; // in milliseconds - + const uint64_t I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL = 100; // in milliseconds + /** max size for i2p udp */ const size_t I2P_UDP_MAX_MTU = 64*1024; @@ -330,7 +330,7 @@ namespace client bool IsUniqueLocal () const { return m_IsUniqueLocal; } void SetLocalAddress (const std::string& localAddress); - + const std::string& GetAddress() const { return m_Address; } int GetPort () const { return m_Port; }; uint16_t GetLocalPort () const { return m_PortDestination->GetLocalPort (); }; diff --git a/libi2pd_client/MatchedDestination.cpp b/libi2pd_client/MatchedDestination.cpp index 666e260e..ce800ecc 100644 --- a/libi2pd_client/MatchedDestination.cpp +++ b/libi2pd_client/MatchedDestination.cpp @@ -72,7 +72,7 @@ namespace client bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound) { auto pool = GetTunnelPool(); - if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound, + if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound, std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, std::placeholders::_2))) return false; // more here for outbound tunnels @@ -86,14 +86,14 @@ namespace client auto leases = m_RemoteLeaseSet->GetNonExpiredLeases(); // pick lease std::shared_ptr obep; - while(!obep && leases.size() > 0) + while(!obep && leases.size() > 0) { auto idx = rand() % leases.size(); auto lease = leases[idx]; obep = i2p::data::netdb.FindRouter(lease->tunnelGateway); leases.erase(leases.begin()+idx); } - if(obep) + if(obep) { path.Add (obep); LogPrint(eLogDebug, "Destination: Found OBEP matching IBGW"); diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index cbba4cc1..d58a5128 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -54,7 +54,7 @@ namespace client break; } case eSAMSocketTypeAcceptor: - case eSAMSocketTypeForward: + case eSAMSocketTypeForward: { if (Session) { @@ -481,7 +481,7 @@ namespace client { SendI2PError ("Socket already in use"); return; - } + } std::map params; ExtractParams (buf, params); std::string& id = params[SAM_PARAM_ID]; @@ -502,7 +502,7 @@ namespace client std::shared_ptr addr; if (destination.find(".i2p") != std::string::npos) - addr = context.GetAddressBook().GetAddress (destination); + addr = context.GetAddressBook().GetAddress (destination); else { auto dest = std::make_shared (); @@ -511,13 +511,13 @@ namespace client { context.GetAddressBook().InsertFullAddress(dest); addr = std::make_shared
(dest->GetIdentHash ()); - } - } - + } + } + if (addr && addr->IsValid ()) { if (addr->IsIdentHash ()) - { + { auto leaseSet = session->GetLocalDestination ()->FindLeaseSet(addr->identHash); if (leaseSet) Connect(leaseSet, session); @@ -527,7 +527,7 @@ namespace client std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete, shared_from_this(), std::placeholders::_1)); } - } + } else // B33 session->GetLocalDestination ()->RequestDestinationWithEncryptedLeaseSet (addr->blindedPublicKey, std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete, @@ -548,12 +548,12 @@ namespace client m_SocketType = eSAMSocketTypeStream; m_Stream = session->GetLocalDestination ()->CreateStream (remote); if (m_Stream) - { + { m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send m_BufferOffset = 0; I2PReceive (); SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); - } + } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } @@ -579,7 +579,7 @@ namespace client { SendI2PError ("Socket already in use"); return; - } + } std::map params; ExtractParams (buf, params); std::string& id = params[SAM_PARAM_ID]; @@ -612,42 +612,42 @@ namespace client { SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); return; - } + } if (session->GetLocalDestination ()->IsAcceptingStreams ()) - { + { SendI2PError ("Already accepting"); return; - } + } auto it = params.find (SAM_PARAM_PORT); if (it == params.end ()) { SendI2PError ("PORT is missing"); return; - } + } auto port = std::stoi (it->second); if (port <= 0 || port >= 0xFFFF) { SendI2PError ("Invalid PORT"); return; - } + } boost::system::error_code ec; auto ep = m_Socket.remote_endpoint (ec); if (ec) { SendI2PError ("Socket error"); return; - } + } ep.port (port); m_SocketType = eSAMSocketTypeForward; m_ID = id; m_IsAccepting = true; std::string& silent = params[SAM_PARAM_SILENT]; if (silent == SAM_VALUE_TRUE) m_IsSilent = true; - session->GetLocalDestination ()->AcceptStreams (std::bind (&SAMSocket::HandleI2PForward, + session->GetLocalDestination ()->AcceptStreams (std::bind (&SAMSocket::HandleI2PForward, shared_from_this (), std::placeholders::_1, ep)); - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); - } - + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + } + size_t SAMSocket::ProcessDatagramSend (char * buf, size_t len, const char * data) { LogPrint (eLogDebug, "SAM: Datagram send: ", buf, " ", len); @@ -778,8 +778,8 @@ namespace client // session exists SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), false); return; - } - std::string& style = params[SAM_PARAM_STYLE]; + } + std::string& style = params[SAM_PARAM_STYLE]; SAMSessionType type = eSAMSessionTypeUnknown; if (style == SAM_VALUE_STREAM) type = eSAMSessionTypeStream; // TODO: implement other styles @@ -800,14 +800,14 @@ namespace client { masterSession->subsessions.insert (id); SendSessionCreateReplyOk (); - } + } else SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), false); - } + } else SendI2PError ("Wrong session type"); } - + void SAMSocket::ProcessSessionRemove (char * buf, size_t len) { auto session = m_Owner.FindSession(m_ID); @@ -819,17 +819,17 @@ namespace client ExtractParams (buf, params); std::string& id = params[SAM_PARAM_ID]; if (!masterSession->subsessions.erase (id)) - { + { SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), false); return; } m_Owner.CloseSession (id); SendSessionCreateReplyOk (); - } + } else SendI2PError ("Wrong session type"); - } - + } + void SAMSocket::SendI2PError(const std::string & msg) { LogPrint (eLogError, "SAM: I2P error: ", msg); @@ -1067,7 +1067,7 @@ namespace client LogPrint (eLogWarning, "SAM: I2P acceptor has been reset"); } - void SAMSocket::HandleI2PForward (std::shared_ptr stream, + void SAMSocket::HandleI2PForward (std::shared_ptr stream, boost::asio::ip::tcp::endpoint ep) { if (stream) @@ -1076,7 +1076,7 @@ namespace client auto newSocket = std::make_shared(m_Owner); newSocket->SetSocketType (eSAMSocketTypeStream); auto s = shared_from_this (); - newSocket->GetSocket ().async_connect (ep, + newSocket->GetSocket ().async_connect (ep, [s, newSocket, stream](const boost::system::error_code& ecode) { if (!ecode) @@ -1098,12 +1098,12 @@ namespace client } else stream->AsyncClose (); - }); + }); } else LogPrint (eLogWarning, "SAM: I2P forward acceptor has been reset"); - } - + } + void SAMSocket::HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { LogPrint (eLogDebug, "SAM: Datagram received ", len); @@ -1198,11 +1198,11 @@ namespace client localDestination (dest) { } - + SAMSingleSession::~SAMSingleSession () { i2p::client::context.DeleteLocalDestination (localDestination); - } + } void SAMSingleSession::StopLocalDestination () { @@ -1220,24 +1220,24 @@ namespace client for (const auto& it: subsessions) m_Bridge.CloseSession (it); subsessions.clear (); - } - + } + SAMSubSession::SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, int port): SAMSession (master->m_Bridge, name, type), masterSession (master), inPort (port) { if (Type == eSAMSessionTypeStream) - { + { auto d = masterSession->GetLocalDestination ()->CreateStreamingDestination (inPort); if (d) d->Start (); - } - // TODO: implement datagrams - } - + } + // TODO: implement datagrams + } + std::shared_ptr SAMSubSession::GetLocalDestination () { return masterSession ? masterSession->GetLocalDestination () : nullptr; } - + void SAMSubSession::StopLocalDestination () { auto dest = GetLocalDestination (); @@ -1245,10 +1245,10 @@ namespace client { auto d = dest->RemoveStreamingDestination (inPort); if (d) d->Stop (); - } + } // TODO: implement datagrams - } - + } + SAMBridge::SAMBridge (const std::string& address, int port, bool singleThread): RunnableService ("SAM"), m_IsSingleThread (singleThread), m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)), @@ -1311,8 +1311,8 @@ namespace client { std::unique_lock lock(m_OpenSocketsMutex); m_OpenSockets.push_back(socket); - } - + } + void SAMBridge::RemoveSocket(const std::shared_ptr & socket) { std::unique_lock lock(m_OpenSocketsMutex); @@ -1403,7 +1403,7 @@ namespace client auto ret = m_Sessions.emplace (session->Name, session); return ret.second; } - + void SAMBridge::CloseSession (const std::string& id) { std::shared_ptr session; diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index d92cf009..a969b76c 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -80,7 +80,7 @@ namespace client const char SAM_VALUE_STREAM[] = "STREAM"; const char SAM_VALUE_DATAGRAM[] = "DATAGRAM"; const char SAM_VALUE_RAW[] = "RAW"; - const char SAM_VALUE_MASTER[] = "MASTER"; + const char SAM_VALUE_MASTER[] = "MASTER"; const char SAM_VALUE_TRUE[] = "true"; const char SAM_VALUE_FALSE[] = "false"; @@ -188,14 +188,14 @@ namespace client std::string Name; SAMSessionType Type; std::shared_ptr UDPEndpoint; // TODO: move - + SAMSession (SAMBridge & parent, const std::string & name, SAMSessionType type); virtual ~SAMSession () {}; - + virtual std::shared_ptr GetLocalDestination () = 0; virtual void StopLocalDestination () = 0; virtual void Close () { CloseStreams (); }; - + void CloseStreams (); }; @@ -208,15 +208,15 @@ namespace client std::shared_ptr GetLocalDestination () { return localDestination; }; void StopLocalDestination (); - }; + }; struct SAMMasterSession: public SAMSingleSession { std::set subsessions; SAMMasterSession (SAMBridge & parent, const std::string & name, std::shared_ptr dest): SAMSingleSession (parent, name, eSAMSessionTypeMaster, dest) {}; - void Close (); - }; + void Close (); + }; struct SAMSubSession: public SAMSession { @@ -227,8 +227,8 @@ namespace client // implements SAMSession std::shared_ptr GetLocalDestination (); void StopLocalDestination (); - }; - + }; + class SAMBridge: private i2p::util::RunnableService { public: