use Mapping for local destination params

This commit is contained in:
orignal 2025-10-13 17:33:53 -04:00
parent d10a7fe8e5
commit 12895b5744
16 changed files with 261 additions and 312 deletions

View file

@ -931,7 +931,7 @@ namespace client
if (value)
{
*(const_cast<char *>(value)) = 0;
m_Options[operand] = value + 1;
m_Options.Insert (operand, value + 1);
SendReplyOK ({ "option ", operand, " set to ", value + 1 });
*(const_cast<char *>(value)) = '=';
}

View file

@ -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<std::string, std::string> m_Options;
i2p::util::Mapping m_Options;
std::shared_ptr<BOBDestination> m_CurrentDestination;
enum class TunnelType

View file

@ -340,7 +340,7 @@ namespace client
std::shared_ptr<ClientDestination> ClientContext::CreateNewLocalDestination (bool isPublic,
i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType,
const std::map<std::string, std::string> * params)
const i2p::util::Mapping * params)
{
i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType, true);
auto localDestination = std::make_shared<RunnableClientDestination> (keys, isPublic, params);
@ -351,7 +351,7 @@ namespace client
std::shared_ptr<ClientDestination> ClientContext::CreateNewLocalDestination (
boost::asio::io_context& service, bool isPublic,
i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType,
const std::map<std::string, std::string> * params)
const i2p::util::Mapping * params)
{
i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType, true);
auto localDestination = std::make_shared<ClientDestination> (service, keys, isPublic, params);
@ -359,7 +359,8 @@ namespace client
return localDestination;
}
std::shared_ptr<ClientDestination> ClientContext::CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map<std::string, std::string> * params)
std::shared_ptr<ClientDestination> ClientContext::CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
const std::string & name, const i2p::util::Mapping * params)
{
auto localDestination = std::make_shared<MatchedTunnelDestination>(keys, name, params);
AddLocalDestination (localDestination);
@ -389,7 +390,7 @@ namespace client
}
std::shared_ptr<ClientDestination> ClientContext::CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic,
const std::map<std::string, std::string> * 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<ClientDestination> ClientContext::CreateNewLocalDestination (boost::asio::io_context& service,
const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * 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<std::string, std::string> 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, &params); // non-public, EDDSA
@ -450,88 +451,89 @@ namespace client
}
template<typename Section>
void ClientContext::ReadI2CPOptionsGroup (const Section& section, const std::string& group, std::map<std::string, std::string>& 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<typename Section>
void ClientContext::ReadI2CPOptions (const Section& section, bool isServer, std::map<std::string, std::string>& 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<std::string, std::string>& 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<std::string, std::string> 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<ClientDestination> localDestination = nullptr;
if (keys == "shareddest")
@ -778,13 +779,12 @@ namespace client
bool ssl = section.second.get (I2P_SERVER_TUNNEL_SSL, false);
// I2CP
std::map<std::string, std::string> 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<ClientDestination> localDestination = nullptr;
if (keys == "shareddest")
@ -944,9 +944,9 @@ namespace client
i2p::data::PrivateKeys keys;
if(LoadPrivateKeys (keys, httpProxyKeys, sigType))
{
std::map<std::string, std::string> 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, &params);
if (localDestination) localDestination->Acquire ();
}
@ -1001,9 +1001,9 @@ namespace client
i2p::data::PrivateKeys keys;
if (LoadPrivateKeys (keys, socksProxyKeys, sigType))
{
std::map<std::string, std::string> 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, &params);
if (localDestination) localDestination->Acquire ();
}

View file

@ -80,18 +80,18 @@ namespace client
std::shared_ptr<ClientDestination> 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<std::string, std::string> * params = nullptr); // used by SAM only
const i2p::util::Mapping * params = nullptr); // used by SAM only
std::shared_ptr<ClientDestination> 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<std::string, std::string> * 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<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true,
const std::map<std::string, std::string> * params = nullptr);
const i2p::util::Mapping * params = nullptr);
std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_context& service,
const i2p::data::PrivateKeys& keys, bool isPublic = true,
const std::map<std::string, std::string> * params = nullptr); // same as previous but on external io_service
const i2p::util::Mapping * params = nullptr); // same as previous but on external io_service
std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
const std::string & name, const std::map<std::string, std::string> * params = nullptr);
const std::string & name, const i2p::util::Mapping * params = nullptr);
void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination);
std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const;
bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, std::string_view filename,
@ -120,10 +120,10 @@ namespace client
template<typename Section>
std::string GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const; // GetI2CPOption with string default value
template<typename Section>
void ReadI2CPOptionsGroup (const Section& section, const std::string& group, std::map<std::string, std::string>& options) const;
void ReadI2CPOptionsGroup (const Section& section, const std::string& group, i2p::util::Mapping& options) const;
template<typename Section>
void ReadI2CPOptions (const Section& section, bool isServer, std::map<std::string, std::string>& options) const; // for tunnels
void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& 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();

View file

@ -26,7 +26,7 @@ namespace client
I2CPDestination::I2CPDestination (boost::asio::io_context& service, std::shared_ptr<I2CPSession> owner,
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, bool isSameThread,
const std::map<std::string, std::string>& params):
const i2p::util::Mapping& params):
LeaseSetDestination (service, isPublic, &params),
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<I2CPSession> owner,
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
std::shared_ptr<const i2p::data::IdentityEx> 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<std::string, std::string>& 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<std::string, std::string> 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<std::string, std::string> opts;
i2p::util::Mapping opts;
ExtractMapping(buf, optssize, opts);
buf += optssize;
//uint64_t date = bufbe64toh(buf);

View file

@ -87,7 +87,7 @@ namespace client
I2CPDestination (boost::asio::io_context& service, std::shared_ptr<I2CPSession> owner,
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, bool isSameThread,
const std::map<std::string, std::string>& params);
const i2p::util::Mapping& params);
~I2CPDestination () {};
void Stop () override;
@ -142,7 +142,7 @@ namespace client
public:
RunnableI2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity,
bool isPublic, const std::map<std::string, std::string>& 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<std::string, std::string>& 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<const i2p::data::IdentityEx> identity);

View file

@ -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<std::string, std::string> * params)
MatchedTunnelDestination::MatchedTunnelDestination(const i2p::data::PrivateKeys & keys,
const std::string & remoteName, const i2p::util::Mapping * params)
: RunnableClientDestination(keys, false, params),
m_RemoteName(remoteName) {}

View file

@ -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<std::string, std::string> * params = nullptr);
const i2p::util::Mapping * params = nullptr);
void Start();
void Stop();

View file

@ -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<boost::asio::ip::udp::endpoint> 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<SAMSubSession>(masterSession, id, type, fromPort);
if (m_Owner.AddSession (subsession))
{
@ -1027,9 +1004,9 @@ namespace client
SendMessageReply ({m_Buffer, l}, false);
}
const std::map<std::string_view, std::string_view> SAMSocket::ExtractParams (std::string_view buf)
i2p::util::Mapping SAMSocket::ExtractParams (std::string_view buf)
{
std::map<std::string_view, std::string_view> 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<SAMSession> SAMBridge::CreateSession (std::string_view id, SAMSessionType type,
std::string_view destination, const std::map<std::string_view, std::string_view>& params)
std::string_view destination, const i2p::util::Mapping& params)
{
#if __GNUC__ < 10 // TODO: remove when older versions discontinued
std::map<std::string, std::string> p;
for (auto it: params)
p.emplace (std::string (it.first), std::string (it.second));
#else
std::map<std::string, std::string> p(params.begin (), params.end ());
#endif
std::shared_ptr<ClientDestination> 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, &params) :
i2p::client::context.CreateNewLocalDestination (keys, true, &params);
}
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, &params) :
i2p::client::context.CreateNewLocalDestination (true, signatureType, cryptoType, &params);
}
if (localDestination)
{

View file

@ -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<std::string_view, std::string_view> ExtractParams (std::string_view buf);
static i2p::util::Mapping ExtractParams (std::string_view buf);
void Connect (std::shared_ptr<const i2p::data::LeaseSet> remote, std::shared_ptr<SAMSession> session = nullptr);
void HandleConnectLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet);
@ -264,7 +264,7 @@ namespace client
auto& GetService () { return GetIOService (); };
std::shared_ptr<SAMSession> CreateSession (std::string_view id, SAMSessionType type, std::string_view destination, // empty string means transient
const std::map<std::string_view, std::string_view>& params);
const i2p::util::Mapping& params);
bool AddSession (std::shared_ptr<SAMSession> session);
void CloseSession (std::string_view id);
std::shared_ptr<SAMSession> FindSession (std::string_view id) const;