/ daemon / I2PControlHandlers.cpp
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  }