From 058120d001524036f702f497a668e714f33cf29d Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Nov 2016 13:10:29 -0500 Subject: [PATCH 01/10] 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 02/10] 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 03/10] 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 () From a4988fd7cb509e1a1fb03af05f2631959a2800eb Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Nov 2016 19:14:25 -0500 Subject: [PATCH 04/10] insert I2CP session with correct sessionid --- HTTPServer.cpp | 162 +++++++++++++++++++++++++++++-------------------- I2CP.cpp | 47 ++++++++------ I2CP.h | 5 ++ 3 files changed, 130 insertions(+), 84 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index bf0a3159..5a3e5190 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,75 @@ 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 dest = it.second->GetDestination (); + if (dest) + { + auto ident = dest->GetIdentHash (); + s << ""; + s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl; + } + } + } + } + + 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; } - void ShowLocalDestination (std::stringstream& s, const std::string& b32) + static void ShowLocalDestination (std::stringstream& s, const std::string& b32) { s << "Local Destination:
\r\n
\r\n"; i2p::data::IdentHash ident; @@ -284,55 +343,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
Streams
StreamIDDestination
"; s << ""; s << ""; @@ -365,7 +377,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 +426,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 +448,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 +470,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 +485,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 +534,7 @@ namespace http { } } - void ShowSAMSessions (std::stringstream& s) + static void ShowSAMSessions (std::stringstream& s) { auto sam = i2p::client::context.GetSAMBridge (); if (!sam) { @@ -521,7 +549,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 +581,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 +771,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.cpp b/I2CP.cpp index e0139b9f..e9fb4335 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -346,6 +346,7 @@ namespace client void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len) { RAND_bytes ((uint8_t *)&m_SessionID, 2); + m_Owner.InsertSession (shared_from_this ()); auto identity = std::make_shared(); size_t offset = identity->FromBuffer (buf, len); if (!offset) @@ -460,23 +461,23 @@ namespace client { i2p::data::IdentityEx identity; size_t identsize = identity.FromBuffer (buf + offset, len - offset); - if (identsize) - { - offset += identsize; - uint32_t payloadLen = bufbe32toh (buf + offset); - if (payloadLen + offset <= len) - { - offset += 4; - uint32_t nonce = bufbe32toh (buf + offset + payloadLen); - if (m_IsSendAccepted) - SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted - m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce); - } - else - LogPrint(eLogError, "I2CP: cannot send message, too big"); - } - else - LogPrint(eLogError, "I2CP: invalid identity"); + if (identsize) + { + offset += identsize; + uint32_t payloadLen = bufbe32toh (buf + offset); + if (payloadLen + offset <= len) + { + offset += 4; + uint32_t nonce = bufbe32toh (buf + offset + payloadLen); + if (m_IsSendAccepted) + SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted + m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce); + } + else + LogPrint(eLogError, "I2CP: cannot send message, too big"); + } + else + LogPrint(eLogError, "I2CP: invalid identity"); } } else @@ -711,7 +712,6 @@ namespace client { LogPrint (eLogDebug, "I2CP: new connection from ", ep); auto session = std::make_shared(*this, socket); - m_Sessions[session->GetSessionID ()] = session; session->Start (); } else @@ -724,6 +724,17 @@ namespace client Accept (); } + bool I2CPServer::InsertSession (std::shared_ptr session) + { + if (!session) return false; + if (!m_Sessions.insert({session->GetSessionID (), session}).second) + { + LogPrint (eLogError, "I2CP: duplicate session id ", session->GetSessionID ()); + return false; + } + return true; + } + void I2CPServer::RemoveSession (uint16_t sessionID) { m_Sessions.erase (sessionID); diff --git a/I2CP.h b/I2CP.h index 4964c575..b55f43c1 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); @@ -173,6 +174,7 @@ namespace client void Stop (); boost::asio::io_service& GetService () { return m_Service; }; + bool InsertSession (std::shared_ptr session); void RemoveSession (uint16_t sessionID); private: @@ -196,6 +198,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 b4a9d4df8c023447d09b63d4c7e97545338de020 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Nov 2016 22:11:34 -0500 Subject: [PATCH 05/10] fixed crash in daemon mode --- Daemon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Daemon.cpp b/Daemon.cpp index 490277fc..a007995f 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -113,7 +113,6 @@ namespace i2p } else { // use stdout -- default } - i2p::log::Logger().Start(); LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); LogPrint(eLogDebug, "FS: main config file: ", config); @@ -246,6 +245,7 @@ namespace i2p bool Daemon_Singleton::start() { + i2p::log::Logger().Start(); LogPrint(eLogInfo, "Daemon: starting NetDB"); i2p::data::netdb.Start(); From cd8169c0a55bcd7b2e3f210d9972cf7fda416f6b Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Nov 2016 22:44:02 -0500 Subject: [PATCH 06/10] reopen log upon daemon start --- Log.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Log.cpp b/Log.cpp index bace5f55..a38fc808 100644 --- a/Log.cpp +++ b/Log.cpp @@ -72,6 +72,7 @@ namespace log { { if (!m_IsRunning) { + Reopen (); m_IsRunning = true; m_Thread = new std::thread (std::bind (&Log::Run, this)); } From 93b8bd7f02f5d5c0d0a2a5bd651dd0e6d9a5de4b Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 18 Nov 2016 09:27:40 -0500 Subject: [PATCH 07/10] set high bandwidth together with extra badnwidth --- RouterContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RouterContext.cpp b/RouterContext.cpp index 6e0057fe..7847bef7 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -215,8 +215,8 @@ namespace i2p switch (type) { case low : /* not set */; break; + case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; // no break here case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break; - case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; } m_RouterInfo.SetCaps (caps); UpdateRouterInfo (); From 12b9b4990279d5c87cf9b01b4070e0c5b877009d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 18 Nov 2016 10:27:49 -0500 Subject: [PATCH 08/10] fixed infinite loop bug --- UPnP.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UPnP.cpp b/UPnP.cpp index 612b1441..6a46ee77 100644 --- a/UPnP.cpp +++ b/UPnP.cpp @@ -66,10 +66,13 @@ namespace transport try { m_Service.run (); + // Discover failed + break; // terminate the thread } catch (std::exception& ex) { LogPrint (eLogError, "UPnP: runtime exception: ", ex.what ()); + PortMapping (); } } } From 9d292bb6a4eadbec11d4e41955eed3dbd0423bc9 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 18 Nov 2016 11:16:55 -0500 Subject: [PATCH 09/10] fixed potential race condition --- Garlic.cpp | 27 +++++++++++++++++++-------- Garlic.h | 1 + 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Garlic.cpp b/Garlic.cpp index 35c8bc15..f4ca1f06 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -650,37 +650,48 @@ namespace garlic } } // delivery status sessions - for (auto it = m_DeliveryStatusSessions.begin (); it != m_DeliveryStatusSessions.end (); ) - { - if (it->second->GetOwner () != this) - it = m_DeliveryStatusSessions.erase (it); - else - ++it; + { + std::unique_lock l(m_DeliveryStatusSessionsMutex); + for (auto it = m_DeliveryStatusSessions.begin (); it != m_DeliveryStatusSessions.end (); ) + { + if (it->second->GetOwner () != this) + it = m_DeliveryStatusSessions.erase (it); + else + ++it; + } } } void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID) { + std::unique_lock l(m_DeliveryStatusSessionsMutex); m_DeliveryStatusSessions.erase (msgID); } void GarlicDestination::DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID) { + std::unique_lock l(m_DeliveryStatusSessionsMutex); m_DeliveryStatusSessions[msgID] = session; } void GarlicDestination::HandleDeliveryStatusMessage (std::shared_ptr msg) { uint32_t msgID = bufbe32toh (msg->GetPayload ()); + GarlicRoutingSessionPtr session; { + std::unique_lock l(m_DeliveryStatusSessionsMutex); auto it = m_DeliveryStatusSessions.find (msgID); if (it != m_DeliveryStatusSessions.end ()) { - it->second->MessageConfirmed (msgID); + session = it->second; m_DeliveryStatusSessions.erase (it); - LogPrint (eLogDebug, "Garlic: message ", msgID, " acknowledged"); } } + if (session) + { + session->MessageConfirmed (msgID); + LogPrint (eLogDebug, "Garlic: message ", msgID, " acknowledged"); + } } void GarlicDestination::SetLeaseSetUpdated () diff --git a/Garlic.h b/Garlic.h index e0e65111..7cbf3d6f 100644 --- a/Garlic.h +++ b/Garlic.h @@ -195,6 +195,7 @@ namespace garlic // incoming std::map> m_Tags; // DeliveryStatus + std::mutex m_DeliveryStatusSessionsMutex; std::map m_DeliveryStatusSessions; // msgID -> session public: From bdd6037726977f25050142f34ba056ccc77966a9 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 18 Nov 2016 14:50:29 -0500 Subject: [PATCH 10/10] use std::map for unconfirmed tags --- Garlic.cpp | 32 +++++++++++--------------------- Garlic.h | 2 +- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/Garlic.cpp b/Garlic.cpp index f4ca1f06..290b9b79 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -94,26 +94,16 @@ namespace garlic void GarlicRoutingSession::TagsConfirmed (uint32_t msgID) { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - for (auto it = m_UnconfirmedTagsMsgs.begin (); it != m_UnconfirmedTagsMsgs.end ();) + auto it = m_UnconfirmedTagsMsgs.find (msgID); + if (it != m_UnconfirmedTagsMsgs.end ()) { - auto& tags = *it; - if (tags->msgID == msgID) - { - if (ts < tags->tagsCreationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) - { - for (int i = 0; i < tags->numTags; i++) - m_SessionTags.push_back (tags->sessionTags[i]); - } - it = m_UnconfirmedTagsMsgs.erase (it); - } - else if (ts >= tags->tagsCreationTime + OUTGOING_TAGS_CONFIRMATION_TIMEOUT) - { - if (m_Owner) - m_Owner->RemoveDeliveryStatusSession (tags->msgID); - it = m_UnconfirmedTagsMsgs.erase (it); + auto& tags = it->second; + if (ts < tags->tagsCreationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) + { + for (int i = 0; i < tags->numTags; i++) + m_SessionTags.push_back (tags->sessionTags[i]); } - else - ++it; + m_UnconfirmedTagsMsgs.erase (it); } } @@ -144,10 +134,10 @@ namespace garlic // delete expired unconfirmed tags for (auto it = m_UnconfirmedTagsMsgs.begin (); it != m_UnconfirmedTagsMsgs.end ();) { - if (ts >= (*it)->tagsCreationTime + OUTGOING_TAGS_CONFIRMATION_TIMEOUT) + if (ts >= it->second->tagsCreationTime + OUTGOING_TAGS_CONFIRMATION_TIMEOUT) { if (m_Owner) - m_Owner->RemoveDeliveryStatusSession ((*it)->msgID); + m_Owner->RemoveDeliveryStatusSession (it->first); it = m_UnconfirmedTagsMsgs.erase (it); ret = true; } @@ -284,7 +274,7 @@ namespace garlic if (newTags) // new tags created { newTags->msgID = msgID; - m_UnconfirmedTagsMsgs.emplace_back (newTags); + m_UnconfirmedTagsMsgs.emplace (msgID, std::unique_ptr(newTags)); newTags = nullptr; // got acquired } m_Owner->DeliveryStatusSent (shared_from_this (), msgID); diff --git a/Garlic.h b/Garlic.h index 7cbf3d6f..010338cd 100644 --- a/Garlic.h +++ b/Garlic.h @@ -131,7 +131,7 @@ namespace garlic i2p::crypto::AESKey m_SessionKey; std::list m_SessionTags; int m_NumTags; - std::list > m_UnconfirmedTagsMsgs; + std::map > m_UnconfirmedTagsMsgs; // msgID->tags LeaseSetUpdateStatus m_LeaseSetUpdateStatus; uint32_t m_LeaseSetUpdateMsgID;
Streams
StreamIDDestination