diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 246fb803..f2e2217b 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -155,6 +155,13 @@ namespace client } m_ServerTunnels.clear (); + for (auto& it: m_TorrentsTunnels) + { + LogPrint(eLogInfo, "Clients: Stopping torrents tunnel"); + it.second->Stop (); + } + m_TorrentsTunnels.clear (); + if (m_SamBridge) { LogPrint(eLogInfo, "Clients: Stopping SAM bridge"); @@ -942,6 +949,53 @@ namespace client } } + else if (type == I2P_TUNNELS_SECTION_TYPE_TORRENTS) + { + + // mandatory params + std::string keys = section.second.get (TORRENTS_TUNNEL_KEYS); + std::string torrentsDir = section.second.get (TORRENTS_TUNNEL_TORRENTS_DIR); + // optional params + std::string trackers = section.second.get (TORRENTS_TUNNEL_TRACKERS, ""); + i2p::data::SigningKeyType sigType = section.second.get (TORRENTS_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); + if (sigType > i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519) sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519; + + // I2CP + i2p::util::Mapping options; + ReadI2CPOptions (section, true, options); + + // Set I2CP name if not set + if (!options.Contains (I2CP_PARAM_INBOUND_NICKNAME)) + options.Insert (I2CP_PARAM_INBOUND_NICKNAME, name); + + 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; + if(!LoadPrivateKeys (k, keys, sigType, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)) + continue; + localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); + if (!localDestination) + { + localDestination = CreateNewLocalDestination (k, true, &options); + destinations[keys] = localDestination; + } + else + localDestination->SetPublic (true); + } + auto torrentsTunnel = std::make_shared (localDestination, torrentsDir, trackers); + auto [iit, inserted] = m_TorrentsTunnels.emplace (localDestination->GetIdentHash (), torrentsTunnel); + if (inserted) + torrentsTunnel->Start (); + else + LogPrint (eLogError, "Clients: Failed to create torrents tunnel ", name, ". Duplicate keys ", keys); + } else LogPrint (eLogError, "Clients: Unknown section type = ", type, " of ", name, " in ", tunConf); } diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index ed28fe33..a193939a 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -10,6 +10,7 @@ #define CLIENT_CONTEXT_H__ #include +#include #include #include #include @@ -22,6 +23,7 @@ #include "BOB.h" #include "I2CP.h" #include "AddressBook.h" +#include "Torrents.h" #include "I18N_langs.h" namespace i2p @@ -38,6 +40,7 @@ namespace client const char I2P_TUNNELS_SECTION_TYPE_SOCKS[] = "socks"; const char I2P_TUNNELS_SECTION_TYPE_WEBSOCKS[] = "websocks"; const char I2P_TUNNELS_SECTION_TYPE_HTTPPROXY[] = "httpproxy"; + const char I2P_TUNNELS_SECTION_TYPE_TORRENTS[] = "torrents"; const char I2P_CLIENT_TUNNEL_PORT[] = "port"; const char I2P_CLIENT_TUNNEL_ADDRESS[] = "address"; const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination"; @@ -66,6 +69,10 @@ namespace client const char I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL[] = "enableuniquelocal"; const char I2P_SERVER_TUNNEL_SSL[] = "ssl"; const char UDP_CLIENT_TUNNEL_DATAGRAM_VERSION[] = "datagramversion"; + const char TORRENTS_TUNNEL_KEYS[] = "keys"; + const char TORRENTS_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; + const char TORRENTS_TUNNEL_TORRENTS_DIR[] = "torrentsdir"; + const char TORRENTS_TUNNEL_TRACKERS[] = "trackers"; class ClientContext { @@ -153,6 +160,8 @@ namespace client std::map > m_ClientForwards; // local endpoint -> udp tunnel std::map, std::shared_ptr > m_ServerForwards; // -> udp tunnel + std::unordered_map > m_TorrentsTunnels; // local destination -> torrents tunnel + SAMBridge * m_SamBridge; BOBCommandChannel * m_BOBCommandChannel; I2CPServer * m_I2CPServer;