diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 7479f126..558a5b7e 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -247,10 +247,17 @@ namespace client void ClientContext::ReloadConfig () { - std::string config; i2p::config::GetOption("conf", config); - i2p::config::ParseConfig(config); - Stop(); - Start(); + // TODO: handle config changes + /*std::string config; i2p::config::GetOption("conf", config); + i2p::config::ParseConfig(config);*/ + + // handle tunnels + // reset isUpdated for each tunnel + VisitTunnels ([](I2PService * s)->bool { s->isUpdated = false; return true; }); + // reload tunnels + ReadTunnels(); + // delete not updated tunnels (not in config anymore) + VisitTunnels ([](I2PService * s)->bool { return s->isUpdated; }); // delete unused destinations std::unique_lock l(m_DestinationsMutex); @@ -538,13 +545,18 @@ namespace client clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); clientEndpoint = ((I2PClientTunnel*)clientTunnel)->GetAcceptor().local_endpoint(); } - if (m_ClientTunnels.insert (std::make_pair (clientEndpoint, std::unique_ptr(clientTunnel))).second) + auto ins = m_ClientTunnels.insert (std::make_pair (clientEndpoint, std::unique_ptr(clientTunnel))); + if (ins.second) { clientTunnel->Start (); numClientTunnels++; } else - LogPrint (eLogError, "Clients: I2P client tunnel for endpoint ", clientEndpoint, "already exists"); + { + // TODO: update + ins.first->second->isUpdated = true; + LogPrint (eLogInfo, "Clients: I2P client tunnel for endpoint ", clientEndpoint, "already exists"); + } } } else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER @@ -637,15 +649,20 @@ namespace client while (comma != std::string::npos); serverTunnel->SetAccessList (idents); } - if (m_ServerTunnels.insert (std::make_pair ( + auto ins = m_ServerTunnels.insert (std::make_pair ( std::make_pair (localDestination->GetIdentHash (), inPort), - std::unique_ptr(serverTunnel))).second) + std::unique_ptr(serverTunnel))); + if (ins.second) { serverTunnel->Start (); numServerTunnels++; } else - LogPrint (eLogError, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists"); + { + // TODO: update + ins.first->second->isUpdated = true; + LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists"); + } } else @@ -680,5 +697,25 @@ namespace client ScheduleCleanupUDP(); } } + + template + void VisitTunnelsContainer (Container& c, Visitor v) + { + for (auto it = c.begin (); it != c.end ();) + { + if (!v (it->second.get ())) + it = c.erase (it); + else + it++; + } + } + + template + void ClientContext::VisitTunnels (Visitor v) + { + VisitTunnelsContainer (m_ClientTunnels, v); + VisitTunnelsContainer (m_ServerTunnels, v); + // TODO: implement UDP forwards + } } } diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 50ea4755..0eef1f79 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -89,6 +89,9 @@ namespace client void CleanupUDP(const boost::system::error_code & ecode); void ScheduleCleanupUDP(); + template + void VisitTunnels (Visitor v); // Visitor: (I2PService *) -> bool, true means retain + private: std::mutex m_DestinationsMutex; diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 856ea8ab..446500a0 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -11,13 +11,14 @@ namespace client I2PService::I2PService (std::shared_ptr localDestination): m_LocalDestination (localDestination ? localDestination : - i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)) + i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)), isUpdated (true) { m_LocalDestination->Acquire (); } I2PService::I2PService (i2p::data::SigningKeyType kt): - m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)) + m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)), + isUpdated (true) { m_LocalDestination->Acquire (); } diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index 8ea29815..dd0a3c4a 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -53,6 +53,9 @@ namespace client std::shared_ptr m_LocalDestination; std::unordered_set > m_Handlers; std::mutex m_HandlersMutex; + + public: + bool isUpdated; // transient, used during reload only }; /*Simple interface for I2PHandlers, allows detection of finalization amongst other things */