I2PControlHandlers.cpp
1 /* 2 * Copyright (c) 2013-2025, The PurpleI2P Project 3 * 4 * This file is part of Purple i2pd project and licensed under BSD3 5 * 6 * See full license text in LICENSE file at top of project tree 7 */ 8 9 #include <iomanip> 10 #define BOOST_BIND_GLOBAL_PLACEHOLDERS 11 #include <boost/lexical_cast.hpp> 12 #include <boost/property_tree/json_parser.hpp> 13 14 #include "Log.h" 15 #include "RouterContext.h" 16 #include "NetDb.hpp" 17 #include "Tunnel.h" 18 #include "Transports.h" 19 #include "version.h" 20 #include "ClientContext.h" 21 #include "I2PControlHandlers.h" 22 23 namespace i2p 24 { 25 namespace client 26 { 27 I2PControlHandlers::I2PControlHandlers () 28 { 29 // RouterInfo 30 m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlHandlers::UptimeHandler; 31 m_RouterInfoHandlers["i2p.router.version"] = &I2PControlHandlers::VersionHandler; 32 m_RouterInfoHandlers["i2p.router.status"] = &I2PControlHandlers::StatusHandler; 33 m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlHandlers::NetDbKnownPeersHandler; 34 m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlHandlers::NetDbActivePeersHandler; 35 m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlHandlers::InboundBandwidth1S; 36 m_RouterInfoHandlers["i2p.router.net.bw.inbound.15s"] = &I2PControlHandlers::InboundBandwidth15S; 37 m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlHandlers::OutboundBandwidth1S; 38 m_RouterInfoHandlers["i2p.router.net.bw.outbound.15s"] = &I2PControlHandlers::OutboundBandwidth15S; 39 m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlHandlers::NetStatusHandler; 40 m_RouterInfoHandlers["i2p.router.net.status.v6"] = &I2PControlHandlers::NetStatusV6Handler; 41 m_RouterInfoHandlers["i2p.router.net.error"] = &I2PControlHandlers::NetErrorHandler; 42 m_RouterInfoHandlers["i2p.router.net.error.v6"] = &I2PControlHandlers::NetErrorV6Handler; 43 m_RouterInfoHandlers["i2p.router.net.testing"] = &I2PControlHandlers::NetTestingHandler; 44 m_RouterInfoHandlers["i2p.router.net.testing.v6"] = &I2PControlHandlers::NetTestingV6Handler; 45 m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlHandlers::TunnelsParticipatingHandler; 46 m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlHandlers::TunnelsSuccessRateHandler; 47 m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlHandlers::NetTotalReceivedBytes; 48 m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlHandlers::NetTotalSentBytes; 49 50 // NetworkSetting 51 m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlHandlers::InboundBandwidthLimit; 52 m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlHandlers::OutboundBandwidthLimit; 53 54 // ClientServicesInfo 55 m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlHandlers::I2PTunnelInfoHandler; 56 m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlHandlers::HTTPProxyInfoHandler; 57 m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlHandlers::SOCKSInfoHandler; 58 m_ClientServicesInfoHandlers["SAM"] = &I2PControlHandlers::SAMInfoHandler; 59 m_ClientServicesInfoHandlers["BOB"] = &I2PControlHandlers::BOBInfoHandler; 60 m_ClientServicesInfoHandlers["I2CP"] = &I2PControlHandlers::I2CPInfoHandler; 61 } 62 63 void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, int value) const 64 { 65 ss << "\"" << name << "\":" << value; 66 } 67 68 void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes) const 69 { 70 ss << "\"" << name << "\":"; 71 if (value.length () > 0) 72 { 73 if (quotes) 74 ss << "\"" << value << "\""; 75 else 76 ss << value; 77 } 78 else 79 ss << "null"; 80 } 81 82 void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, double value) const 83 { 84 ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value; 85 } 86 87 void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const 88 { 89 std::ostringstream buf; 90 boost::property_tree::write_json (buf, value, false); 91 ss << "\"" << name << "\":" << buf.str(); 92 } 93 94 // RouterInfo 95 96 void I2PControlHandlers::RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) 97 { 98 bool first = true; 99 for (auto it = params.begin (); it != params.end (); it++) 100 { 101 LogPrint (eLogDebug, "I2PControl: RouterInfo request: ", it->first); 102 auto it1 = m_RouterInfoHandlers.find (it->first); 103 if (it1 != m_RouterInfoHandlers.end ()) 104 { 105 if (!first) results << ","; 106 else first = false; 107 (this->*(it1->second))(results); 108 } 109 else 110 LogPrint (eLogError, "I2PControl: RouterInfo unknown request ", it->first); 111 } 112 } 113 114 void I2PControlHandlers::UptimeHandler (std::ostringstream& results) 115 { 116 InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL), false); 117 } 118 119 void I2PControlHandlers::VersionHandler (std::ostringstream& results) 120 { 121 InsertParam (results, "i2p.router.version", VERSION); 122 } 123 124 void I2PControlHandlers::StatusHandler (std::ostringstream& results) 125 { 126 auto dest = i2p::client::context.GetSharedLocalDestination (); 127 InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0"); 128 } 129 130 void I2PControlHandlers::NetDbKnownPeersHandler (std::ostringstream& results) 131 { 132 InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ()); 133 } 134 135 void I2PControlHandlers::NetDbActivePeersHandler (std::ostringstream& results) 136 { 137 InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ()); 138 } 139 140 void I2PControlHandlers::NetStatusHandler (std::ostringstream& results) 141 { 142 InsertParam (results, "i2p.router.net.status", (int)i2p::context.GetStatus ()); 143 } 144 145 void I2PControlHandlers::NetStatusV6Handler (std::ostringstream& results) 146 { 147 InsertParam (results, "i2p.router.net.status.v6", (int)i2p::context.GetStatusV6 ()); 148 } 149 150 void I2PControlHandlers::NetErrorHandler (std::ostringstream& results) 151 { 152 InsertParam (results, "i2p.router.net.error", (int)i2p::context.GetError ()); 153 } 154 155 void I2PControlHandlers::NetErrorV6Handler (std::ostringstream& results) 156 { 157 InsertParam (results, "i2p.router.net.error.v6", (int)i2p::context.GetErrorV6 ()); 158 } 159 160 void I2PControlHandlers::NetTestingHandler (std::ostringstream& results) 161 { 162 InsertParam (results, "i2p.router.net.testing", (int)i2p::context.GetTesting ()); 163 } 164 165 void I2PControlHandlers::NetTestingV6Handler (std::ostringstream& results) 166 { 167 InsertParam (results, "i2p.router.net.testing.v6", (int)i2p::context.GetTestingV6 ()); 168 } 169 170 void I2PControlHandlers::TunnelsParticipatingHandler (std::ostringstream& results) 171 { 172 int transit = i2p::tunnel::tunnels.GetTransitTunnels ().size (); 173 InsertParam (results, "i2p.router.net.tunnels.participating", transit); 174 } 175 176 void I2PControlHandlers::TunnelsSuccessRateHandler (std::ostringstream& results) 177 { 178 int rate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate (); 179 InsertParam (results, "i2p.router.net.tunnels.successrate", rate); 180 } 181 182 void I2PControlHandlers::InboundBandwidth1S (std::ostringstream& results) 183 { 184 double bw = i2p::transport::transports.GetInBandwidth (); 185 InsertParam (results, "i2p.router.net.bw.inbound.1s", bw); 186 } 187 188 void I2PControlHandlers::InboundBandwidth15S (std::ostringstream& results) 189 { 190 double bw = i2p::transport::transports.GetInBandwidth15s (); 191 InsertParam (results, "i2p.router.net.bw.inbound.15s", bw); 192 } 193 194 void I2PControlHandlers::OutboundBandwidth1S (std::ostringstream& results) 195 { 196 double bw = i2p::transport::transports.GetOutBandwidth (); 197 InsertParam (results, "i2p.router.net.bw.outbound.1s", bw); 198 } 199 200 void I2PControlHandlers::OutboundBandwidth15S (std::ostringstream& results) 201 { 202 double bw = i2p::transport::transports.GetOutBandwidth15s (); 203 InsertParam (results, "i2p.router.net.bw.outbound.15s", bw); 204 } 205 206 void I2PControlHandlers::NetTotalReceivedBytes (std::ostringstream& results) 207 { 208 InsertParam (results, "i2p.router.net.total.received.bytes", (double)i2p::transport::transports.GetTotalReceivedBytes ()); 209 } 210 211 void I2PControlHandlers::NetTotalSentBytes (std::ostringstream& results) 212 { 213 InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ()); 214 } 215 216 // network setting 217 void I2PControlHandlers::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results) 218 { 219 for (auto it = params.begin (); it != params.end (); it++) 220 { 221 LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first); 222 auto it1 = m_NetworkSettingHandlers.find (it->first); 223 if (it1 != m_NetworkSettingHandlers.end ()) { 224 if (it != params.begin ()) results << ","; 225 (this->*(it1->second))(it->second.data (), results); 226 } else 227 LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first); 228 } 229 } 230 231 void I2PControlHandlers::InboundBandwidthLimit (const std::string& value, std::ostringstream& results) 232 { 233 if (value != "null") 234 i2p::context.SetBandwidth (std::atoi(value.c_str())); 235 int bw = i2p::context.GetBandwidthLimit(); 236 InsertParam (results, "i2p.router.net.bw.in", bw); 237 } 238 239 void I2PControlHandlers::OutboundBandwidthLimit (const std::string& value, std::ostringstream& results) 240 { 241 if (value != "null") 242 i2p::context.SetBandwidth (std::atoi(value.c_str())); 243 int bw = i2p::context.GetBandwidthLimit(); 244 InsertParam (results, "i2p.router.net.bw.out", bw); 245 } 246 247 // ClientServicesInfo 248 249 void I2PControlHandlers::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) 250 { 251 for (auto it = params.begin (); it != params.end (); it++) 252 { 253 LogPrint (eLogDebug, "I2PControl: ClientServicesInfo request: ", it->first); 254 auto it1 = m_ClientServicesInfoHandlers.find (it->first); 255 if (it1 != m_ClientServicesInfoHandlers.end ()) 256 { 257 if (it != params.begin ()) results << ","; 258 (this->*(it1->second))(results); 259 } 260 else 261 LogPrint (eLogError, "I2PControl: ClientServicesInfo unknown request ", it->first); 262 } 263 } 264 265 void I2PControlHandlers::I2PTunnelInfoHandler (std::ostringstream& results) 266 { 267 boost::property_tree::ptree pt; 268 boost::property_tree::ptree client_tunnels, server_tunnels; 269 270 for (auto& it: i2p::client::context.GetClientTunnels ()) 271 { 272 auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); 273 boost::property_tree::ptree ct; 274 ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident)); 275 client_tunnels.add_child(it.second->GetName (), ct); 276 } 277 278 auto& serverTunnels = i2p::client::context.GetServerTunnels (); 279 if (!serverTunnels.empty ()) { 280 for (auto& it: serverTunnels) 281 { 282 auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); 283 boost::property_tree::ptree st; 284 st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident)); 285 st.put("port", it.second->GetLocalPort ()); 286 server_tunnels.add_child(it.second->GetName (), st); 287 } 288 } 289 290 auto& clientForwards = i2p::client::context.GetClientForwards (); 291 if (!clientForwards.empty ()) 292 { 293 for (auto& it: clientForwards) 294 { 295 auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); 296 boost::property_tree::ptree ct; 297 ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident)); 298 client_tunnels.add_child(it.second->GetName (), ct); 299 } 300 } 301 302 auto& serverForwards = i2p::client::context.GetServerForwards (); 303 if (!serverForwards.empty ()) 304 { 305 for (auto& it: serverForwards) 306 { 307 auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); 308 boost::property_tree::ptree st; 309 st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident)); 310 server_tunnels.add_child(it.second->GetName (), st); 311 } 312 } 313 314 pt.add_child("client", client_tunnels); 315 pt.add_child("server", server_tunnels); 316 317 InsertParam (results, "I2PTunnel", pt); 318 } 319 320 void I2PControlHandlers::HTTPProxyInfoHandler (std::ostringstream& results) 321 { 322 boost::property_tree::ptree pt; 323 324 auto httpProxy = i2p::client::context.GetHttpProxy (); 325 if (httpProxy) 326 { 327 auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash(); 328 pt.put("enabled", true); 329 pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident)); 330 } 331 else 332 pt.put("enabled", false); 333 334 InsertParam (results, "HTTPProxy", pt); 335 } 336 337 void I2PControlHandlers::SOCKSInfoHandler (std::ostringstream& results) 338 { 339 boost::property_tree::ptree pt; 340 341 auto socksProxy = i2p::client::context.GetSocksProxy (); 342 if (socksProxy) 343 { 344 auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash(); 345 pt.put("enabled", true); 346 pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident)); 347 } 348 else 349 pt.put("enabled", false); 350 351 InsertParam (results, "SOCKS", pt); 352 } 353 354 void I2PControlHandlers::SAMInfoHandler (std::ostringstream& results) 355 { 356 boost::property_tree::ptree pt; 357 auto sam = i2p::client::context.GetSAMBridge (); 358 if (sam) 359 { 360 pt.put("enabled", true); 361 boost::property_tree::ptree sam_sessions; 362 for (auto& it: sam->GetSessions ()) 363 { 364 boost::property_tree::ptree sam_session, sam_session_sockets; 365 auto& name = it.second->GetLocalDestination ()->GetNickname (); 366 auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); 367 sam_session.put("name", name); 368 sam_session.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident)); 369 370 for (const auto& socket: sam->ListSockets(it.first)) 371 { 372 boost::property_tree::ptree stream; 373 stream.put("type", (int)socket->GetSocketType ()); 374 stream.put("peer", socket->GetSocket ().remote_endpoint()); 375 376 sam_session_sockets.push_back(std::make_pair("", stream)); 377 } 378 sam_session.add_child("sockets", sam_session_sockets); 379 sam_sessions.add_child(it.first, sam_session); 380 } 381 382 pt.add_child("sessions", sam_sessions); 383 } 384 else 385 pt.put("enabled", false); 386 387 InsertParam (results, "SAM", pt); 388 } 389 390 void I2PControlHandlers::BOBInfoHandler (std::ostringstream& results) 391 { 392 boost::property_tree::ptree pt; 393 auto bob = i2p::client::context.GetBOBCommandChannel (); 394 if (bob) 395 { 396 /* TODO more info */ 397 pt.put("enabled", true); 398 } 399 else 400 pt.put("enabled", false); 401 402 InsertParam (results, "BOB", pt); 403 } 404 405 void I2PControlHandlers::I2CPInfoHandler (std::ostringstream& results) 406 { 407 boost::property_tree::ptree pt; 408 auto i2cp = i2p::client::context.GetI2CPServer (); 409 if (i2cp) 410 { 411 /* TODO more info */ 412 pt.put("enabled", true); 413 } 414 else 415 pt.put("enabled", false); 416 417 InsertParam (results, "I2CP", pt); 418 } 419 } 420 }