From 058120d001524036f702f497a668e714f33cf29d Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Nov 2016 13:10:29 -0500 Subject: [PATCH 1/3] show I2CP local destinations --- ClientContext.h | 1 + HTTPServer.cpp | 158 ++++++++++++++++++++++++++++-------------------- I2CP.h | 4 ++ 3 files changed, 97 insertions(+), 66 deletions(-) diff --git a/ClientContext.h b/ClientContext.h index 73001934..db74a19e 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -66,6 +66,7 @@ namespace client AddressBook& GetAddressBook () { return m_AddressBook; }; const SAMBridge * GetSAMBridge () const { return m_SamBridge; }; + const I2CPServer * GetI2CPServer () const { return m_I2CPServer; }; std::vector > GetForwardInfosFor(const i2p::data::IdentHash & destination); diff --git a/HTTPServer.cpp b/HTTPServer.cpp index bf0a3159..b3bcf473 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -71,6 +71,7 @@ namespace http { const char HTTP_PAGE_TRANSPORTS[] = "transports"; const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations"; const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination"; + const char HTTP_PAGE_I2CP_LOCAL_DESTINATION[] = "i2cp_local_destination"; const char HTTP_PAGE_SAM_SESSIONS[] = "sam_sessions"; const char HTTP_PAGE_SAM_SESSION[] = "sam_session"; const char HTTP_PAGE_I2P_TUNNELS[] = "i2p_tunnels"; @@ -86,7 +87,8 @@ namespace http { const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; const char HTTP_PARAM_ADDRESS[] = "address"; - void ShowUptime (std::stringstream& s, int seconds) { + static void ShowUptime (std::stringstream& s, int seconds) + { int num; if ((num = seconds / 86400) > 0) { @@ -104,7 +106,7 @@ namespace http { s << seconds << " seconds"; } - void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, int bytes) + static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, int bytes) { std::string state; switch (eState) { @@ -121,7 +123,7 @@ namespace http { s << " " << (int) (bytes / 1024) << " KiB
\r\n"; } - void ShowPageHead (std::stringstream& s) + static void ShowPageHead (std::stringstream& s) { s << "\r\n" @@ -156,7 +158,7 @@ namespace http { "
"; } - void ShowPageTail (std::stringstream& s) + static void ShowPageTail (std::stringstream& s) { s << "
\r\n" @@ -164,12 +166,12 @@ namespace http { "\r\n"; } - void ShowError(std::stringstream& s, const std::string& string) + static void ShowError(std::stringstream& s, const std::string& string) { s << "ERROR: " << string << "
\r\n"; } - void ShowStatus (std::stringstream& s) + static void ShowStatus (std::stringstream& s) { s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ()); @@ -265,18 +267,71 @@ namespace http { s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n"; } - void ShowLocalDestinations (std::stringstream& s) + static void ShowLocalDestinations (std::stringstream& s) { s << "Local Destinations:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetDestinations ()) { - auto ident = it.second->GetIdentHash ();; + auto ident = it.second->GetIdentHash (); s << ""; s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl; } + + auto i2cpServer = i2p::client::context.GetI2CPServer (); + if (i2cpServer) + { + s << "
I2CP Local Destinations:
\r\n
\r\n"; + for (auto& it: i2cpServer->GetSessions ()) + { + auto ident = it.second->GetDestination ()->GetIdentHash (); + s << ""; + s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl; + } + } } - void ShowLocalDestination (std::stringstream& s, const std::string& b32) + static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr dest) + { + s << "Base64:
\r\n
\r\n
\r\n"; + s << "LeaseSets: " << dest->GetNumRemoteLeaseSets () << "
\r\n"; + if(dest->GetNumRemoteLeaseSets()) + { + s << "
\r\n\r\n

\r\n"; + for(auto& it: dest->GetLeaseSets ()) + s << it.second->GetIdentHash ().ToBase32 () << "
\r\n"; + s << "

\r\n
\r\n"; + } + auto pool = dest->GetTunnelPool (); + if (pool) + { + s << "Inbound tunnels:
\r\n"; + for (auto & it : pool->GetInboundTunnels ()) { + it->Print(s); + if(it->LatencyIsKnown()) + s << " ( " << it->GetMeanLatency() << "ms )"; + ShowTunnelDetails(s, it->GetState (), it->GetNumReceivedBytes ()); + } + s << "
\r\n"; + s << "Outbound tunnels:
\r\n"; + for (auto & it : pool->GetOutboundTunnels ()) { + it->Print(s); + if(it->LatencyIsKnown()) + s << " ( " << it->GetMeanLatency() << "ms )"; + ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ()); + } + } + s << "
\r\n"; + s << "Tags
Incoming: " << dest->GetNumIncomingTags () << "
Outgoing:
" << std::endl; + for (const auto& it: dest->GetSessions ()) + { + s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " "; + s << it.second->GetNumOutgoingTags () << "
" << std::endl; + } + s << "
" << std::endl; + } + + static void ShowLocalDestination (std::stringstream& s, const std::string& b32) { s << "Local Destination:
\r\n
\r\n"; i2p::data::IdentHash ident; @@ -284,55 +339,8 @@ namespace http { auto dest = i2p::client::context.FindLocalDestination (ident); if (dest) { - s << "Base64:
\r\n
\r\n
\r\n"; - s << "LeaseSets: " << dest->GetNumRemoteLeaseSets () << "
\r\n"; - if(dest->GetNumRemoteLeaseSets()) - { - s << "
\r\n\r\n

\r\n"; - for(auto& it: dest->GetLeaseSets ()) - s << it.second->GetIdentHash ().ToBase32 () << "
\r\n"; - s << "

\r\n
\r\n"; - } - auto pool = dest->GetTunnelPool (); - if (pool) - { - s << "Inbound tunnels:
\r\n"; - for (auto & it : pool->GetInboundTunnels ()) { - it->Print(s); - if(it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << "ms )"; - ShowTunnelDetails(s, it->GetState (), it->GetNumReceivedBytes ()); - } - s << "
\r\n"; - s << "Outbound tunnels:
\r\n"; - for (auto & it : pool->GetOutboundTunnels ()) { - it->Print(s); - if(it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << "ms )"; - ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ()); - } - } - s << "
\r\n"; - s << "Tags
Incoming: " << dest->GetNumIncomingTags () << "
Outgoing:
" << std::endl; - for (const auto& it: dest->GetSessions ()) - { - s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " "; - s << it.second->GetNumOutgoingTags () << "
" << std::endl; - } - s << "
" << std::endl; - // s << "
\r\nStreams:
\r\n"; - // for (auto it: dest->GetStreamingDestination ()->GetStreams ()) - // { - // s << it.first << "->" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetRemoteIdentity ()) << " "; - // s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; - // s << " [out:" << it.second->GetSendQueueSize () << "][in:" << it.second->GetReceiveQueueSize () << "]"; - // s << "[buf:" << it.second->GetSendBufferSize () << "]"; - // s << "[RTT:" << it.second->GetRTT () << "]"; - // s << "[Window:" << it.second->GetWindowSize () << "]"; - // s << "[Status:" << (int)it.second->GetStatus () << "]"; - // s << "
\r\n"<< std::endl; - // } + ShowLeaseSetDestination (s, dest); + // show streams s << "
\r\n"; s << ""; s << ""; @@ -365,7 +373,23 @@ namespace http { } } - void ShowLeasesSets(std::stringstream& s) + static void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id) + { + auto i2cpServer = i2p::client::context.GetI2CPServer (); + if (i2cpServer) + { + s << "I2CP Local Destination:
\r\n
\r\n"; + auto it = i2cpServer->GetSessions ().find (std::stoi (id)); + if (it != i2cpServer->GetSessions ().end ()) + ShowLeaseSetDestination (s, it->second->GetDestination ()); + else + ShowError(s, "I2CP session not found"); + } + else + ShowError(s, "I2CP is not enabled"); + } + + static void ShowLeasesSets(std::stringstream& s) { s << "
LeaseSets (click on to show info):

\r\n"; int counter = 1; @@ -398,7 +422,7 @@ namespace http { // end for each lease set } - void ShowTunnels (std::stringstream& s) + static void ShowTunnels (std::stringstream& s) { s << "Queue size: " << i2p::tunnel::tunnels.GetQueueSize () << "
\r\n"; @@ -420,7 +444,7 @@ namespace http { s << "
\r\n"; } - void ShowCommands (std::stringstream& s) + static void ShowCommands (std::stringstream& s) { /* commands */ s << "Router Commands
\r\n"; @@ -442,7 +466,7 @@ namespace http { s << " Force shutdown
\r\n"; } - void ShowTransitTunnels (std::stringstream& s) + static void ShowTransitTunnels (std::stringstream& s) { s << "Transit tunnels:
\r\n
\r\n"; for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) @@ -457,7 +481,7 @@ namespace http { } } - void ShowTransports (std::stringstream& s) + static void ShowTransports (std::stringstream& s) { s << "Transports:
\r\n
\r\n"; auto ntcpServer = i2p::transport::transports.GetNTCPServer (); @@ -506,7 +530,7 @@ namespace http { } } - void ShowSAMSessions (std::stringstream& s) + static void ShowSAMSessions (std::stringstream& s) { auto sam = i2p::client::context.GetSAMBridge (); if (!sam) { @@ -521,7 +545,7 @@ namespace http { } } - void ShowSAMSession (std::stringstream& s, const std::string& id) + static void ShowSAMSession (std::stringstream& s, const std::string& id) { s << "SAM Session:
\r\n
\r\n"; auto sam = i2p::client::context.GetSAMBridge (); @@ -553,7 +577,7 @@ namespace http { } } - void ShowI2PTunnels (std::stringstream& s) + static void ShowI2PTunnels (std::stringstream& s) { s << "Client Tunnels:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetClientTunnels ()) @@ -743,6 +767,8 @@ namespace http { ShowLocalDestinations (s); else if (page == HTTP_PAGE_LOCAL_DESTINATION) ShowLocalDestination (s, params["b32"]); + else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION) + ShowI2CPLocalDestination (s, params["i2cp_id"]); else if (page == HTTP_PAGE_SAM_SESSIONS) ShowSAMSessions (s); else if (page == HTTP_PAGE_SAM_SESSION) diff --git a/I2CP.h b/I2CP.h index 4964c575..4033d9cd 100644 --- a/I2CP.h +++ b/I2CP.h @@ -112,6 +112,7 @@ namespace client void Start (); void Stop (); uint16_t GetSessionID () const { return m_SessionID; }; + std::shared_ptr GetDestination () const { return m_Destination; }; // called from I2CPDestination void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); @@ -196,6 +197,9 @@ namespace client public: const decltype(m_MessagesHandlers)& GetMessagesHandlers () const { return m_MessagesHandlers; }; + + // for HTTP + const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; }; } } From 164d3566e30beb73aae5392b3437870d3e4414c3 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Nov 2016 15:00:30 -0500 Subject: [PATCH 2/3] fixed linker error --- Crypto.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Crypto.h b/Crypto.h index 476d2a26..0bc1e03c 100644 --- a/Crypto.h +++ b/Crypto.h @@ -320,8 +320,6 @@ inline int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) inline void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) { *pub_key = dh->pub_key; *priv_key = dh->priv_key; } -inline int EVP_PKEY_base_id(const EVP_PKEY *pkey) - { return EVP_PKEY_type(pkey->type); } inline RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) { return pkey->pkey.rsa; } #endif From d91691c3448f9c726182d2a8996fe06cdda7c9ba Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Nov 2016 15:46:28 -0500 Subject: [PATCH 3/3] write to log through the separate thread --- Daemon.cpp | 3 +- Log.cpp | 96 +++++++++++++++++++++++++++++++++++------------------- Log.h | 20 +++++------- api.cpp | 3 +- 4 files changed, 75 insertions(+), 47 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index 9c0d15f8..490277fc 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -113,7 +113,7 @@ namespace i2p } else { // use stdout -- default } - i2p::log::Logger().Ready(); + i2p::log::Logger().Start(); LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); LogPrint(eLogDebug, "FS: main config file: ", config); @@ -351,6 +351,7 @@ namespace i2p } #endif i2p::crypto::TerminateCrypto (); + i2p::log::Logger().Stop(); return true; } diff --git a/Log.cpp b/Log.cpp index 268e9667..bace5f55 100644 --- a/Log.cpp +++ b/Log.cpp @@ -58,13 +58,29 @@ namespace log { Log::Log(): m_Destination(eLogStdout), m_MinLevel(eLogInfo), - m_LogStream (nullptr), m_Logfile(""), m_IsReady(false), m_HasColors(true) + m_LogStream (nullptr), m_Logfile(""), m_HasColors(true), + m_IsRunning (false), m_Thread (nullptr) { } Log::~Log () { - switch (m_Destination) { + delete m_Thread; + } + + void Log::Start () + { + if (!m_IsRunning) + { + m_IsRunning = true; + m_Thread = new std::thread (std::bind (&Log::Run, this)); + } + } + + void Log::Stop () + { + switch (m_Destination) + { #ifndef _WIN32 case eLogSyslog : closelog(); @@ -78,7 +94,14 @@ namespace log { /* do nothing */ break; } - Process(); + m_IsRunning = false; + m_Queue.WakeUp (); + if (m_Thread) + { + m_Thread->join (); + delete m_Thread; + m_Thread = nullptr; + } } void Log::SetLogLevel (const std::string& level) { @@ -106,45 +129,52 @@ namespace log { * Unfortunately, with current startup process with late fork() this * will give us nothing but pain. Maybe later. See in NetDb as example. */ - void Log::Process() { - std::unique_lock l(m_OutputLock); + void Log::Process(std::shared_ptr msg) + { + if (!msg) return; std::hash hasher; unsigned short short_tid; - while (1) { - auto msg = m_Queue.GetNextWithTimeout (1); - if (!msg) - break; - short_tid = (short) (hasher(msg->tid) % 1000); - switch (m_Destination) { + short_tid = (short) (hasher(msg->tid) % 1000); + switch (m_Destination) { #ifndef _WIN32 - case eLogSyslog: - syslog(GetSyslogPrio(msg->level), "[%03u] %s", short_tid, msg->text.c_str()); - break; + case eLogSyslog: + syslog(GetSyslogPrio(msg->level), "[%03u] %s", short_tid, msg->text.c_str()); + break; #endif - case eLogFile: - case eLogStream: - if (m_LogStream) - *m_LogStream << TimeAsString(msg->timestamp) - << "@" << short_tid - << "/" << g_LogLevelStr[msg->level] - << " - " << msg->text << std::endl; - break; - case eLogStdout: - default: - std::cout << TimeAsString(msg->timestamp) + case eLogFile: + case eLogStream: + if (m_LogStream) + *m_LogStream << TimeAsString(msg->timestamp) << "@" << short_tid - << "/" << LogMsgColors[msg->level] << g_LogLevelStr[msg->level] << LogMsgColors[eNumLogLevels] + << "/" << g_LogLevelStr[msg->level] << " - " << msg->text << std::endl; - break; - } // switch - } // while + break; + case eLogStdout: + default: + std::cout << TimeAsString(msg->timestamp) + << "@" << short_tid + << "/" << LogMsgColors[msg->level] << g_LogLevelStr[msg->level] << LogMsgColors[eNumLogLevels] + << " - " << msg->text << std::endl; + break; + } // switch } - void Log::Append(std::shared_ptr & msg) { + void Log::Run () + { + while (m_IsRunning) + { + std::shared_ptr msg; + while (msg = m_Queue.Get ()) + Process (msg); + if (m_LogStream) m_LogStream->flush(); + if (m_IsRunning) + m_Queue.Wait (); + } + } + + void Log::Append(std::shared_ptr & msg) + { m_Queue.Put(msg); - if (!m_IsReady) - return; - Process(); } void Log::SendTo (const std::string& path) diff --git a/Log.h b/Log.h index a6fc2222..1d02a845 100644 --- a/Log.h +++ b/Log.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "Queue.h" #ifndef _WIN32 @@ -56,9 +57,9 @@ namespace log { std::time_t m_LastTimestamp; char m_LastDateTime[64]; i2p::util::Queue > m_Queue; - volatile bool m_IsReady; bool m_HasColors; - mutable std::mutex m_OutputLock; + volatile bool m_IsRunning; + std::thread * m_Thread; private: @@ -66,10 +67,8 @@ namespace log { Log (const Log &); const Log& operator=(const Log&); - /** - * @brief process stored messages in queue - */ - void Process (); + void Run (); + void Process (std::shared_ptr msg); /** * @brief Makes formatted string from unix timestamp @@ -87,6 +86,9 @@ namespace log { LogType GetLogType () { return m_Destination; }; LogLevel GetLogLevel () { return m_MinLevel; }; + void Start (); + void Stop (); + /** * @brief Sets minimal allowed level for log messages * @param level String with wanted minimal msg level @@ -120,12 +122,6 @@ namespace log { */ void Append(std::shared_ptr &); - /** @brief Allow log output */ - void Ready() { m_IsReady = true; } - - /** @brief Flushes the output log stream */ - void Flush(); - /** @brief Reopen log file */ void Reopen(); }; diff --git a/api.cpp b/api.cpp index 1828901b..5148ed41 100644 --- a/api.cpp +++ b/api.cpp @@ -47,7 +47,7 @@ namespace api i2p::log::Logger().SendTo (logStream); else i2p::log::Logger().SendTo (i2p::fs::DataDirPath (i2p::fs::GetAppName () + ".log")); - i2p::log::Logger().Ready(); + i2p::log::Logger().Start (); LogPrint(eLogInfo, "API: starting NetDB"); i2p::data::netdb.Start(); LogPrint(eLogInfo, "API: starting Transports"); @@ -65,6 +65,7 @@ namespace api i2p::transport::transports.Stop(); LogPrint(eLogInfo, "API: stopping NetDB"); i2p::data::netdb.Stop(); + i2p::log::Logger().Stop (); } void RunPeerTest ()
Streams
StreamIDDestination