diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index ae6e46ef..4d173193 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -26,7 +26,7 @@ namespace i2p namespace client { LeaseSetDestination::LeaseSetDestination (boost::asio::io_context& service, - bool isPublic, const std::map * params): + bool isPublic, const i2p::util::Mapping * params): m_Service (service), m_IsPublic (isPublic), m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service), @@ -45,36 +45,23 @@ namespace client { if (params) { - auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH); - if (it != params->end ()) - inLen = std::stoi(it->second); - it = params->find (I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH); - if (it != params->end ()) - outLen = std::stoi(it->second); - it = params->find (I2CP_PARAM_INBOUND_TUNNELS_QUANTITY); - if (it != params->end ()) - inQty = std::stoi(it->second); - it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY); - if (it != params->end ()) - outQty = std::stoi(it->second); - it = params->find (I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE); - if (it != params->end ()) - inVar = std::stoi(it->second); - it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE); - if (it != params->end ()) - outVar = std::stoi(it->second); - it = params->find (I2CP_PARAM_TAGS_TO_SEND); - if (it != params->end ()) - numTags = std::stoi(it->second); + params->Get (I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen); + params->Get (I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen); + params->Get (I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, inQty); + params->Get (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, outQty); + params->Get (I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE, inVar); + params->Get (I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE, outVar); + params->Get (I2CP_PARAM_TAGS_TO_SEND, numTags); LogPrint (eLogInfo, "Destination: Parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags"); - it = params->find (I2CP_PARAM_RATCHET_INBOUND_TAGS); - if (it != params->end ()) - SetNumRatchetInboundTags (std::stoi(it->second)); - it = params->find (I2CP_PARAM_EXPLICIT_PEERS); - if (it != params->end ()) + int ratchetsInboundTags = 0; + if (params->Get (I2CP_PARAM_RATCHET_INBOUND_TAGS, ratchetsInboundTags)) + SetNumRatchetInboundTags (ratchetsInboundTags); + auto explicitPeersStr = (*params)[I2CP_PARAM_EXPLICIT_PEERS]; + if (!explicitPeersStr.empty ()) { explicitPeers = std::make_shared >(); - std::stringstream ss(it->second); + std::string str (explicitPeersStr); + std::stringstream ss(str); std::string b64; while (std::getline (ss, b64, ',')) { @@ -84,47 +71,37 @@ namespace client LogPrint (eLogInfo, "Destination: Added to explicit peers list: ", b64); } } - it = params->find (I2CP_PARAM_INBOUND_NICKNAME); - if (it != params->end ()) m_Nickname = it->second; - else // try outbound - { - it = params->find (I2CP_PARAM_OUTBOUND_NICKNAME); - if (it != params->end ()) m_Nickname = it->second; - // otherwise we set default nickname in Start when we know local address - } - it = params->find (I2CP_PARAM_DONT_PUBLISH_LEASESET); - if (it != params->end ()) - // override isPublic - m_IsPublic = GetBoolParamValue (it->second); - it = params->find (I2CP_PARAM_LEASESET_TYPE); - if (it != params->end ()) - m_LeaseSetType = std::stoi(it->second); + m_Nickname = (*params)[I2CP_PARAM_INBOUND_NICKNAME]; + if (m_Nickname.empty ()) // try outbound + m_Nickname = (*params)[I2CP_PARAM_OUTBOUND_NICKNAME]; + // otherwise we set default nickname in Start when we know local address + params->Get (I2CP_PARAM_DONT_PUBLISH_LEASESET, m_IsPublic); // override isPublic + params->Get (I2CP_PARAM_LEASESET_TYPE, m_LeaseSetType); if (m_LeaseSetType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) { // authentication for encrypted LeaseSet - it = params->find (I2CP_PARAM_LEASESET_AUTH_TYPE); - if (it != params->end ()) + int authType = 0; + if (params->Get (I2CP_PARAM_LEASESET_AUTH_TYPE, authType)) { - auto authType = std::stoi (it->second); if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) m_AuthType = authType; else LogPrint (eLogError, "Destination: Unknown auth type: ", authType); } } - it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY); - if (it != params->end ()) + auto leaseSetPrivKey = (*params)[I2CP_PARAM_LEASESET_PRIV_KEY]; + if (!leaseSetPrivKey.empty ()) { m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>()); - if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32) + if (m_LeaseSetPrivKey->FromBase64 (leaseSetPrivKey) != 32) { - LogPrint(eLogCritical, "Destination: Invalid value i2cp.leaseSetPrivKey: ", it->second); + LogPrint(eLogCritical, "Destination: Invalid value i2cp.leaseSetPrivKey: ", leaseSetPrivKey); m_LeaseSetPrivKey.reset (nullptr); } } - it = params->find (I2CP_PARAM_STREAMING_PROFILE); - if (it != params->end ()) - isHighBandwidth = std::stoi (it->second) != STREAMING_PROFILE_INTERACTIVE; + int streamingProfile = 0; + if (params->Get (I2CP_PARAM_STREAMING_PROFILE, streamingProfile)) + isHighBandwidth = streamingProfile != STREAMING_PROFILE_INTERACTIVE; } } catch (std::exception & ex) @@ -137,16 +114,17 @@ namespace client m_Pool->SetExplicitPeers (explicitPeers); if(params) { - auto itr = params->find(I2CP_PARAM_MAX_TUNNEL_LATENCY); - if (itr != params->end()) { - auto maxlatency = std::stoi(itr->second); - itr = params->find(I2CP_PARAM_MIN_TUNNEL_LATENCY); - if (itr != params->end()) { - auto minlatency = std::stoi(itr->second); - if ( minlatency > 0 && maxlatency > 0 ) { + int maxLatency = 0; + if (params->Get (I2CP_PARAM_MAX_TUNNEL_LATENCY, maxLatency)) + { + int minLatency = 0; + if (params->Get (I2CP_PARAM_MIN_TUNNEL_LATENCY, minLatency)) + { + if (minLatency > 0 && maxLatency > 0) + { // set tunnel pool latency - LogPrint(eLogInfo, "Destination: Requiring tunnel latency [", minlatency, "ms, ", maxlatency, "ms]"); - m_Pool->RequireLatency(minlatency, maxlatency); + LogPrint(eLogInfo, "Destination: Requiring tunnel latency [", minLatency, "ms, ", maxLatency, "ms]"); + m_Pool->RequireLatency(minLatency, maxLatency); } } } @@ -186,35 +164,14 @@ namespace client SaveTags (); CleanUp (); // GarlicDestination } - - bool LeaseSetDestination::GetBoolParamValue (std::string_view value) - { - bool ret = false; - if (value == "true") - ret = true; - else if (value == "false") - ret = false; - else - { - int v = 0; - auto res = std::from_chars(value.data(), value.data() + value.size(), v); - if (res.ec != std::errc()) - LogPrint (eLogError, "Destination: Unable to parse bool param value ", value, ": ", std::make_error_code (res.ec).message ()); - ret = v; - } - return ret; - } - bool LeaseSetDestination::Reconfigure(std::map params) + bool LeaseSetDestination::Reconfigure(const i2p::util::Mapping& params) { - auto itr = params.find("i2cp.dontPublishLeaseSet"); - if (itr != params.end()) - { - m_IsPublic = itr->second != "true"; - } + params.Get ("i2cp.dontPublishLeaseSet", m_IsPublic); int inLen = 0, outLen = 0, inQuant = 0, outQuant = 0, numTags = 0, minLatency = 0, maxLatency = 0; - std::map intOpts = { + std::map intOpts = + { {I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen}, {I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen}, {I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, inQuant}, @@ -233,13 +190,8 @@ namespace client maxLatency = 0; for (auto & opt : intOpts) - { - itr = params.find(opt.first); - if(itr != params.end()) - { - opt.second = std::stoi(itr->second); - } - } + params.Get (opt.first, opt.second); + pool->RequireLatency(minLatency, maxLatency); return pool->Reconfigure(inLen, outLen, inQuant, outQuant); } @@ -1020,7 +972,7 @@ namespace client } ClientDestination::ClientDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys, - bool isPublic, const std::map * params): + bool isPublic, const i2p::util::Mapping * params): LeaseSetDestination (service, isPublic, params), m_Keys (keys), m_PreferredCryptoType (0), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), m_StreamingOutboundSpeed (DEFAULT_MAX_OUTBOUND_SPEED), @@ -1038,12 +990,12 @@ namespace client std::set encryptionKeyTypes; if (params) { - auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE); - if (it != params->end ()) + auto encryptionTypesStr = (*params)[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE]; + if (!encryptionTypesStr.empty ()) { // comma-separated values std::vector values; - boost::split(values, it->second, boost::is_any_of(",")); + boost::split(values, encryptionTypesStr, boost::is_any_of(",")); for (auto& it1: values) { try @@ -1095,31 +1047,15 @@ namespace client if (params) { // extract streaming params - auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY); - if (it != params->end ()) - m_StreamingAckDelay = std::stoi(it->second); - it = params->find (I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED); - if (it != params->end ()) - m_StreamingOutboundSpeed = std::stoi(it->second); - it = params->find (I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED); - if (it != params->end ()) - m_StreamingInboundSpeed = std::stoi(it->second); - it = params->find (I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS); - if (it != params->end ()) - m_StreamingMaxConcurrentStreams = std::stoi(it->second); - it = params->find (I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE); - if (it != params->end ()) - { - m_StreamingMaxWindowSize = std::stoi(it->second); - if (m_StreamingMaxWindowSize < i2p::stream::MIN_WINDOW_SIZE) + params->Get (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, m_StreamingAckDelay); + params->Get (I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED, m_StreamingOutboundSpeed); + params->Get (I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED, m_StreamingInboundSpeed); + params->Get (I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS, m_StreamingMaxConcurrentStreams); + if (params->Get (I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, m_StreamingMaxWindowSize) && + (m_StreamingMaxWindowSize < i2p::stream::MIN_WINDOW_SIZE)) m_StreamingMaxWindowSize = i2p::stream::MIN_WINDOW_SIZE; - } - it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); - if (it != params->end ()) - m_IsStreamingAnswerPings = GetBoolParamValue (it->second); - it = params->find (I2CP_PARAM_STREAMING_DONT_SIGN); - if (it != params->end ()) - m_IsStreamingDontSign = GetBoolParamValue (it->second); + params->Get (I2CP_PARAM_STREAMING_ANSWER_PINGS, m_IsStreamingAnswerPings); + params->Get (I2CP_PARAM_STREAMING_DONT_SIGN, m_IsStreamingDontSign); if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) { @@ -1603,21 +1539,21 @@ namespace client return nullptr; } - void ClientDestination::ReadAuthKey (const std::string& group, const std::map * params) + void ClientDestination::ReadAuthKey (const std::string& group, const i2p::util::Mapping * params) { - for (auto it: *params) - if (it.first.length () >= group.length () && !it.first.compare (0, group.length (), group)) - { - auto pos = it.second.find (':'); - if (pos != std::string::npos) + for (const auto& it: params->GetOptions ()) + if (it.first.length () >= group.length () && !it.first.compare (0, group.length (), group)) { - i2p::data::AuthPublicKey pubKey; - if (pubKey.FromBase64 (it.second.substr (pos+1))) - m_AuthKeys->push_back (pubKey); - else - LogPrint (eLogCritical, "Destination: Unexpected auth key: ", it.second.substr (pos+1)); + auto pos = it.second.find (':'); + if (pos != std::string::npos) + { + i2p::data::AuthPublicKey pubKey; + if (pubKey.FromBase64 (it.second.substr (pos+1))) + m_AuthKeys->push_back (pubKey); + else + LogPrint (eLogCritical, "Destination: Unexpected auth key: ", it.second.substr (pos+1)); + } } - } } bool ClientDestination::DeleteStream (uint32_t recvStreamID) @@ -1630,9 +1566,9 @@ namespace client return false; } - RunnableClientDestination::RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): - RunnableService ("Destination"), - ClientDestination (GetIOService (), keys, isPublic, params) + RunnableClientDestination::RunnableClientDestination (const i2p::data::PrivateKeys& keys, + bool isPublic, const i2p::util::Mapping * params): + RunnableService ("Destination"), ClientDestination (GetIOService (), keys, isPublic, params) { if (!GetNickname ().empty ()) RunnableService::SetName (GetNickname ()); diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index f7ba269f..8565baaf 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -132,7 +132,7 @@ namespace client public: - LeaseSetDestination (boost::asio::io_context& service, bool isPublic, const std::map * params = nullptr); + LeaseSetDestination (boost::asio::io_context& service, bool isPublic, const i2p::util::Mapping * params = nullptr); ~LeaseSetDestination (); const std::string& GetNickname () const { return m_Nickname; }; auto& GetService () { return m_Service; }; @@ -141,7 +141,7 @@ namespace client virtual void Stop (); /** i2cp reconfigure */ - virtual bool Reconfigure(std::map i2cpOpts); + virtual bool Reconfigure(const i2p::util::Mapping& i2cpOpts); std::shared_ptr GetTunnelPool () { return m_Pool; }; bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; }; @@ -176,7 +176,6 @@ namespace client int GetLeaseSetType () const { return m_LeaseSetType; }; void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; }; int GetAuthType () const { return m_AuthType; }; - static bool GetBoolParamValue (std::string_view value); virtual void CleanupDestination () {}; // additional clean up in derived classes virtual i2p::data::CryptoKeyType GetPreferredCryptoType () const = 0; // I2CP @@ -240,7 +239,7 @@ namespace client public: ClientDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys, - bool isPublic, const std::map * params = nullptr); + bool isPublic, const i2p::util::Mapping * params = nullptr); ~ClientDestination (); void Start () override; @@ -306,7 +305,7 @@ namespace client return std::static_pointer_cast(shared_from_this ()); } void PersistTemporaryKeys (std::shared_ptr keys); - void ReadAuthKey (const std::string& group, const std::map * params); + void ReadAuthKey (const std::string& group, const i2p::util::Mapping * params); template std::shared_ptr CreateStreamSync (const Dest& dest, uint16_t port); @@ -341,7 +340,7 @@ namespace client { public: - RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params = nullptr); + RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const i2p::util::Mapping * params = nullptr); ~RunnableClientDestination (); void Start (); diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index 7dc11157..8e2eb146 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -91,7 +91,7 @@ namespace api } std::shared_ptr CreateLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic, - const std::map * params) + const i2p::util::Mapping * params) { auto localDestination = std::make_shared (keys, isPublic, params); localDestination->Start (); @@ -99,7 +99,7 @@ namespace api } std::shared_ptr CreateLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType, - const std::map * params) + const i2p::util::Mapping * params) { i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType); auto localDestination = std::make_shared (keys, isPublic, params); diff --git a/libi2pd/api.h b/libi2pd/api.h index 9b0256d8..ba2a27a5 100644 --- a/libi2pd/api.h +++ b/libi2pd/api.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -14,6 +14,7 @@ #include "Identity.h" #include "Destination.h" #include "Streaming.h" +#include "util.h" namespace i2p { @@ -29,9 +30,9 @@ namespace api // destinations std::shared_ptr CreateLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, - const std::map * params = nullptr); + const i2p::util::Mapping * params = nullptr); std::shared_ptr CreateLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, - const std::map * params = nullptr); // transient destinations usually not published + const i2p::util::Mapping * params = nullptr); // transient destinations usually not published void DestroyLocalDestination (std::shared_ptr dest); // streams diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 94f3cd43..66c4da5a 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -313,6 +313,16 @@ namespace util return m_Options.emplace (param, value).second; } + bool Mapping::Contains (std::string_view param) const + { +#if __cplusplus >= 202002L // C++20 + return m_Options.contains (param); +#else + auto it = m_Options.find (param); + return it != m_Options.end (); +#endif + } + void Mapping::CleanUp () { if (!m_Options.empty ()) @@ -321,6 +331,29 @@ namespace util m_Options.swap (tmp); } } + + bool Mapping::GetBoolParamValue (std::string_view s, bool& value) + { + bool ret = true; + value = false; + if (s == "true") + value = true; + else if (s == "false") + value = false; + else + { + int v = 0; + auto res = std::from_chars(s.data(), s.data() + s.size(), v); + if (res.ec == std::errc()) + value = v; + else + { + LogPrint (eLogError, "Mapping: Unable to parse bool param value ", s, ": ", std::make_error_code (res.ec).message ()); + ret = false; + } + } + return ret; + } namespace net { diff --git a/libi2pd/util.h b/libi2pd/util.h index 59901f2b..10c50c69 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -233,12 +233,18 @@ namespace util public: Mapping () = default; + Mapping (const Mapping& ) = default; + Mapping (Mapping&& ) = default; + Mapping (std::initializer_list > options): + m_Options (options) {} + size_t FromBuffer (const uint8_t * buf, size_t len); size_t FromBuffer (size_t size, const uint8_t * buf, size_t len); //without 2 bytes size size_t ToBuffer (uint8_t * buf, size_t len) const; std::string_view operator[](std::string_view param) const; bool Insert (std::string_view param, std::string_view value); + bool Contains (std::string_view param) const; void CleanUp (); bool IsEmpty () const { return m_Options.empty (); } @@ -253,16 +259,30 @@ namespace util if (s.empty ()) return false; auto res = std::from_chars(s.data(), s.data() + s.size(), value); return res.ec == std::errc(); + } + bool Get(std::string_view param, bool& value) const + { + auto s = (*this)[param]; + if (s.empty ()) return false; + return GetBoolParamValue (s, value); } template bool Put (std::string_view param, T value) { return Insert (param, std::to_string (value)); } + + private: + + static bool GetBoolParamValue (std::string_view s, bool& value); private: std::map > m_Options; + + public: + + const decltype(m_Options)& GetOptions () const { return m_Options; } }; namespace net diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 08d3c3f0..a5651253 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -931,7 +931,7 @@ namespace client if (value) { *(const_cast(value)) = 0; - m_Options[operand] = value + 1; + m_Options.Insert (operand, value + 1); SendReplyOK ({ "option ", operand, " set to ", value + 1 }); *(const_cast(value)) = '='; } diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index a3f6754f..e7dd87aa 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -272,7 +272,7 @@ namespace client std::string m_Nickname, m_InHost, m_OutHost; uint16_t m_InPort, m_OutPort; i2p::data::PrivateKeys m_Keys; - std::map m_Options; + i2p::util::Mapping m_Options; std::shared_ptr m_CurrentDestination; enum class TunnelType diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index b890fbc6..7c5d7b15 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -340,7 +340,7 @@ namespace client std::shared_ptr ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType, - const std::map * params) + const i2p::util::Mapping * params) { i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType, true); auto localDestination = std::make_shared (keys, isPublic, params); @@ -351,7 +351,7 @@ namespace client std::shared_ptr ClientContext::CreateNewLocalDestination ( boost::asio::io_context& service, bool isPublic, i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType, - const std::map * params) + const i2p::util::Mapping * params) { i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType, true); auto localDestination = std::make_shared (service, keys, isPublic, params); @@ -359,7 +359,8 @@ namespace client return localDestination; } - std::shared_ptr ClientContext::CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map * params) + std::shared_ptr ClientContext::CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, + const std::string & name, const i2p::util::Mapping * params) { auto localDestination = std::make_shared(keys, name, params); AddLocalDestination (localDestination); @@ -389,7 +390,7 @@ namespace client } std::shared_ptr ClientContext::CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic, - const std::map * params) + const i2p::util::Mapping * params) { auto it = m_Destinations.find (keys.GetPublic ()->GetIdentHash ()); if (it != m_Destinations.end ()) @@ -404,7 +405,7 @@ namespace client } std::shared_ptr ClientContext::CreateNewLocalDestination (boost::asio::io_context& service, - const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params) + const i2p::data::PrivateKeys& keys, bool isPublic, const i2p::util::Mapping * params) { auto it = m_Destinations.find (keys.GetPublic ()->GetIdentHash ()); if (it != m_Destinations.end ()) @@ -420,9 +421,9 @@ namespace client void ClientContext::CreateNewSharedLocalDestination () { - std::map params; + i2p::util::Mapping params; ReadI2CPOptionsFromConfig ("shareddest.", params); - params[I2CP_PARAM_OUTBOUND_NICKNAME] = "SharedDest"; + params.Insert (I2CP_PARAM_OUTBOUND_NICKNAME, "SharedDest"); m_SharedLocalDestination = CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, ¶ms); // non-public, EDDSA @@ -450,88 +451,89 @@ namespace client } template - void ClientContext::ReadI2CPOptionsGroup (const Section& section, const std::string& group, std::map& options) const + void ClientContext::ReadI2CPOptionsGroup (const Section& section, const std::string& group, + i2p::util::Mapping& options) const { for (auto it: section.second) { if (it.first.length () >= group.length () && !it.first.compare (0, group.length (), group)) - options[it.first] = it.second.get_value (""); + options.Insert (it.first, it.second.get_value ("")); } } template - void ClientContext::ReadI2CPOptions (const Section& section, bool isServer, std::map& options) const + void ClientContext::ReadI2CPOptions (const Section& section, bool isServer, i2p::util::Mapping& options) const { - options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH); - options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH); - options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, DEFAULT_INBOUND_TUNNELS_QUANTITY); - options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, DEFAULT_OUTBOUND_TUNNELS_QUANTITY); - options[I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE, DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE); - options[I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE, DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE); - options[I2CP_PARAM_TAGS_TO_SEND] = GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND); - options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY); - options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY); - options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY); - options[I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED, DEFAULT_MAX_OUTBOUND_SPEED); - options[I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED, DEFAULT_MAX_INBOUND_SPEED); - options[I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS, DEFAULT_MAX_CONCURRENT_STREAMS); - options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false); - options[I2CP_PARAM_STREAMING_DONT_SIGN] = GetI2CPOption(section, I2CP_PARAM_STREAMING_DONT_SIGN, DEFAULT_DONT_SIGN); - options[I2CP_PARAM_STREAMING_PROFILE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_PROFILE, DEFAULT_STREAMING_PROFILE); - options[I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, i2p::stream::MAX_WINDOW_SIZE); - options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); + options.Insert (I2CP_PARAM_INBOUND_TUNNEL_LENGTH, GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH)); + options.Insert (I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH)); + options.Insert (I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, DEFAULT_INBOUND_TUNNELS_QUANTITY)); + options.Insert (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, DEFAULT_OUTBOUND_TUNNELS_QUANTITY)); + options.Insert (I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE, GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE, DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE)); + options.Insert (I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE, GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE, DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE)); + options.Insert (I2CP_PARAM_TAGS_TO_SEND, GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND)); + options.Insert (I2CP_PARAM_MIN_TUNNEL_LATENCY, GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY)); + options.Insert (I2CP_PARAM_MAX_TUNNEL_LATENCY, GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY)); + options.Insert (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY)); + options.Insert (I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED, GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED, DEFAULT_MAX_OUTBOUND_SPEED)); + options.Insert (I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED, GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED, DEFAULT_MAX_INBOUND_SPEED)); + options.Insert (I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS, GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS, DEFAULT_MAX_CONCURRENT_STREAMS)); + options.Insert (I2CP_PARAM_STREAMING_ANSWER_PINGS, GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false)); + options.Insert (I2CP_PARAM_STREAMING_DONT_SIGN, GetI2CPOption(section, I2CP_PARAM_STREAMING_DONT_SIGN, DEFAULT_DONT_SIGN)); + options.Insert (I2CP_PARAM_STREAMING_PROFILE, GetI2CPOption(section, I2CP_PARAM_STREAMING_PROFILE, DEFAULT_STREAMING_PROFILE)); + options.Insert (I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, i2p::stream::MAX_WINDOW_SIZE)); + options.Insert (I2CP_PARAM_LEASESET_TYPE, GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE)); #if OPENSSL_PQ std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "6,4" : "6,4,0"); #else std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "4" : "4,0"); #endif - if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType; + if (encType.length () > 0) options.Insert (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, encType); std::string privKey = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_PRIV_KEY, ""); - if (privKey.length () > 0) options[I2CP_PARAM_LEASESET_PRIV_KEY] = privKey; + if (privKey.length () > 0) options.Insert (I2CP_PARAM_LEASESET_PRIV_KEY, privKey); auto authType = GetI2CPOption(section, I2CP_PARAM_LEASESET_AUTH_TYPE, 0); if (authType != "0") // auth is set { - options[I2CP_PARAM_LEASESET_AUTH_TYPE] = authType; + options.Insert (I2CP_PARAM_LEASESET_AUTH_TYPE, authType); if (authType == "1") // DH ReadI2CPOptionsGroup (section, I2CP_PARAM_LEASESET_CLIENT_DH, options); else if (authType == "2") // PSK ReadI2CPOptionsGroup (section, I2CP_PARAM_LEASESET_CLIENT_PSK, options); } std::string explicitPeers = GetI2CPStringOption(section, I2CP_PARAM_EXPLICIT_PEERS, ""); - if (explicitPeers.length () > 0) options[I2CP_PARAM_EXPLICIT_PEERS] = explicitPeers; + if (explicitPeers.length () > 0) options.Insert (I2CP_PARAM_EXPLICIT_PEERS, explicitPeers); std::string ratchetInboundTags = GetI2CPStringOption(section, I2CP_PARAM_RATCHET_INBOUND_TAGS, ""); - if (ratchetInboundTags.length () > 0) options[I2CP_PARAM_RATCHET_INBOUND_TAGS] = ratchetInboundTags; + if (ratchetInboundTags.length () > 0) options.Insert (I2CP_PARAM_RATCHET_INBOUND_TAGS, ratchetInboundTags); } - void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const + void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, i2p::util::Mapping& options) const { std::string value; if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNEL_LENGTH, value)) - options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = value; + options.Insert (I2CP_PARAM_INBOUND_TUNNEL_LENGTH, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, value)) - options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = value; + options.Insert (I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE, value)) - options[I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE] = value; + options.Insert (I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, value)) - options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = value; + options.Insert (I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, value)) - options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = value; + options.Insert (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE, value)) - options[I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE] = value; + options.Insert (I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_MIN_TUNNEL_LATENCY, value)) - options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = value; + options.Insert (I2CP_PARAM_MIN_TUNNEL_LATENCY, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_MAX_TUNNEL_LATENCY, value)) - options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; + options.Insert (I2CP_PARAM_MAX_TUNNEL_LATENCY, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_LEASESET_TYPE, value)) - options[I2CP_PARAM_LEASESET_TYPE] = value; + options.Insert (I2CP_PARAM_LEASESET_TYPE, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, value)) - options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = value; + options.Insert (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_LEASESET_PRIV_KEY, value) && !value.empty ()) - options[I2CP_PARAM_LEASESET_PRIV_KEY] = value; + options.Insert (I2CP_PARAM_LEASESET_PRIV_KEY, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_STREAMING_PROFILE, value)) - options[I2CP_PARAM_STREAMING_PROFILE] = value; + options.Insert (I2CP_PARAM_STREAMING_PROFILE, value); if (i2p::config::GetOption(prefix + I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, value)) - options[I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE] = value; + options.Insert (I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, value); } void ClientContext::ReadTunnels () @@ -609,13 +611,12 @@ namespace client #endif i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); // I2CP - std::map options; + i2p::util::Mapping options; ReadI2CPOptions (section, false, options); // Set I2CP name if not set - auto itopt = options.find (I2CP_PARAM_OUTBOUND_NICKNAME); - if (itopt == options.end ()) - options[I2CP_PARAM_OUTBOUND_NICKNAME] = name; + if (!options.Contains (I2CP_PARAM_OUTBOUND_NICKNAME)) + options.Insert (I2CP_PARAM_OUTBOUND_NICKNAME, name); std::shared_ptr localDestination = nullptr; if (keys == "shareddest") @@ -778,13 +779,12 @@ namespace client bool ssl = section.second.get (I2P_SERVER_TUNNEL_SSL, false); // I2CP - std::map options; + i2p::util::Mapping options; ReadI2CPOptions (section, true, options); // Set I2CP name if not set - auto itopt = options.find (I2CP_PARAM_INBOUND_NICKNAME); - if (itopt == options.end ()) - options[I2CP_PARAM_INBOUND_NICKNAME] = name; + if (!options.Contains (I2CP_PARAM_INBOUND_NICKNAME)) + options.Insert (I2CP_PARAM_INBOUND_NICKNAME, name); std::shared_ptr localDestination = nullptr; if (keys == "shareddest") @@ -944,9 +944,9 @@ namespace client i2p::data::PrivateKeys keys; if(LoadPrivateKeys (keys, httpProxyKeys, sigType)) { - std::map params; + i2p::util::Mapping params; ReadI2CPOptionsFromConfig ("httpproxy.", params); - params[I2CP_PARAM_OUTBOUND_NICKNAME] = "HTTPProxy"; + params.Insert (I2CP_PARAM_OUTBOUND_NICKNAME, "HTTPProxy"); localDestination = CreateNewLocalDestination (keys, false, ¶ms); if (localDestination) localDestination->Acquire (); } @@ -1001,9 +1001,9 @@ namespace client i2p::data::PrivateKeys keys; if (LoadPrivateKeys (keys, socksProxyKeys, sigType)) { - std::map params; + i2p::util::Mapping params; ReadI2CPOptionsFromConfig ("socksproxy.", params); - params[I2CP_PARAM_OUTBOUND_NICKNAME] = "SOCKSProxy"; + params.Insert (I2CP_PARAM_OUTBOUND_NICKNAME, "SOCKSProxy"); localDestination = CreateNewLocalDestination (keys, false, ¶ms); if (localDestination) localDestination->Acquire (); } diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 52790836..f0184882 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -80,18 +80,18 @@ namespace client std::shared_ptr CreateNewLocalDestination (bool isPublic = false, // transient i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519, i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, - const std::map * params = nullptr); // used by SAM only + const i2p::util::Mapping * params = nullptr); // used by SAM only std::shared_ptr CreateNewLocalDestination (boost::asio::io_context& service, bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519, i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, - const std::map * params = nullptr); // same as previous but on external io_service + const i2p::util::Mapping * params = nullptr); // same as previous but on external io_service std::shared_ptr CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, - const std::map * params = nullptr); + const i2p::util::Mapping * params = nullptr); std::shared_ptr CreateNewLocalDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys, bool isPublic = true, - const std::map * params = nullptr); // same as previous but on external io_service + const i2p::util::Mapping * params = nullptr); // same as previous but on external io_service std::shared_ptr CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, - const std::string & name, const std::map * params = nullptr); + const std::string & name, const i2p::util::Mapping * params = nullptr); void DeleteLocalDestination (std::shared_ptr destination); std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, std::string_view filename, @@ -120,10 +120,10 @@ namespace client template std::string GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const; // GetI2CPOption with string default value template - void ReadI2CPOptionsGroup (const Section& section, const std::string& group, std::map& options) const; + void ReadI2CPOptionsGroup (const Section& section, const std::string& group, i2p::util::Mapping& options) const; template - void ReadI2CPOptions (const Section& section, bool isServer, std::map& options) const; // for tunnels - void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const; // for HTTP and SOCKS proxy + void ReadI2CPOptions (const Section& section, bool isServer, i2p::util::Mapping& options) const; // for tunnels + void ReadI2CPOptionsFromConfig (const std::string& prefix, i2p::util::Mapping& options) const; // for HTTP and SOCKS proxy void CleanupUDP(const boost::system::error_code & ecode); void ScheduleCleanupUDP(); diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 2c2b6801..5b96b860 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -26,7 +26,7 @@ namespace client I2CPDestination::I2CPDestination (boost::asio::io_context& service, std::shared_ptr owner, std::shared_ptr identity, bool isPublic, bool isSameThread, - const std::map& params): + const i2p::util::Mapping& params): LeaseSetDestination (service, isPublic, ¶ms), m_Owner (owner), m_Identity (identity), m_IsCreatingLeaseSet (false), m_IsSameThread (isSameThread), m_LeaseSetCreationTimer (service), m_ReadinessCheckTimer (service) @@ -376,7 +376,7 @@ namespace client } RunnableI2CPDestination::RunnableI2CPDestination (std::shared_ptr owner, - std::shared_ptr identity, bool isPublic, const std::map& params): + std::shared_ptr identity, bool isPublic, const i2p::util::Mapping& params): RunnableService ("I2CP"), I2CPDestination (GetIOService (), owner, identity, isPublic, false, params) { @@ -637,8 +637,8 @@ namespace client return l + 1; } - void I2CPSession::ExtractMapping (const uint8_t * buf, size_t len, std::map& mapping) const - // TODO: move to Base.cpp + void I2CPSession::ExtractMapping (const uint8_t * buf, size_t len, i2p::util::Mapping& mapping) const + // TODO: call FromBuffer { size_t offset = 0; while (offset < len) @@ -660,7 +660,7 @@ namespace client break; } offset++; - mapping.emplace (param, value); + mapping.Insert (param, value); } } @@ -701,7 +701,7 @@ namespace client SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid return; } - std::map params; + i2p::util::Mapping params; ExtractMapping (buf + offset, optionsSize, params); offset += optionsSize; // options if (params[I2CP_PARAM_MESSAGE_RELIABILITY] == "none") m_IsSendAccepted = false; @@ -767,7 +767,7 @@ namespace client if (optssize <= len - sizeof(uint16_t) - sizeof(uint64_t) - identsz - ident.GetSignatureLen() - sizeof(uint16_t)) { buf += sizeof(uint16_t); - std::map opts; + i2p::util::Mapping opts; ExtractMapping(buf, optssize, opts); buf += optssize; //uint64_t date = bufbe64toh(buf); diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 102fc554..9c842735 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -87,7 +87,7 @@ namespace client I2CPDestination (boost::asio::io_context& service, std::shared_ptr owner, std::shared_ptr identity, bool isPublic, bool isSameThread, - const std::map& params); + const i2p::util::Mapping& params); ~I2CPDestination () {}; void Stop () override; @@ -142,7 +142,7 @@ namespace client public: RunnableI2CPDestination (std::shared_ptr owner, std::shared_ptr identity, - bool isPublic, const std::map& params); + bool isPublic, const i2p::util::Mapping& params); ~RunnableI2CPDestination (); void Start (); @@ -197,7 +197,7 @@ namespace client std::string_view ExtractString (const uint8_t * buf, size_t len) const; size_t PutString (uint8_t * buf, size_t len, std::string_view str); - void ExtractMapping (const uint8_t * buf, size_t len, std::map& mapping) const; + void ExtractMapping (const uint8_t * buf, size_t len, i2p::util::Mapping& mapping) const; void SendSessionStatusMessage (I2CPSessionStatus status); void SendHostReplyMessage (uint32_t requestID, std::shared_ptr identity); diff --git a/libi2pd_client/MatchedDestination.cpp b/libi2pd_client/MatchedDestination.cpp index 40752f5b..934b882d 100644 --- a/libi2pd_client/MatchedDestination.cpp +++ b/libi2pd_client/MatchedDestination.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -15,7 +15,8 @@ namespace i2p { namespace client { - MatchedTunnelDestination::MatchedTunnelDestination(const i2p::data::PrivateKeys & keys, const std::string & remoteName, const std::map * params) + MatchedTunnelDestination::MatchedTunnelDestination(const i2p::data::PrivateKeys & keys, + const std::string & remoteName, const i2p::util::Mapping * params) : RunnableClientDestination(keys, false, params), m_RemoteName(remoteName) {} diff --git a/libi2pd_client/MatchedDestination.h b/libi2pd_client/MatchedDestination.h index 30ad8942..f1b30b3d 100644 --- a/libi2pd_client/MatchedDestination.h +++ b/libi2pd_client/MatchedDestination.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -23,7 +23,7 @@ namespace client public: MatchedTunnelDestination(const i2p::data::PrivateKeys& keys, const std::string & remoteName, - const std::map * params = nullptr); + const i2p::util::Mapping * params = nullptr); void Start(); void Stop(); diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 6cb48660..c9d8e7f5 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -132,12 +132,12 @@ namespace client { separator++; auto params = ExtractParams (separator); - auto it = params.find (SAM_PARAM_MAX); - if (it != params.end ()) - maxVer = ExtractVersion (it->second); - it = params.find(SAM_PARAM_MIN); - if (it != params.end ()) - minVer = ExtractVersion (it->second); + auto maxVerStr = params[SAM_PARAM_MAX]; + if (!maxVerStr.empty ()) + maxVer = ExtractVersion (maxVerStr); + auto minVerStr = params[SAM_PARAM_MIN]; + if (!minVerStr.empty ()) + minVer = ExtractVersion (minVerStr); } // version negotiation if (maxVer && maxVer <= MAX_SAM_VERSION) @@ -399,7 +399,7 @@ namespace client std::shared_ptr forward = nullptr; if ((type == SAMSessionType::eSAMSessionTypeDatagram || type == SAMSessionType::eSAMSessionTypeRaw) && - params.find(SAM_PARAM_HOST) != params.end() && params.find(SAM_PARAM_PORT) != params.end()) + params.Contains(SAM_PARAM_HOST) && params.Contains(SAM_PARAM_PORT)) { // udp forward selected boost::system::error_code e; @@ -684,14 +684,13 @@ namespace client LogPrint(eLogDebug, "SAM: Stream forward: ", buf); auto params = ExtractParams(buf); - const auto itId = params.find(SAM_PARAM_ID); - if (itId == params.end()) + auto id = params[SAM_PARAM_ID]; + if (id.empty ()) { SendSessionI2PError("Missing ID"); return; } - std::string_view id = itId->second; - + auto session = m_Owner.FindSession(id); if (!session) { @@ -704,14 +703,13 @@ namespace client return; } - const auto itPort = params.find(SAM_PARAM_PORT); - if (itPort == params.end()) + auto portStr = params[SAM_PARAM_PORT]; + if (portStr.empty ()) { SendSessionI2PError("PORT is missing"); return; } - std::string_view portStr = itPort->second; if (!std::all_of(portStr.begin(), portStr.end(), ::isdigit)) { SendSessionI2PError("Port must be numeric"); @@ -727,12 +725,12 @@ namespace client } boost::asio::ip::tcp::endpoint ep; - const auto itHost = params.find(SAM_PARAM_HOST); + auto host = params[SAM_PARAM_HOST]; - if (itHost != params.end()) + if (!host.empty ()) { boost::system::error_code ec; - auto addr = boost::asio::ip::make_address(itHost->second, ec); + auto addr = boost::asio::ip::make_address(host, ec); if (ec) { SendSessionI2PError("Invalid IP Address in HOST"); @@ -756,8 +754,7 @@ namespace client m_ID = id; m_IsAccepting = true; - auto itSilent = params.find(SAM_PARAM_SILENT); - if (itSilent != params.end() && itSilent->second == SAM_VALUE_TRUE) + if (params[SAM_PARAM_SILENT] == SAM_VALUE_TRUE) m_IsSilent = true; session->GetLocalDestination()->AcceptStreams( @@ -812,24 +809,13 @@ namespace client // extract signature type i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; - auto it = params.find (SAM_PARAM_SIGNATURE_TYPE); - if (it != params.end ()) + auto signatureTypeStr = params[SAM_PARAM_SIGNATURE_TYPE]; + if (!signatureTypeStr.empty ()) { - if (!m_Owner.ResolveSignatureType (it->second, signatureType)) - LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", it->second); - } - it = params.find (SAM_PARAM_CRYPTO_TYPE); - if (it != params.end ()) - { - try - { - cryptoType = std::stoi(std::string (it->second)); - } - catch (const std::exception& ex) - { - LogPrint (eLogWarning, "SAM: ", SAM_PARAM_CRYPTO_TYPE, "error: ", ex.what ()); - } + if (!m_Owner.ResolveSignatureType (signatureTypeStr, signatureType)) + LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", signatureTypeStr); } + params.Get (SAM_PARAM_CRYPTO_TYPE, cryptoType); auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType, true); #ifdef _MSC_VER size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, @@ -914,17 +900,8 @@ namespace client return; } uint16_t fromPort = 0; - auto it = params.find (SAM_PARAM_FROM_PORT); - if (it != params.end ()) - { - auto p = it->second; - auto res = std::from_chars(p.data(), p.data() + p.size(), fromPort); - if (res.ec != std::errc()) - { - SendSessionI2PError("Invalid from port"); - return; - } - } + params.Get (SAM_PARAM_FROM_PORT, fromPort); + auto subsession = std::make_shared(masterSession, id, type, fromPort); if (m_Owner.AddSession (subsession)) { @@ -1027,9 +1004,9 @@ namespace client SendMessageReply ({m_Buffer, l}, false); } - const std::map SAMSocket::ExtractParams (std::string_view buf) + i2p::util::Mapping SAMSocket::ExtractParams (std::string_view buf) { - std::map params; + i2p::util::Mapping params; size_t pos = 0; while (pos < buf.length ()) { @@ -1047,7 +1024,7 @@ namespace client } auto value = field.find ('='); if (value != std::string_view::npos) - params.emplace (field.substr (0, value), field.substr (value + 1)); + params.Insert (field.substr (0, value), field.substr (value + 1)); } return params; } @@ -1523,53 +1500,35 @@ namespace client } std::shared_ptr SAMBridge::CreateSession (std::string_view id, SAMSessionType type, - std::string_view destination, const std::map& params) + std::string_view destination, const i2p::util::Mapping& params) { -#if __GNUC__ < 10 // TODO: remove when older versions discontinued - std::map p; - for (auto it: params) - p.emplace (std::string (it.first), std::string (it.second)); -#else - std::map p(params.begin (), params.end ()); -#endif std::shared_ptr localDestination = nullptr; if (destination != "") { i2p::data::PrivateKeys keys; if (!keys.FromBase64 (destination)) return nullptr; localDestination = m_IsSingleThread ? - i2p::client::context.CreateNewLocalDestination (GetIOService (), keys, true, &p) : - i2p::client::context.CreateNewLocalDestination (keys, true, &p); + i2p::client::context.CreateNewLocalDestination (GetIOService (), keys, true, ¶ms) : + i2p::client::context.CreateNewLocalDestination (keys, true, ¶ms); } else // transient { // extract signature type i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; - if (!params.empty ()) + if (!params.IsEmpty ()) { - auto it = params.find (SAM_PARAM_SIGNATURE_TYPE); - if (it != params.end ()) + auto signatureTypeStr = params[SAM_PARAM_SIGNATURE_TYPE]; + if (!signatureTypeStr.empty ()) { - if (!ResolveSignatureType (it->second, signatureType)) - LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", it->second); - } - it = params.find (SAM_PARAM_CRYPTO_TYPE); - if (it != params.end ()) - { - try - { - cryptoType = std::stoi(std::string (it->second)); - } - catch (const std::exception& ex) - { - LogPrint (eLogWarning, "SAM: ", SAM_PARAM_CRYPTO_TYPE, "error: ", ex.what ()); - } + if (!ResolveSignatureType (signatureTypeStr, signatureType)) + LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", signatureTypeStr); } + params.Get (SAM_PARAM_CRYPTO_TYPE, cryptoType); } localDestination = m_IsSingleThread ? - i2p::client::context.CreateNewLocalDestination (GetIOService (), true, signatureType, cryptoType, &p) : - i2p::client::context.CreateNewLocalDestination (true, signatureType, cryptoType, &p); + i2p::client::context.CreateNewLocalDestination (GetIOService (), true, signatureType, cryptoType, ¶ms) : + i2p::client::context.CreateNewLocalDestination (true, signatureType, cryptoType, ¶ms); } if (localDestination) { diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 96b89487..52cedbe4 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -163,7 +163,7 @@ namespace client void SendStreamI2PError(const std::string & msg); void SendStreamCantReachPeer(const std::string & msg); size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 - const std::map ExtractParams (std::string_view buf); + static i2p::util::Mapping ExtractParams (std::string_view buf); void Connect (std::shared_ptr remote, std::shared_ptr session = nullptr); void HandleConnectLeaseSetRequestComplete (std::shared_ptr leaseSet); @@ -264,7 +264,7 @@ namespace client auto& GetService () { return GetIOService (); }; std::shared_ptr CreateSession (std::string_view id, SAMSessionType type, std::string_view destination, // empty string means transient - const std::map& params); + const i2p::util::Mapping& params); bool AddSession (std::shared_ptr session); void CloseSession (std::string_view id); std::shared_ptr FindSession (std::string_view id) const;