From 058120d001524036f702f497a668e714f33cf29d Mon Sep 17 00:00:00 2001
From: orignal <i2porignal@yandex.ru>
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<std::shared_ptr<DatagramSessionInfo> > 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) << "&nbsp;KiB<br>\r\n";
 	}
 
-	void ShowPageHead (std::stringstream& s)
+	static void ShowPageHead (std::stringstream& s)
 	{
 		s <<
 			"<!DOCTYPE html>\r\n"
@@ -156,7 +158,7 @@ namespace http {
 			"<div class=right>";
 	}
 
-	void ShowPageTail (std::stringstream& s)
+	static void ShowPageTail (std::stringstream& s)
 	{
 		s <<
 			"</div></div>\r\n"
@@ -164,12 +166,12 @@ namespace http {
 			"</html>\r\n";
 	}
 
-	void ShowError(std::stringstream& s, const std::string& string)
+	static void ShowError(std::stringstream& s, const std::string& string)
 	{
 		s << "<b>ERROR:</b>&nbsp;" << string << "<br>\r\n";
 	}
 
-	void ShowStatus (std::stringstream& s)
+	static void ShowStatus (std::stringstream& s)
 	{
 		s << "<b>Uptime:</b> ";
 		ShowUptime(s, i2p::context.GetUptime ());
@@ -265,18 +267,71 @@ namespace http {
 		s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n";
 	}
 
-	void ShowLocalDestinations (std::stringstream& s)
+	static void ShowLocalDestinations (std::stringstream& s)
 	{
 		s << "<b>Local Destinations:</b><br>\r\n<br>\r\n";
 		for (auto& it: i2p::client::context.GetDestinations ())
 		{
-			auto ident = it.second->GetIdentHash ();; 
+			auto ident = it.second->GetIdentHash (); 
 			s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">"; 
 			s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
 		}
+
+		auto i2cpServer = i2p::client::context.GetI2CPServer ();
+		if (i2cpServer)
+		{
+			s << "<br><b>I2CP Local Destinations:</b><br>\r\n<br>\r\n";
+			for (auto& it: i2cpServer->GetSessions ())
+			{
+				auto ident = it.second->GetDestination ()->GetIdentHash (); 
+				s << "<a href=\"/?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">"; 
+				s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
+			}
+		}
 	}
 
-	void  ShowLocalDestination (std::stringstream& s, const std::string& b32)
+	static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest)
+	{
+		s << "<b>Base64:</b><br>\r\n<textarea readonly=\"readonly\" cols=\"64\" rows=\"11\" wrap=\"on\">";
+		s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
+		s << "<b>LeaseSets:</b> <i>" << dest->GetNumRemoteLeaseSets () << "</i><br>\r\n";
+		if(dest->GetNumRemoteLeaseSets())
+		{
+			s << "<div class='slide'\r\n><label for='slide1'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide1'/>\r\n<p class='content'>\r\n";
+			for(auto& it: dest->GetLeaseSets ())
+				s << it.second->GetIdentHash ().ToBase32 () << "<br>\r\n";
+			s << "</p>\r\n</div>\r\n";
+		}
+		auto pool = dest->GetTunnelPool ();
+		if (pool)
+		{
+			s << "<b>Inbound tunnels:</b><br>\r\n";
+			for (auto & it : pool->GetInboundTunnels ()) {
+				it->Print(s);
+				if(it->LatencyIsKnown())
+					s << " ( " << it->GetMeanLatency() << "ms )";
+				ShowTunnelDetails(s, it->GetState (), it->GetNumReceivedBytes ());
+			}
+			s << "<br>\r\n";
+			s << "<b>Outbound tunnels:</b><br>\r\n";
+			for (auto & it : pool->GetOutboundTunnels ()) {
+				it->Print(s);
+				if(it->LatencyIsKnown())
+					s << " ( " << it->GetMeanLatency() << "ms )";
+				ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ());
+			}
+		}
+		s << "<br>\r\n";
+		s << "<b>Tags</b><br>Incoming: " << dest->GetNumIncomingTags () << "<br>Outgoing:<br>" << std::endl;
+		for (const auto& it: dest->GetSessions ())
+		{
+			s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " ";
+			s << it.second->GetNumOutgoingTags () << "<br>" << std::endl;
+		}
+		s << "<br>" << std::endl;
+	}
+
+	static void  ShowLocalDestination (std::stringstream& s, const std::string& b32)
 	{
 		s << "<b>Local Destination:</b><br>\r\n<br>\r\n";
 		i2p::data::IdentHash ident;
@@ -284,55 +339,8 @@ namespace http {
 		auto dest = i2p::client::context.FindLocalDestination (ident);
 		if (dest)
 		{
-			s << "<b>Base64:</b><br>\r\n<textarea readonly=\"readonly\" cols=\"64\" rows=\"11\" wrap=\"on\">";
-			s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
-			s << "<b>LeaseSets:</b> <i>" << dest->GetNumRemoteLeaseSets () << "</i><br>\r\n";
-			if(dest->GetNumRemoteLeaseSets())
-			{
-				s << "<div class='slide'\r\n><label for='slide1'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide1'/>\r\n<p class='content'>\r\n";
-				for(auto& it: dest->GetLeaseSets ())
-					s << it.second->GetIdentHash ().ToBase32 () << "<br>\r\n";
-				s << "</p>\r\n</div>\r\n";
-			}
-			auto pool = dest->GetTunnelPool ();
-			if (pool)
-			{
-				s << "<b>Inbound tunnels:</b><br>\r\n";
-				for (auto & it : pool->GetInboundTunnels ()) {
-					it->Print(s);
-					if(it->LatencyIsKnown())
-						s << " ( " << it->GetMeanLatency() << "ms )";
-					ShowTunnelDetails(s, it->GetState (), it->GetNumReceivedBytes ());
-				}
-				s << "<br>\r\n";
-				s << "<b>Outbound tunnels:</b><br>\r\n";
-				for (auto & it : pool->GetOutboundTunnels ()) {
-					it->Print(s);
-					if(it->LatencyIsKnown())
-						s << " ( " << it->GetMeanLatency() << "ms )";
-					ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ());
-				}
-			}
-			s << "<br>\r\n";
-			s << "<b>Tags</b><br>Incoming: " << dest->GetNumIncomingTags () << "<br>Outgoing:<br>" << std::endl;
-			for (const auto& it: dest->GetSessions ())
-			{
-				s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " ";
-				s << it.second->GetNumOutgoingTags () << "<br>" << std::endl;
-			}
-			s << "<br>" << std::endl;
-			// s << "<br>\r\n<b>Streams:</b><br>\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 << "<br>\r\n"<< std::endl; 
-			// }
+			ShowLeaseSetDestination (s, dest);	
+			// show streams
 			s << "<br>\r\n<table><caption>Streams</caption><tr>";
 			s << "<th>StreamID</th>";
 			s << "<th>Destination</th>";
@@ -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 << "<b>I2CP Local Destination:</b><br>\r\n<br>\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 << "<div id='leasesets'><b>LeaseSets (click on to show info):</b></div><br>\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 << "<b>Queue size:</b> " << i2p::tunnel::tunnels.GetQueueSize () << "<br>\r\n";
 
@@ -420,7 +444,7 @@ namespace http {
 		s << "<br>\r\n";
 	}
 
-	void ShowCommands (std::stringstream& s)
+	static void ShowCommands (std::stringstream& s)
 	{
 		/* commands */
 		s << "<b>Router Commands</b><br>\r\n";
@@ -442,7 +466,7 @@ namespace http {
 		s << "  <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "\">Force shutdown</a><br>\r\n";
 	}
 
-	void ShowTransitTunnels (std::stringstream& s)
+	static void ShowTransitTunnels (std::stringstream& s)
 	{
 		s << "<b>Transit tunnels:</b><br>\r\n<br>\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 << "<b>Transports:</b><br>\r\n<br>\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 << "<b>SAM Session:</b><br>\r\n<br>\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 << "<b>Client Tunnels:</b><br>\r\n<br>\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<const I2CPDestination> 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 <i2porignal@yandex.ru>
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 <i2porignal@yandex.ru>
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<std::mutex> l(m_OutputLock);
+	void Log::Process(std::shared_ptr<LogMsg> msg) 
+	{
+		if (!msg) return;
 		std::hash<std::thread::id> 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<i2p::log::LogMsg> & msg) {
+	void Log::Run ()
+	{
+		while (m_IsRunning)
+		{
+			std::shared_ptr<LogMsg> 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<i2p::log::LogMsg> & 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 <sstream>
 #include <chrono>
 #include <memory>
+#include <thread>
 #include "Queue.h"
 
 #ifndef _WIN32
@@ -56,9 +57,9 @@ namespace log {
 			std::time_t m_LastTimestamp;
 			char m_LastDateTime[64];
 			i2p::util::Queue<std::shared_ptr<LogMsg> > 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<LogMsg> 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<i2p::log::LogMsg> &);
 
-			/** @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 ()