From 56699a9f8974374ef72ccd3a94d478fd702e707e Mon Sep 17 00:00:00 2001 From: xcps Date: Sat, 26 Mar 2016 02:45:37 -0400 Subject: [PATCH 01/27] check if i2p address to call jump service --- HTTPProxy.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 6e835d21..c252614b 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -39,6 +39,7 @@ namespace proxy void HTTPRequestFailed(/*std::string message*/); void RedirectToJumpService(); void ExtractRequest(); + bool IsI2PAddress(); bool ValidateHTTPRequest(); void HandleJumpServices(); bool CreateHTTPRequest(uint8_t *http_buff, std::size_t len); @@ -176,6 +177,16 @@ namespace proxy m_path.erase(addressHelperPos); } + bool HTTPProxyHandler::IsI2PAddress() + { + auto pos = m_address.rfind (".i2p"); + if (pos != std::string::npos && (pos+4) == m_address.length ()) + { + return true; + } + return false; + } + bool HTTPProxyHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len) { ExtractRequest(); //TODO: parse earlier @@ -183,10 +194,14 @@ namespace proxy HandleJumpServices(); i2p::data::IdentHash identHash; - if (!i2p::client::context.GetAddressBook ().GetIdentHash (m_address, identHash)){ - RedirectToJumpService(); - return false; + if (IsI2PAddress ()) + { + if (!i2p::client::context.GetAddressBook ().GetIdentHash (m_address, identHash)){ + RedirectToJumpService(); + return false; + } } + m_request = m_method; m_request.push_back(' '); From 5261a3e8458a3ee1a811d861690795056b1c4b52 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 26 Mar 2016 09:40:19 -0400 Subject: [PATCH 02/27] add syslog logging option --- Daemon.cpp | 5 ++++- Log.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ Log.h | 27 +++++++++++++++++++++++---- docs/i2pd.conf | 7 +++++-- 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index bd89250e..8b8dfac1 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -159,7 +159,10 @@ namespace i2p if (isDaemon && (logs == "" || logs == "stdout")) logs = "file"; - if (logs == "file") { + if (logs == "syslog") { + // use syslog only no stdout + StartSyslog(); + } else if (logs == "file") { if (logfile == "") logfile = i2p::fs::DataDirPath("i2pd.log"); StartLog (logfile); diff --git a/Log.cpp b/Log.cpp index 6bba1b62..fbaac8c1 100644 --- a/Log.cpp +++ b/Log.cpp @@ -11,8 +11,32 @@ static const char * g_LogLevelStr[eNumLogLevels] = "debug" // eLogDebug }; +/** convert LogLevel enum to syslog priority level */ +static int ToSyslogLevel(LogLevel lvl) +{ + switch (lvl) { + case eLogError: + return LOG_ERR; + case eLogWarning: + return LOG_WARNING; + case eLogInfo: + return LOG_INFO; + case eLogDebug: + return LOG_DEBUG; + default: + // WTF? invalid log level? + return LOG_CRIT; + } +} + + void LogMsg::Process() { + if (log && log->SyslogEnabled()) { + // only log to syslog + syslog(ToSyslogLevel(level), "%s", s.str().c_str()); + return; + } auto stream = log ? log->GetLogStream () : nullptr; auto& output = stream ? *stream : std::cout; if (log) @@ -84,3 +108,20 @@ void Log::SetLogStream (std::shared_ptr logStream) { m_LogStream = logStream; } + +void Log::StartSyslog(const std::string & ident, const int facility) +{ + m_Ident = ident; + openlog(m_Ident.c_str(), LOG_PID, facility); +} + +void Log::StopSyslog() +{ + closelog(); + m_Ident.clear(); +} + +bool Log::SyslogEnabled() +{ + return m_Ident.size() > 0; +} diff --git a/Log.h b/Log.h index 363a23b5..701c450d 100644 --- a/Log.h +++ b/Log.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "Queue.h" enum LogLevel @@ -45,14 +46,19 @@ class Log: public i2p::util::MsgQueue std::shared_ptr GetLogStream () const { return m_LogStream; }; const std::string& GetTimestamp (); LogLevel GetLogLevel () { return m_MinLevel; }; - const std::string& GetFullFilePath () const { return m_FullFilePath; }; - + const std::string& GetFullFilePath () const { return m_FullFilePath; }; + /** start logging to syslog */ + void StartSyslog(const std::string & ident, const int facility = LOG_USER); + /** stop logging to syslog */ + void StopSyslog(); + /** are we logging to syslog right now? */ + bool SyslogEnabled(); private: void Flush (); private: - + std::string m_FullFilePath; // empty if stream std::shared_ptr m_LogStream; enum LogLevel m_MinLevel; @@ -61,7 +67,8 @@ class Log: public i2p::util::MsgQueue std::chrono::monotonic_clock::time_point m_LastTimestampUpdate; #else std::chrono::steady_clock::time_point m_LastTimestampUpdate; -#endif +#endif + std::string m_Ident; }; extern Log * g_Log; @@ -116,6 +123,18 @@ inline bool IsLogToFile () return g_Log ? !g_Log->GetFullFilePath ().empty () : false; } +inline void StartSyslog() +{ + StartLog(""); + g_Log->StartSyslog("i2pd"); +} + +inline void StopSyslog() +{ + if(g_Log) + g_Log->StopSyslog(); +} + template void LogPrint (std::stringstream& s, TValue arg) { diff --git a/docs/i2pd.conf b/docs/i2pd.conf index 32c524ca..92595311 100644 --- a/docs/i2pd.conf +++ b/docs/i2pd.conf @@ -16,7 +16,10 @@ ## Logging configuration section ## By default logs go to stdout with level info ## -## Logs destination (stdout, file) +## Logs destination (stdout, file, syslog) +## stdout - print log entries to stdout +## file - log entries to a file +## syslog - use syslog, see man 3 syslog #log = file ## Path to logfile (default - autodetect) #logfile = /var/log/i2pd.log @@ -40,7 +43,7 @@ ## don't just uncomment this #port = 4321 ##Enable communication through ipv6 -ipv6 +ipv6 = true ## Bandwidth configuration ## L limit bandwidth to 32Kbs/sec, O - to 256Kbs/sec, P - unlimited ## Default is P for floodfill, L for regular node From c4e5a130ee2f045d9361fae33c5f9c6ecef270b8 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 26 Mar 2016 09:49:45 -0400 Subject: [PATCH 03/27] don't break win32 --- Log.cpp | 10 ++++++++-- Log.h | 11 ++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Log.cpp b/Log.cpp index fbaac8c1..bb4f8231 100644 --- a/Log.cpp +++ b/Log.cpp @@ -10,7 +10,7 @@ static const char * g_LogLevelStr[eNumLogLevels] = "info", // eLogInfo "debug" // eLogDebug }; - +#ifndef _WIN32 /** convert LogLevel enum to syslog priority level */ static int ToSyslogLevel(LogLevel lvl) { @@ -28,15 +28,17 @@ static int ToSyslogLevel(LogLevel lvl) return LOG_CRIT; } } - +#endif void LogMsg::Process() { +#ifndef _WIN32 if (log && log->SyslogEnabled()) { // only log to syslog syslog(ToSyslogLevel(level), "%s", s.str().c_str()); return; } +#endif auto stream = log ? log->GetLogStream () : nullptr; auto& output = stream ? *stream : std::cout; if (log) @@ -111,14 +113,18 @@ void Log::SetLogStream (std::shared_ptr logStream) void Log::StartSyslog(const std::string & ident, const int facility) { +#ifndef _WIN32 m_Ident = ident; openlog(m_Ident.c_str(), LOG_PID, facility); +#endif } void Log::StopSyslog() { +#ifndef _WIN32 closelog(); m_Ident.clear(); +#endif } bool Log::SyslogEnabled() diff --git a/Log.h b/Log.h index 701c450d..76866590 100644 --- a/Log.h +++ b/Log.h @@ -8,9 +8,12 @@ #include #include #include -#include #include "Queue.h" +#ifndef _WIN32 +#include +#endif + enum LogLevel { eLogError = 0, @@ -48,7 +51,7 @@ class Log: public i2p::util::MsgQueue LogLevel GetLogLevel () { return m_MinLevel; }; const std::string& GetFullFilePath () const { return m_FullFilePath; }; /** start logging to syslog */ - void StartSyslog(const std::string & ident, const int facility = LOG_USER); + void StartSyslog(const std::string & ident, const int facility); /** stop logging to syslog */ void StopSyslog(); /** are we logging to syslog right now? */ @@ -126,7 +129,9 @@ inline bool IsLogToFile () inline void StartSyslog() { StartLog(""); - g_Log->StartSyslog("i2pd"); +#ifndef _WIN32 + g_Log->StartSyslog("i2pd", LOG_USER); +#endif } inline void StopSyslog() From 215d39fc547e8159692e3a535967ad56091ec2b1 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Mar 2016 10:31:47 -0400 Subject: [PATCH 04/27] address lookup --- AddressBook.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++++-- AddressBook.h | 13 +++++- ClientContext.cpp | 2 + 3 files changed, 126 insertions(+), 6 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index f972d48f..e26ce024 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "Base.h" #include "util.h" #include "Identity.h" @@ -218,10 +219,17 @@ namespace client m_Storage->Init(); LoadHosts (); /* try storage, then hosts.txt, then download */ StartSubscriptions (); + StartLookups (); } + + void AddressBook::StartResolvers () + { + LoadLocal (); + } void AddressBook::Stop () { + StopLookups (); StopSubscriptions (); if (m_SubscriptionsUpdateTimer) { @@ -330,7 +338,6 @@ namespace client LoadHostsFromStream (f); m_IsLoaded = true; } - LoadLocal (); } void AddressBook::LoadHostsFromStream (std::istream& f) @@ -518,6 +525,94 @@ namespace client } } + void AddressBook::StartLookups () + { + auto dest = i2p::client::context.GetSharedLocalDestination (); + if (dest) + { + auto datagram = dest->GetDatagramDestination (); + if (!datagram) + datagram = dest->CreateDatagramDestination (); + datagram->SetReceiver (std::bind (&AddressBook::HandleLookupResponse, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), + ADDRESS_RESPONSE_DATAGRAM_PORT); + } + } + + void AddressBook::StopLookups () + { + auto dest = i2p::client::context.GetSharedLocalDestination (); + if (dest) + { + auto datagram = dest->GetDatagramDestination (); + if (datagram) + datagram->ResetReceiver (ADDRESS_RESPONSE_DATAGRAM_PORT); + } + } + + void AddressBook::LookupAddress (const std::string& address) + { + const i2p::data::IdentHash * ident = nullptr; + auto dot = address.find ('.'); + if (dot != std::string::npos) + ident = FindAddress (address.substr (dot + 1)); + if (!ident) + { + LogPrint (eLogError, "AddressBook: Can't find domain for ", address); + return; + } + + auto dest = i2p::client::context.GetSharedLocalDestination (); + if (dest) + { + auto datagram = dest->GetDatagramDestination (); + if (datagram) + { + uint32_t nonce; + RAND_bytes ((uint8_t *)&nonce, 4); + { + std::unique_lock l(m_LookupsMutex); + m_Lookups[nonce] = address; + } + LogPrint (eLogDebug, "AddressBook: Lookup of ", address, " to ", ident->ToBase32 (), " nonce=", nonce); + size_t len = address.length () + 9; + uint8_t * buf = new uint8_t[len]; + memset (buf, 0, 4); + htobe32buf (buf + 4, nonce); + buf[8] = address.length (); + memcpy (buf + 9, address.c_str (), address.length ()); + datagram->SendDatagramTo (buf, len, *ident, ADDRESS_RESPONSE_DATAGRAM_PORT, ADDRESS_RESOLVER_DATAGRAM_PORT); + delete[] buf; + } + } + } + + void AddressBook::HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + { + if (len < 44) + { + LogPrint (eLogError, "AddressBook: Lookup response is too short ", len); + return; + } + uint32_t nonce = bufbe32toh (buf + 4); + LogPrint (eLogDebug, "AddressBook: Lookup response received from ", from.GetIdentHash ().ToBase32 (), " nonce=", nonce); + std::string address; + { + std::unique_lock l(m_LookupsMutex); + auto it = m_Lookups.find (nonce); + if (it != m_Lookups.end ()) + { + address = it->second; + m_Lookups.erase (it); + } + } + if (address.length () > 0) + { + // TODO: verify from + m_Addresses[address] = buf + 8; + } + } + AddressBookSubscription::AddressBookSubscription (AddressBook& book, const std::string& link): m_Book (book), m_Link (link) { @@ -701,20 +796,31 @@ namespace client } } + AddressResolver::~AddressResolver () + { + if (m_LocalDestination) + { + auto datagram = m_LocalDestination->GetDatagramDestination (); + if (datagram) + datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT); + } + } + void AddressResolver::HandleRequest (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { if (len < 9 || len < buf[8] + 9U) { - LogPrint (eLogError, "Address request is too short ", len); + LogPrint (eLogError, "AddressBook: Address request is too short ", len); return; } // read requested address uint8_t l = buf[8]; char address[255]; memcpy (address, buf + 9, l); - address[l] = 0; + address[l] = 0; + LogPrint (eLogDebug, "AddressBook: Address request ", address); // send response - uint8_t response[40]; + uint8_t response[44]; memset (response, 0, 4); // reserved memcpy (response + 4, buf + 4, 4); // nonce auto it = m_LocalAddresses.find (address); // address lookup @@ -722,7 +828,8 @@ namespace client memcpy (response + 8, it->second, 32); // ident else memset (response + 8, 0, 32); // not found - m_LocalDestination->GetDatagramDestination ()->SendDatagramTo (response, 40, from.GetIdentHash (), toPort, fromPort); + memset (response + 40, 0, 4); // set expiration time to zero + m_LocalDestination->GetDatagramDestination ()->SendDatagramTo (response, 44, from.GetIdentHash (), toPort, fromPort); } void AddressResolver::AddAddress (const std::string& name, const i2p::data::IdentHash& ident) diff --git a/AddressBook.h b/AddressBook.h index 436e7c8b..24a7e151 100644 --- a/AddressBook.h +++ b/AddressBook.h @@ -25,6 +25,9 @@ namespace client const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second + const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; + const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54; + inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); } class AddressBookStorage // interface for storage @@ -54,10 +57,12 @@ namespace client AddressBook (); ~AddressBook (); void Start (); + void StartResolvers (); void Stop (); bool GetIdentHash (const std::string& address, i2p::data::IdentHash& ident); std::shared_ptr GetAddress (const std::string& address); const i2p::data::IdentHash * FindAddress (const std::string& address); + void LookupAddress (const std::string& address); void InsertAddress (const std::string& address, const std::string& base64); // for jump service void InsertAddress (std::shared_ptr address); @@ -80,11 +85,17 @@ namespace client void HandleSubscriptionsUpdateTimer (const boost::system::error_code& ecode); + void StartLookups (); + void StopLookups (); + void HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + private: std::mutex m_AddressBookMutex; std::map m_Addresses; std::map > m_Resolvers; // local destination->resolver + std::mutex m_LookupsMutex; + std::map m_Lookups; // nonce -> address AddressBookStorage * m_Storage; volatile bool m_IsLoaded, m_IsDownloading; std::vector m_Subscriptions; @@ -111,12 +122,12 @@ namespace client // m_Etag must be surrounded by "" }; - const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; class AddressResolver { public: AddressResolver (std::shared_ptr destination); + ~AddressResolver (); void AddAddress (const std::string& name, const i2p::data::IdentHash& ident); private: diff --git a/ClientContext.cpp b/ClientContext.cpp index 8d675286..8c626b25 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -96,6 +96,8 @@ namespace client m_BOBCommandChannel = new BOBCommandChannel (bobAddr, bobPort); m_BOBCommandChannel->Start (); } + + m_AddressBook.StartResolvers (); } void ClientContext::Stop () From 8614c4db736457dc39d0fc7c92cb2f07d05f1b06 Mon Sep 17 00:00:00 2001 From: xcps Date: Sat, 26 Mar 2016 10:32:19 -0400 Subject: [PATCH 05/27] Sent/received traffic amount humanize --- HTTPServer.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 67ddf362..1aa5d273 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -421,10 +421,25 @@ namespace util } s << "
\r\n"; s << "Tunnel creation success rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%
\r\n"; - s << "Received: " << i2p::transport::transports.GetTotalReceivedBytes ()/1000 << "K"; - s << " (" << i2p::transport::transports.GetInBandwidth () <<" Bps)
\r\n"; - s << "Sent: " << i2p::transport::transports.GetTotalSentBytes ()/1000 << "K"; - s << " (" << i2p::transport::transports.GetOutBandwidth () <<" Bps)
\r\n"; + s << "Received: "; + s << std::fixed << std::setprecision(2); + auto numKBytesReceived = (double) i2p::transport::transports.GetTotalReceivedBytes () / 1024; + if (numKBytesReceived < 1024) + s << numKBytesReceived << " KiB"; + else if (numKBytesReceived < 1024 * 1024) + s << numKBytesReceived / 1024 << " MiB"; + else + s << numKBytesReceived / 1024 / 1024 << " GiB"; + s << " (" << (double) i2p::transport::transports.GetInBandwidth () / 1024 << " KiB/s)
\r\n"; + s << "Sent: "; + auto numKBytesSent = (double) i2p::transport::transports.GetTotalSentBytes () / 1024; + if (numKBytesSent < 1024) + s << numKBytesSent << " KiB"; + else if (numKBytesSent < 1024 * 1024) + s << numKBytesSent / 1024 << " MiB"; + else + s << numKBytesSent / 1024 / 1024 << " GiB"; + s << " (" << (double) i2p::transport::transports.GetOutBandwidth () / 1024 << " KiB/s)
\r\n"; s << "Data path: " << i2p::fs::GetDataDir() << "
\r\n
\r\n"; s << "Our external address:" << "
\r\n" ; for (auto address : i2p::context.GetRouterInfo().GetAddresses()) From d39229713fc717018d63511a7a1874f81825e0c4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Mar 2016 15:02:27 -0400 Subject: [PATCH 06/27] lookup address upon request --- AddressBook.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AddressBook.cpp b/AddressBook.cpp index e26ce024..ad2d0c32 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -283,7 +283,10 @@ namespace client return true; } else + { + LookupAddress (address); // TODO: return false; + } } } // if not .b32 we assume full base64 address From 437225b43eaf448fe7338dc33ac78c192e4ad371 Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 24 Mar 2016 10:34:39 +0000 Subject: [PATCH 07/27] * convert makefiles back to unix linefeeds --- Makefile | 182 ++++++++++++++++++++++++------------------------- Makefile.mingw | 87 ++++++++++++----------- 2 files changed, 134 insertions(+), 135 deletions(-) diff --git a/Makefile b/Makefile index d9d62b4c..beb7b467 100644 --- a/Makefile +++ b/Makefile @@ -1,91 +1,91 @@ -UNAME := $(shell uname -s) -SHLIB := libi2pd.so -ARLIB := libi2pd.a -SHLIB_CLIENT := libi2pdclient.so -ARLIB_CLIENT := libi2pdclient.a -I2PD := i2pd -GREP := fgrep -DEPS := obj/make.dep - -include filelist.mk - -USE_AESNI := yes -USE_STATIC := no - -ifeq ($(UNAME),Darwin) - DAEMON_SRC += DaemonLinux.cpp - include Makefile.osx -else ifeq ($(shell echo $(UNAME) | $(GREP) -c FreeBSD),1) - DAEMON_SRC += DaemonLinux.cpp - include Makefile.bsd -else ifeq ($(UNAME),Linux) - DAEMON_SRC += DaemonLinux.cpp - include Makefile.linux -else # win32 mingw - DAEMON_SRC += DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp - include Makefile.mingw -endif - -all: mk_obj_dir $(ARLIB) $(ARLIB_CLIENT) $(I2PD) - -mk_obj_dir: - @mkdir -p obj - @mkdir -p obj/Win32 - -api: mk_obj_dir $(SHLIB) $(ARLIB) -api_client: mk_obj_dir $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) - -## NOTE: The NEEDED_CXXFLAGS are here so that CXXFLAGS can be specified at build time -## **without** overwriting the CXXFLAGS which we need in order to build. -## For example, when adding 'hardening flags' to the build -## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove -## -std=c++11. If you want to remove this variable please do so in a way that allows setting -## custom FLAGS to work at build-time. - -deps: mk_obj_dir - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) -MM *.cpp > $(DEPS) - @sed -i -e '/\.o:/ s/^/obj\//' $(DEPS) - -obj/%.o: %.cpp - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(CPU_FLAGS) -c -o $@ $< - -# '-' is 'ignore if missing' on first run --include $(DEPS) - -DAEMON_OBJS += $(patsubst %.cpp,obj/%.o,$(DAEMON_SRC)) -$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) - $(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS) - -$(SHLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) -ifneq ($(USE_STATIC),yes) - $(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^ -endif - -$(SHLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) - $(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^ - -$(ARLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) - ar -r $@ $^ - -$(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) - ar -r $@ $^ - -clean: - rm -rf obj - $(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) - -strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB) - strip $^ - -LATEST_TAG=$(shell git describe --tags --abbrev=0 master) -dist: - git archive --format=tar.gz -9 --worktree-attributes \ - --prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz - -.PHONY: all -.PHONY: clean -.PHONY: deps -.PHONY: dist -.PHONY: api -.PHONY: api_client -.PHONY: mk_obj_dir +UNAME := $(shell uname -s) +SHLIB := libi2pd.so +ARLIB := libi2pd.a +SHLIB_CLIENT := libi2pdclient.so +ARLIB_CLIENT := libi2pdclient.a +I2PD := i2pd +GREP := fgrep +DEPS := obj/make.dep + +include filelist.mk + +USE_AESNI := yes +USE_STATIC := no + +ifeq ($(UNAME),Darwin) + DAEMON_SRC += DaemonLinux.cpp + include Makefile.osx +else ifeq ($(shell echo $(UNAME) | $(GREP) -c FreeBSD),1) + DAEMON_SRC += DaemonLinux.cpp + include Makefile.bsd +else ifeq ($(UNAME),Linux) + DAEMON_SRC += DaemonLinux.cpp + include Makefile.linux +else # win32 mingw + DAEMON_SRC += DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp + include Makefile.mingw +endif + +all: mk_obj_dir $(ARLIB) $(ARLIB_CLIENT) $(I2PD) + +mk_obj_dir: + @mkdir -p obj + @mkdir -p obj/Win32 + +api: mk_obj_dir $(SHLIB) $(ARLIB) +api_client: mk_obj_dir $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) + +## NOTE: The NEEDED_CXXFLAGS are here so that CXXFLAGS can be specified at build time +## **without** overwriting the CXXFLAGS which we need in order to build. +## For example, when adding 'hardening flags' to the build +## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove +## -std=c++11. If you want to remove this variable please do so in a way that allows setting +## custom FLAGS to work at build-time. + +deps: mk_obj_dir + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) -MM *.cpp > $(DEPS) + @sed -i -e '/\.o:/ s/^/obj\//' $(DEPS) + +obj/%.o: %.cpp + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(CPU_FLAGS) -c -o $@ $< + +# '-' is 'ignore if missing' on first run +-include $(DEPS) + +DAEMON_OBJS += $(patsubst %.cpp,obj/%.o,$(DAEMON_SRC)) +$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) + $(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS) + +$(SHLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) +ifneq ($(USE_STATIC),yes) + $(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^ +endif + +$(SHLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) + $(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^ + +$(ARLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) + ar -r $@ $^ + +$(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) + ar -r $@ $^ + +clean: + rm -rf obj + $(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) + +strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB) + strip $^ + +LATEST_TAG=$(shell git describe --tags --abbrev=0 master) +dist: + git archive --format=tar.gz -9 --worktree-attributes \ + --prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz + +.PHONY: all +.PHONY: clean +.PHONY: deps +.PHONY: dist +.PHONY: api +.PHONY: api_client +.PHONY: mk_obj_dir diff --git a/Makefile.mingw b/Makefile.mingw index 1b500757..5fe3c479 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -1,44 +1,43 @@ -USE_WIN32_APP=yes -CXX = g++ -WINDRES = windres -CXXFLAGS = -Os -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN -NEEDED_CXXFLAGS = -std=c++11 -BOOST_SUFFIX = -mt -INCFLAGS = -I/usr/include/ -I/usr/local/include/ -LDFLAGS = -Wl,-rpath,/usr/local/lib \ - -L/usr/local/lib \ - -L/c/dev/openssl \ - -L/c/dev/boost/lib -LDLIBS = \ - -Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) \ - -Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) \ - -Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) \ - -Wl,-Bstatic -lboost_regex$(BOOST_SUFFIX) \ - -Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) \ - -Wl,-Bstatic -lssl \ - -Wl,-Bstatic -lcrypto \ - -Wl,-Bstatic -lz \ - -Wl,-Bstatic -lwsock32 \ - -Wl,-Bstatic -lws2_32 \ - -Wl,-Bstatic -lgdi32 \ - -Wl,-Bstatic -liphlpapi \ - -static-libgcc -static-libstdc++ \ - -Wl,-Bstatic -lstdc++ \ - -Wl,-Bstatic -lpthread - -ifeq ($(USE_WIN32_APP), yes) - CXXFLAGS += -DWIN32_APP - LDFLAGS += -mwindows -s - DAEMON_RC += Win32/Resource.rc - DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) -endif - -ifeq ($(USE_AESNI),1) - CPU_FLAGS = -maes -DAESNI -else - CPU_FLAGS = -msse -endif - -obj/%.o : %.rc - $(WINDRES) -i $< -o $@ - +USE_WIN32_APP=yes +CXX = g++ +WINDRES = windres +CXXFLAGS = -Os -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN +NEEDED_CXXFLAGS = -std=c++11 +BOOST_SUFFIX = -mt +INCFLAGS = -I/usr/include/ -I/usr/local/include/ +LDFLAGS = -Wl,-rpath,/usr/local/lib \ + -L/usr/local/lib \ + -L/c/dev/openssl \ + -L/c/dev/boost/lib +LDLIBS = \ + -Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lboost_regex$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lssl \ + -Wl,-Bstatic -lcrypto \ + -Wl,-Bstatic -lz \ + -Wl,-Bstatic -lwsock32 \ + -Wl,-Bstatic -lws2_32 \ + -Wl,-Bstatic -lgdi32 \ + -Wl,-Bstatic -liphlpapi \ + -static-libgcc -static-libstdc++ \ + -Wl,-Bstatic -lstdc++ \ + -Wl,-Bstatic -lpthread + +ifeq ($(USE_WIN32_APP), yes) + CXXFLAGS += -DWIN32_APP + LDFLAGS += -mwindows -s + DAEMON_RC += Win32/Resource.rc + DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) +endif + +ifeq ($(USE_AESNI),1) + CPU_FLAGS = -maes -DAESNI +else + CPU_FLAGS = -msse +endif + +obj/%.o : %.rc + $(WINDRES) -i $< -o $@ From 2e848a7c9a5fa711bd319cd7895042547ac819e2 Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 24 Mar 2016 10:39:16 +0000 Subject: [PATCH 08/27] * chg default branch for 'dist' target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index beb7b467..ae49ae4f 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ clean: strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB) strip $^ -LATEST_TAG=$(shell git describe --tags --abbrev=0 master) +LATEST_TAG=$(shell git describe --tags --abbrev=0 openssl) dist: git archive --format=tar.gz -9 --worktree-attributes \ --prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz From 7bbe926232c870b975170e22ef4546221b954ef0 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 25 Mar 2016 04:00:27 +0000 Subject: [PATCH 09/27] * use freopen() instead close()/open() : avoid potential fd leak --- DaemonLinux.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 53d9f61e..59c286be 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -64,12 +64,9 @@ namespace i2p } // close stdin/stdout/stderr descriptors - ::close (0); - ::open ("/dev/null", O_RDWR); - ::close (1); - ::open ("/dev/null", O_RDWR); - ::close (2); - ::open ("/dev/null", O_RDWR); + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); } // Pidfile From 598d0e216a14d2efd2e693d2bcd6c98f9b311379 Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 24 Mar 2016 14:06:44 +0000 Subject: [PATCH 10/27] * fix build requrements --- debian/control | 2 +- docs/build_requirements.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index e76f9c7b..ceca7a5f 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: net Priority: extra Maintainer: hagen Build-Depends: debhelper (>= 9.0.0), dpkg-dev (>= 1.16.1~), - gcc (>= 4.6) | clang (>= 3.3), + gcc (>= 4.7) | clang (>= 3.3), libboost-regex-dev, libboost-system-dev (>= 1.46), libboost-date-time-dev, diff --git a/docs/build_requirements.md b/docs/build_requirements.md index ec4aa180..3e0dfea9 100644 --- a/docs/build_requirements.md +++ b/docs/build_requirements.md @@ -4,7 +4,7 @@ Build requirements Linux/FreeBSD/OSX ----------------- -GCC 4.8 or newer, Boost 1.49 or newer, openssl, zlib. Clang can be used instead of GCC. +GCC 4.7 or newer, Boost 1.49 or newer, openssl, zlib. Clang can be used instead of GCC. Windows ------- From 17fb419fb1c116142dc4eeaab064cb0b22df097d Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 27 Mar 2016 00:00:00 +0000 Subject: [PATCH 11/27] * new logs: code --- Log.cpp | 250 ++++++++++++++++++++++++++++------------------------ Log.h | 267 +++++++++++++++++++++++++++++--------------------------- 2 files changed, 274 insertions(+), 243 deletions(-) diff --git a/Log.cpp b/Log.cpp index bb4f8231..27637c77 100644 --- a/Log.cpp +++ b/Log.cpp @@ -1,133 +1,155 @@ -#include -#include "Log.h" +/* +* Copyright (c) 2013-2016, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ -Log * g_Log = nullptr; +#include "Log.h" -static const char * g_LogLevelStr[eNumLogLevels] = -{ - "error", // eLogError - "warn", // eLogWarning - "info", // eLogInfo - "debug" // eLogDebug -}; -#ifndef _WIN32 -/** convert LogLevel enum to syslog priority level */ -static int ToSyslogLevel(LogLevel lvl) -{ - switch (lvl) { - case eLogError: - return LOG_ERR; - case eLogWarning: - return LOG_WARNING; - case eLogInfo: - return LOG_INFO; - case eLogDebug: - return LOG_DEBUG; - default: - // WTF? invalid log level? - return LOG_CRIT; - } -} -#endif +namespace i2p { +namespace log { + Log logger; + /** + * @enum Maps our loglevel to their symbolic name + */ + static const char * g_LogLevelStr[eNumLogLevels] = + { + "error", // eLogError + "warn", // eLogWarn + "info", // eLogInfo + "debug" // eLogDebug + }; -void LogMsg::Process() -{ #ifndef _WIN32 - if (log && log->SyslogEnabled()) { - // only log to syslog - syslog(ToSyslogLevel(level), "%s", s.str().c_str()); - return; - } + /** + * @brief Maps our log levels to syslog one + * @return syslog priority LOG_*, as defined in syslog.h + */ + static inline int GetSyslogPrio (enum LogLevel l) { + int priority = LOG_DEBUG; + switch (l) { + case eLogError : priority = LOG_ERR; break; + case eLogWarning : priority = LOG_WARNING; break; + case eLogInfo : priority = LOG_INFO; break; + case eLogDebug : priority = LOG_DEBUG; break; + default : priority = LOG_DEBUG; break; + } + return priority; + } #endif - auto stream = log ? log->GetLogStream () : nullptr; - auto& output = stream ? *stream : std::cout; - if (log) - output << log->GetTimestamp (); - else - output << boost::posix_time::second_clock::local_time().time_of_day (); - output << "/" << g_LogLevelStr[level] << " - "; - output << s.str(); -} -const std::string& Log::GetTimestamp () -{ -#if (__GNUC__ == 4) && (__GNUC_MINOR__ <= 6) && !defined(__clang__) - auto ts = std::chrono::monotonic_clock::now (); -#else - auto ts = std::chrono::steady_clock::now (); -#endif - if (ts > m_LastTimestampUpdate + std::chrono::milliseconds (500)) // 0.5 second + Log::Log(): + m_Destination(eLogStdout), m_MinLevel(eLogInfo), + m_LogStream (nullptr), m_Logfile(""), m_IsReady(false) { - m_LastTimestampUpdate = ts; - m_Timestamp = boost::posix_time::to_simple_string (boost::posix_time::second_clock::local_time().time_of_day ()); - } - return m_Timestamp; -} - -void Log::Flush () -{ - if (m_LogStream) - m_LogStream->flush(); -} + } -void Log::SetLogFile (const std::string& fullFilePath, bool truncate) -{ - m_FullFilePath = fullFilePath; - auto mode = std::ofstream::out | std::ofstream::binary; - mode |= truncate ? std::ofstream::trunc : std::ofstream::app; - auto logFile = std::make_shared (fullFilePath, mode); - if (logFile->is_open ()) + Log::~Log () { - SetLogStream (logFile); - LogPrint(eLogInfo, "Log: will send messages to ", fullFilePath); - } -} + switch (m_Destination) { +#ifndef _WIN32 + case eLogSyslog : + closelog(); + break; +#endif + case eLogFile: + case eLogStream: + m_LogStream->flush(); + break; + default: + /* do nothing */ + break; + } + Process(); + } -void Log::ReopenLogFile () -{ - if (m_FullFilePath.length () > 0) - { - SetLogFile (m_FullFilePath, false); // don't truncate - LogPrint(eLogInfo, "Log: file ", m_FullFilePath, " reopen"); + void Log::SetLogLevel (const std::string& level) { + if (level == "error") { m_MinLevel = eLogError; } + else if (level == "warn") { m_MinLevel = eLogWarning; } + else if (level == "info") { m_MinLevel = eLogInfo; } + else if (level == "debug") { m_MinLevel = eLogDebug; } + else { + LogPrint(eLogError, "Log: unknown loglevel: ", level); + return; + } + LogPrint(eLogInfo, "Log: min messages level set to ", level); + } + + const char * Log::TimeAsString(std::time_t t) { + if (t != m_LastTimestamp) { + strftime(m_LastDateTime, sizeof(m_LastDateTime), "%H:%M:%S", localtime(&t)); + m_LastTimestamp = t; + } + return m_LastDateTime; } -} + void Log::Process() { + std::unique_lock l(m_OutputLock); + while (1) { + auto msg = m_Queue.GetNextWithTimeout (1); + if (!msg) + break; + switch (m_Destination) { +#ifndef _WIN32 + case eLogSyslog: + syslog(GetSyslogPrio(msg->level), "%s", msg->text.c_str()); + break; +#endif + case eLogFile: + case eLogStream: + *m_LogStream << TimeAsString(msg->timestamp) << "/" << g_LogLevelStr[msg->level] << " - " << msg->text << std::endl; + break; + default: + std::cout << TimeAsString(msg->timestamp) << "/" << g_LogLevelStr[msg->level] << " - " << msg->text << std::endl; + break; + } // switch + } // while + } -void Log::SetLogLevel (const std::string& level) -{ - if (level == "error") { m_MinLevel = eLogError; } - else if (level == "warn") { m_MinLevel = eLogWarning; } - else if (level == "info") { m_MinLevel = eLogInfo; } - else if (level == "debug") { m_MinLevel = eLogDebug; } - else { - LogPrint(eLogError, "Log: Unknown loglevel: ", level); - return; - } - LogPrint(eLogInfo, "Log: min msg level set to ", level); -} + void Log::Append(std::shared_ptr & msg) { + m_Queue.Put(msg); + if (!m_IsReady) + return; + Process(); + } -void Log::SetLogStream (std::shared_ptr logStream) -{ - m_LogStream = logStream; -} + void Log::SendTo (const std::string& path) { + auto flags = std::ofstream::out | std::ofstream::app; + auto os = std::make_shared (path, flags); + if (os->is_open ()) { + m_Logfile = path; + m_Destination = eLogFile; + m_LogStream = os; + m_IsReady = true; + return; + } + LogPrint(eLogError, "Log: can't open file ", path); + } -void Log::StartSyslog(const std::string & ident, const int facility) -{ -#ifndef _WIN32 - m_Ident = ident; - openlog(m_Ident.c_str(), LOG_PID, facility); -#endif -} + void Log::SendTo (std::shared_ptr os) { + m_Destination = eLogStream; + m_IsReady = true; + m_LogStream = os; + } -void Log::StopSyslog() -{ #ifndef _WIN32 - closelog(); - m_Ident.clear(); + void Log::SendTo(const char *name, int facility) { + m_Destination = eLogSyslog; + m_LogStream = nullptr; + m_IsReady = true; + openlog(name, LOG_CONS | LOG_PID, facility); + } #endif -} -bool Log::SyslogEnabled() -{ - return m_Ident.size() > 0; -} + void Log::Reopen() { + if (m_Destination == eLogFile) + SendTo(m_Logfile); + } + + Log & Logger() { + return logger; + } +} // log +} // i2p diff --git a/Log.h b/Log.h index 76866590..ba755ae4 100644 --- a/Log.h +++ b/Log.h @@ -1,11 +1,19 @@ +/* +* Copyright (c) 2013-2016, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + #ifndef LOG_H__ #define LOG_H__ +#include #include #include -#include #include -#include +#include #include #include #include "Queue.h" @@ -23,150 +31,151 @@ enum LogLevel eNumLogLevels }; -class Log; -struct LogMsg -{ - std::stringstream s; - Log * log; - LogLevel level; - - LogMsg (Log * l = nullptr, LogLevel lv = eLogInfo): log (l), level (lv) {}; - - void Process(); -}; - -class Log: public i2p::util::MsgQueue -{ - public: - - Log () { SetOnEmpty (std::bind (&Log::Flush, this)); }; - ~Log () {}; - - void SetLogFile (const std::string& fullFilePath, bool truncate = true); - void ReopenLogFile (); - void SetLogLevel (const std::string& level); - void SetLogStream (std::shared_ptr logStream); - std::shared_ptr GetLogStream () const { return m_LogStream; }; - const std::string& GetTimestamp (); - LogLevel GetLogLevel () { return m_MinLevel; }; - const std::string& GetFullFilePath () const { return m_FullFilePath; }; - /** start logging to syslog */ - void StartSyslog(const std::string & ident, const int facility); - /** stop logging to syslog */ - void StopSyslog(); - /** are we logging to syslog right now? */ - bool SyslogEnabled(); - private: - - void Flush (); - - private: - - std::string m_FullFilePath; // empty if stream - std::shared_ptr m_LogStream; - enum LogLevel m_MinLevel; - std::string m_Timestamp; -#if (__GNUC__ == 4) && (__GNUC_MINOR__ <= 6) && !defined(__clang__) // gcc 4.6 - std::chrono::monotonic_clock::time_point m_LastTimestampUpdate; -#else - std::chrono::steady_clock::time_point m_LastTimestampUpdate; +enum LogType { + eLogStdout = 0, + eLogStream, + eLogFile, +#ifndef _WIN32 + eLogSyslog, #endif - std::string m_Ident; }; -extern Log * g_Log; +namespace i2p { +namespace log { + struct LogMsg; /* forward declaration */ -inline void StartLog (const std::string& fullFilePath) -{ - if (!g_Log) - { - auto log = new Log (); - if (fullFilePath.length () > 0) - log->SetLogFile (fullFilePath); - g_Log = log; - } -} - -inline void StartLog (std::shared_ptr s) -{ - if (!g_Log) - { - auto log = new Log (); - if (s) - log->SetLogStream (s); - g_Log = log; - } -} - -inline void StopLog () -{ - if (g_Log) + class Log { - auto log = g_Log; - g_Log = nullptr; - log->Stop (); - delete log; - } -} - -inline void SetLogLevel (const std::string& level) -{ - if (g_Log) - g_Log->SetLogLevel(level); -} - -inline void ReopenLogFile () -{ - if (g_Log) - g_Log->ReopenLogFile (); -} - -inline bool IsLogToFile () -{ - return g_Log ? !g_Log->GetFullFilePath ().empty () : false; -} - -inline void StartSyslog() -{ - StartLog(""); -#ifndef _WIN32 - g_Log->StartSyslog("i2pd", LOG_USER); -#endif -} - -inline void StopSyslog() -{ - if(g_Log) - g_Log->StopSyslog(); -} - + private: + + enum LogType m_Destination; + enum LogLevel m_MinLevel; + std::shared_ptr m_LogStream; + std::string m_Logfile; + std::time_t m_LastTimestamp; + char m_LastDateTime[64]; + i2p::util::Queue > m_Queue; + volatile bool m_IsReady; + mutable std::mutex m_OutputLock; + + private: + + /** prevent making copies */ + Log (const Log &); + const Log& operator=(const Log&); + + /** + * @brief process stored messages in queue + */ + void Process (); + + /** + * @brief Makes formatted string from unix timestamp + * @param ts Second since epoch + * + * This function internally caches the result for last provided value + */ + const char * TimeAsString(std::time_t ts); + + public: + + Log (); + ~Log (); + + LogType GetLogType () { return m_Destination; }; + LogLevel GetLogLevel () { return m_MinLevel; }; + + /** + * @brief Sets minimal alloed level for log messages + * @param level String with wanted minimal msg level + */ + void SetLogLevel (const std::string& level); + + /** + * @brief Sets log destination to logfile + * @param path Path to logfile + */ + void SendTo (const std::string &path); + + /** + * @brief Sets log destination to given output stream + * @param os Output stream + */ + void SendTo (std::shared_ptr s); + + #ifndef _WIN32 + /** + * @brief Sets log destination to syslog + * @param name Wanted program name + * @param facility Wanted log category + */ + void SendTo (const char *name, int facility); + #endif + + /** + * @brief Format log message and write to output stream/syslog + * @param msg Pointer to processed message + */ + void Append(std::shared_ptr &); + + /** @brief Flushes the output log stream */ + void Flush(); + + /** @brief Reopen log file */ + void Reopen(); + }; + + /** + * @struct Log message container + * + * We creating it somewhere with LogPrint(), + * then put in MsgQueue for later processing. + */ + struct LogMsg { + std::time_t timestamp; + std::string text; /**< message text as single string */ + LogLevel level; /**< message level */ + + LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {}; + }; + + Log & Logger(); +} // log +} // i2p + +/** internal usage only -- folding args array to single string */ template -void LogPrint (std::stringstream& s, TValue arg) +void LogPrint (std::stringstream& s, TValue arg) { s << arg; } - + +/** internal usage only -- folding args array to single string */ template -void LogPrint (std::stringstream& s, TValue arg, TArgs... args) +void LogPrint (std::stringstream& s, TValue arg, TArgs... args) { LogPrint (s, arg); LogPrint (s, args...); } +/** + * @brief Create log message and send it to queue + * @param level Message level (eLogError, eLogInfo, ...) + * @param args Array of message parts + */ template -void LogPrint (LogLevel level, TArgs... args) +void LogPrint (LogLevel level, TArgs... args) { - if (g_Log && level > g_Log->GetLogLevel ()) + i2p::log::Log &log = i2p::log::Logger(); + if (level > log.GetLogLevel ()) return; - LogMsg * msg = new LogMsg (g_Log, level); - LogPrint (msg->s, args...); - msg->s << std::endl; - if (g_Log) { - g_Log->Put (msg); - } else { - msg->Process (); - delete msg; - } + + // fold message to single string + std::stringstream ss(""); + LogPrint (ss, args ...); + + auto msg = std::make_shared(level, std::time(nullptr), ss.str()); + log.Append(msg); } -#endif +#endif // LOG_H__ From c57b13d9226ff5b52651f7548bf98b1dc5ca0715 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 27 Mar 2016 00:17:29 +0000 Subject: [PATCH 12/27] * migration --- Config.cpp | 2 +- Daemon.cpp | 50 ++++++++++++++++++++++++------------------------- DaemonLinux.cpp | 2 +- DaemonWin32.cpp | 2 +- api.cpp | 5 ++--- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/Config.cpp b/Config.cpp index 5e775e74..8671f38c 100644 --- a/Config.cpp +++ b/Config.cpp @@ -110,7 +110,7 @@ namespace config { ("conf", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2p.conf or /var/lib/i2pd/i2p.conf)") ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg)") ("pidfile", value()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)") - ("log", value()->default_value(""), "Logs destination: stdout, file (stdout if not set, file - otherwise, for compatibility)") + ("log", value()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)") ("logfile", value()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)") ("loglevel", value()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)") ("family", value()->default_value(""), "Specify a family, router belongs to") diff --git a/Daemon.cpp b/Daemon.cpp index 8b8dfac1..29d52ecc 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -79,17 +79,38 @@ namespace i2p i2p::config::ParseConfig(config); i2p::config::Finalize(); - i2p::crypto::InitCrypto (); - i2p::context.Init (); - i2p::config::GetOption("daemon", isDaemon); - // TODO: move log init here + std::string logs = ""; i2p::config::GetOption("log", logs); + std::string logfile = ""; i2p::config::GetOption("logfile", logfile); + std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel); + + /* setup logging */ + if (isDaemon && (logs == "" || logs == "stdout")) + logs = "file"; + + i2p::log::Logger().SetLogLevel(loglevel); + if (logs == "file") { + if (logfile == "") + logfile = i2p::fs::DataDirPath("i2pd.log"); + LogPrint(eLogInfo, "Log: will send messages to ", logfile); + i2p::log::Logger().SendTo (logfile); +#ifndef _WIN32 + } else if (logs == "syslog") { + LogPrint(eLogInfo, "Log: will send messages to syslog"); + i2p::log::Logger().SendTo("i2pd", LOG_DAEMON); +#endif + } else { + // use stdout -- default + } LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); LogPrint(eLogDebug, "FS: main config file: ", config); LogPrint(eLogDebug, "FS: data directory: ", datadir); + i2p::crypto::InitCrypto (); + i2p::context.Init (); + uint16_t port; i2p::config::GetOption("port", port); if (!i2p::config::IsDefault("port")) { @@ -152,26 +173,6 @@ namespace i2p bool Daemon_Singleton::start() { - std::string logs = ""; i2p::config::GetOption("log", logs); - std::string logfile = ""; i2p::config::GetOption("logfile", logfile); - std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel); - - if (isDaemon && (logs == "" || logs == "stdout")) - logs = "file"; - - if (logs == "syslog") { - // use syslog only no stdout - StartSyslog(); - } else if (logs == "file") { - if (logfile == "") - logfile = i2p::fs::DataDirPath("i2pd.log"); - StartLog (logfile); - } else { - // use stdout - StartLog (""); - } - SetLogLevel(loglevel); - bool http; i2p::config::GetOption("http.enabled", http); if (http) { std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); @@ -236,7 +237,6 @@ namespace i2p d.m_I2PControlService = nullptr; } i2p::crypto::TerminateCrypto (); - StopLog (); return true; } diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 59c286be..e760b4f5 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -19,7 +19,7 @@ void handle_signal(int sig) { case SIGHUP: LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening log..."); - ReopenLogFile (); + i2p::log::Logger().Reopen (); break; case SIGABRT: case SIGTERM: diff --git a/DaemonWin32.cpp b/DaemonWin32.cpp index b28cf2cd..a6d91da4 100644 --- a/DaemonWin32.cpp +++ b/DaemonWin32.cpp @@ -75,7 +75,7 @@ namespace i2p i2p::config::SetOption("log", std::string ("file")); #endif bool ret = Daemon_Singleton::start(); - if (ret && IsLogToFile ()) + if (ret && i2p::log::Logger().GetLogType() == eLogFile) { // TODO: find out where this garbage to console comes from SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE); diff --git a/api.cpp b/api.cpp index 3e037c02..3bef3f8e 100644 --- a/api.cpp +++ b/api.cpp @@ -40,9 +40,9 @@ namespace api void StartI2P (std::shared_ptr logStream) { if (logStream) - StartLog (logStream); + i2p::log::Logger().SendTo (logStream); else - StartLog (i2p::fs::DataDirPath (i2p::fs::GetAppName () + ".log")); + i2p::log::Logger().SendTo (i2p::fs::DataDirPath (i2p::fs::GetAppName () + ".log")); LogPrint(eLogInfo, "API: starting NetDB"); i2p::data::netdb.Start(); LogPrint(eLogInfo, "API: starting Transports"); @@ -60,7 +60,6 @@ namespace api i2p::transport::transports.Stop(); LogPrint(eLogInfo, "API: stopping NetDB"); i2p::data::netdb.Stop(); - StopLog (); } void RunPeerTest () From 3eae716a2d19c4161e6d4f3f82831094f30e8874 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 27 Mar 2016 00:00:00 +0000 Subject: [PATCH 13/27] * drop MsgQueue wrapper : not used anymore --- Queue.h | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/Queue.h b/Queue.h index 6f50e189..b47a19c8 100644 --- a/Queue.h +++ b/Queue.h @@ -117,52 +117,6 @@ namespace util std::mutex m_QueueMutex; std::condition_variable m_NonEmpty; }; - - template - class MsgQueue: public Queue - { - public: - - typedef std::function OnEmpty; - - MsgQueue (): m_IsRunning (true), m_Thread (std::bind (&MsgQueue::Run, this)) {}; - ~MsgQueue () { Stop (); }; - void Stop() - { - if (m_IsRunning) - { - m_IsRunning = false; - Queue::WakeUp (); - m_Thread.join(); - } - } - - void SetOnEmpty (OnEmpty const & e) { m_OnEmpty = e; }; - - private: - - void Run () - { - while (m_IsRunning) - { - while (auto msg = Queue::Get ()) - { - msg->Process (); - delete msg; - } - if (m_OnEmpty != nullptr) - m_OnEmpty (); - if (m_IsRunning) - Queue::Wait (); - } - } - - private: - - volatile bool m_IsRunning; - OnEmpty m_OnEmpty; - std::thread m_Thread; - }; } } From 5c9970c7867dd151ee7766cabe647a916663cd67 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 27 Mar 2016 09:16:30 -0400 Subject: [PATCH 14/27] delete packet if not saved --- Streaming.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Streaming.cpp b/Streaming.cpp index 33be58b5..8c11a889 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -162,7 +162,9 @@ namespace stream void Stream::SavePacket (Packet * packet) { - m_SavedPackets.insert (packet); + auto ins = m_SavedPackets.insert (packet); + // delete packed if not saved + if (!ins.second) delete packet; } void Stream::ProcessPacket (Packet * packet) From 23d6739580fc9725fb10188a9e0fb83c8b112a09 Mon Sep 17 00:00:00 2001 From: i2phttp Date: Sun, 27 Mar 2016 16:27:36 +0300 Subject: [PATCH 15/27] Renamed i2pd.conf->i2p.conf with some fixes --- docs/{i2pd.conf => i2p.conf} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename docs/{i2pd.conf => i2p.conf} (96%) diff --git a/docs/i2pd.conf b/docs/i2p.conf similarity index 96% rename from docs/i2pd.conf rename to docs/i2p.conf index 92595311..9bbc73fa 100644 --- a/docs/i2pd.conf +++ b/docs/i2p.conf @@ -31,9 +31,9 @@ #datadir = /var/lib/i2pd ## Daemon mode. Router will go to background after start -#daemon +#daemon = true ## Run as a service. Router will use system folders like ‘/var/lib/i2pd’ -#service +#service = true ## External IP address to listen for connections ## By default i2pd sets IP automatically @@ -50,10 +50,10 @@ ipv6 = true #bandwidth = L ## Router will not accept transit tunnels at startup -#notransit +#notransit = true ## Router will be floodfill -#floodfill +#floodfill = true ## Section for Web Console ## By default it's available at 127.0.0.1:7070 even if it's not configured @@ -73,7 +73,7 @@ port = 4444 ## Optional keys file for proxy local destination #keys = http-proxy-keys.dat ## Uncomment if you want to disable HTTP proxy -#enabled=false +#enabled = false ## Section for Socks proxy ## By default it's available at 127.0.0.1:4447 even if it's not configured @@ -85,7 +85,7 @@ port = 4444 ## Optional keys file for proxy local destination #keys = socks-proxy-keys.dat ## Uncomment if you want to disable Socks proxy -#enabled=false +#enabled = false ## Socks outproxy. Example below is set to use Tor for all connections except i2p ## Address of outproxy #outproxy = 127.0.0.1 From 266744f640dd66c73e8758eadcd787c9e84d8b1e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 27 Mar 2016 12:06:00 -0400 Subject: [PATCH 16/27] fixe memory leak --- Streaming.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Streaming.cpp b/Streaming.cpp index 33be58b5..e425ce27 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -162,7 +162,8 @@ namespace stream void Stream::SavePacket (Packet * packet) { - m_SavedPackets.insert (packet); + if (!m_SavedPackets.insert (packet).second) + delete packet; } void Stream::ProcessPacket (Packet * packet) From 905cad56d8ed49ccaddf2848cb9e66a0e4e69e9d Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 28 Mar 2016 00:00:00 +0000 Subject: [PATCH 17/27] * add note --- Log.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Log.cpp b/Log.cpp index 27637c77..9dd75d6b 100644 --- a/Log.cpp +++ b/Log.cpp @@ -85,6 +85,11 @@ namespace log { return m_LastDateTime; } + /** + * @note This function better to be run in separate thread due to disk i/o. + * 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); while (1) { From 8437d458661f8c439719a024ea457699161ec70e Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 28 Mar 2016 00:00:00 +0000 Subject: [PATCH 18/27] * rename i2p.conf -> i2pd.conf, add detection of old config --- Config.cpp | 2 +- Daemon.cpp | 14 +++++++++++--- debian/i2pd.1 | 2 +- debian/i2pd.links | 2 +- docs/configuration.md | 4 ++-- docs/{i2p.conf => i2pd.conf} | 0 6 files changed, 16 insertions(+), 8 deletions(-) rename docs/{i2p.conf => i2pd.conf} (100%) diff --git a/Config.cpp b/Config.cpp index 8671f38c..f9cf2477 100644 --- a/Config.cpp +++ b/Config.cpp @@ -107,7 +107,7 @@ namespace config { options_description general("General options"); general.add_options() ("help", "Show this message") - ("conf", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2p.conf or /var/lib/i2pd/i2p.conf)") + ("conf", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)") ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg)") ("pidfile", value()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)") ("log", value()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)") diff --git a/Daemon.cpp b/Daemon.cpp index 29d52ecc..d4803195 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -69,11 +69,19 @@ namespace i2p i2p::fs::Init(); datadir = i2p::fs::GetDataDir(); - if (config == "") + // TODO: drop old name detection in v2.8.0 + if (config == "") { config = i2p::fs::DataDirPath("i2p.conf"); - // use i2p.conf only if exists - if (!i2p::fs::Exists (config)) config = ""; /* reset */ + if (i2p::fs::Exists (config)) { + LogPrint(eLogWarning, "Daemon: please rename i2p.conf to i2pd.conf here: ", config); + } else { + config = i2p::fs::DataDirPath("i2pd.conf"); + if (!i2p::fs::Exists (config)) { + // use i2pd.conf only if exists + config = ""; /* reset */ + } + } } i2p::config::ParseConfig(config); diff --git a/debian/i2pd.1 b/debian/i2pd.1 index c6f0e9ba..2a1e7f88 100644 --- a/debian/i2pd.1 +++ b/debian/i2pd.1 @@ -68,7 +68,7 @@ Port of BOB command channel. Usually \fI2827\fR. BOB will not be enabled if this Port of I2P control service. Usually \fI7650\fR. I2PControl will not be enabled if this is not set. (default: unset) .TP \fB\-\-conf=\fR -Config file (default: \fI~/.i2pd/i2p.conf\fR or \fI/var/lib/i2pd/i2p.conf\fR) +Config file (default: \fI~/.i2pd/i2pd.conf\fR or \fI/var/lib/i2pd/i2pd.conf\fR) This parameter will be silently ignored if the specified config file does not exist. Options specified on the command line take precedence over those in the config file. diff --git a/debian/i2pd.links b/debian/i2pd.links index 369cce5b..58a75552 100644 --- a/debian/i2pd.links +++ b/debian/i2pd.links @@ -1,4 +1,4 @@ -etc/i2pd/i2pd.conf var/lib/i2pd/i2p.conf +etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.cfg etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt usr/share/i2pd/certificates var/lib/i2pd/certificates diff --git a/docs/configuration.md b/docs/configuration.md index 46e5092c..3d03b1c7 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -4,7 +4,7 @@ i2pd configuration Command line options -------------------- -* --conf= - Config file (default: ~/.i2pd/i2p.conf or /var/lib/i2pd/i2p.conf) +* --conf= - Config file (default: ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf) This parameter will be silently ignored if the specified config file does not exist. Options specified on the command line take precedence over those in the config file. * --tunconf= - Tunnels config file (default: ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg) @@ -60,7 +60,7 @@ All command-line parameters are allowed as keys, but note for those which contai For example: -i2p.conf: +i2pd.conf: # comment log = true diff --git a/docs/i2p.conf b/docs/i2pd.conf similarity index 100% rename from docs/i2p.conf rename to docs/i2pd.conf From e6dbeda18eef8b7747910b4c9af149f4c54e316a Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 28 Mar 2016 00:00:00 +0000 Subject: [PATCH 19/27] * rename tunnels.conf -> tunnels.conf, add detection of old config --- ClientContext.cpp | 9 ++++++++- Config.cpp | 2 +- debian/i2pd.links | 2 +- docs/configuration.md | 4 ++-- docs/i2pd.conf | 4 ++-- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 8c626b25..ccb8e0ad 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -261,8 +261,15 @@ namespace client { boost::property_tree::ptree pt; std::string tunConf; i2p::config::GetOption("tunconf", tunConf); - if (tunConf == "") + if (tunConf == "") { + // TODO: cleanup this in 2.8.0 tunConf = i2p::fs::DataDirPath ("tunnels.cfg"); + if (i2p::fs::Exists(tunConf)) { + LogPrint(eLogWarning, "FS: please rename tunnels.cfg -> tunnels.conf here: ", tunConf); + } else { + tunConf = i2p::fs::DataDirPath ("tunnels.conf"); + } + } LogPrint(eLogDebug, "FS: tunnels config file: ", tunConf); try { diff --git a/Config.cpp b/Config.cpp index f9cf2477..1dc1207f 100644 --- a/Config.cpp +++ b/Config.cpp @@ -108,7 +108,7 @@ namespace config { general.add_options() ("help", "Show this message") ("conf", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)") - ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg)") + ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)") ("pidfile", value()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)") ("log", value()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)") ("logfile", value()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)") diff --git a/debian/i2pd.links b/debian/i2pd.links index 58a75552..e8e2473b 100644 --- a/debian/i2pd.links +++ b/debian/i2pd.links @@ -1,4 +1,4 @@ etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf -etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.cfg +etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt usr/share/i2pd/certificates var/lib/i2pd/certificates diff --git a/docs/configuration.md b/docs/configuration.md index 3d03b1c7..18d30017 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -7,7 +7,7 @@ Command line options * --conf= - Config file (default: ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf) This parameter will be silently ignored if the specified config file does not exist. Options specified on the command line take precedence over those in the config file. -* --tunconf= - Tunnels config file (default: ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg) +* --tunconf= - Tunnels config file (default: ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf) * --pidfile= - Where to write pidfile (dont write by default) * --log= - Logs destination: stdout, file (stdout if not set, file - otherwise, for compatibility) * --logfile= - Path to logfile (default - autodetect) @@ -73,7 +73,7 @@ i2pd.conf: [sam] enabled = true -tunnels.cfg (filename of this config is subject of change): +tunnels.conf # outgoing tunnel sample, to remote service # mandatory parameters: diff --git a/docs/i2pd.conf b/docs/i2pd.conf index 9bbc73fa..81bcc634 100644 --- a/docs/i2pd.conf +++ b/docs/i2pd.conf @@ -7,8 +7,8 @@ ## by removing the "#" symbol. ## Tunnels config file -## Default: ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg -#tunconf = /var/lib/i2pd/tunnels.cfg +## Default: ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf +#tunconf = /var/lib/i2pd/tunnels.conf ## Where to write pidfile (don't write by default) #pidfile = /var/run/i2pd.pid From cc25b22f118fd050f944a58c56789e6380e27b99 Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 28 Mar 2016 00:00:00 +0000 Subject: [PATCH 20/27] * update docs --- docs/configuration.md | 14 ++++- docs/family.md | 30 +++++---- docs/i2pd.conf | 139 ++++++++++++++++++++---------------------- 3 files changed, 95 insertions(+), 88 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 18d30017..1a45716d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -4,9 +4,12 @@ i2pd configuration Command line options -------------------- +Options specified on the command line take precedence over those in the config file. +If you are upgrading your very old router (< 2.3.0) see also [this](config_opts_after_2.3.0.md) page. + +* --help - Show builtin help message (default value of option will be shown in braces) * --conf= - Config file (default: ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf) This parameter will be silently ignored if the specified config file does not exist. - Options specified on the command line take precedence over those in the config file. * --tunconf= - Tunnels config file (default: ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf) * --pidfile= - Where to write pidfile (dont write by default) * --log= - Logs destination: stdout, file (stdout if not set, file - otherwise, for compatibility) @@ -24,6 +27,8 @@ Command line options * --family= - Name of a family, router belongs to * --svcctl= - Windows service management (--svcctl="install" or --svcctl="remove") +All options below still possible in cmdline, but better write it in config file: + * --http.address= - The address to listen on (HTTP server) * --http.port= - The port to listen on (HTTP server) @@ -69,11 +74,13 @@ i2pd.conf: [httpproxy] port = 4444 # ^^ this will be --httproxy.port= in cmdline - # another one + # another comment [sam] enabled = true -tunnels.conf +See also commented config with examples of all options in ``docs/i2pd.conf``. + +tunnels.conf: # outgoing tunnel sample, to remote service # mandatory parameters: @@ -107,6 +114,7 @@ tunnels.conf host = 127.0.0.1 port = 80 keys = site-keys.dat + # [IRC-SERVER] type = server host = 127.0.0.1 diff --git a/docs/family.md b/docs/family.md index 8ef76b7a..bb925171 100644 --- a/docs/family.md +++ b/docs/family.md @@ -6,27 +6,31 @@ There are two possibilities: create new family or joing to existing. New family ----------- + You must create family self-signed certificate and key. The only key type supposted is prime256v1. Use the following list of commands: -openssl ecparam -name prime256v1 -genkey -out .key -openssl req -new -key .key -out .csr -touch v3.ext -openssl x509 -req -days 3650 -in .csr -signkey .key -out .crt -extfile v3.ext -specify .family.i2p.net for CN. + openssl ecparam -name prime256v1 -genkey -out .key + openssl req -new -key .key -out .csr + touch v3.ext + openssl x509 -req -days 3650 -in .csr -signkey .key -out .crt -extfile v3.ext + +Specify .family.i2p.net for CN (Common Name) when requested. -Once you are done with it place .key and .crt to /family folder (for exmple ~/.i2pd/family). +Once you are done with it place .key and .crt to /family folder (for exmple ~/.i2pd/family). You should provide these two files to other members joining your family. If you want to register you family and let I2P network recorgnize it, create pull request for you .crt file into contrib/certificate/family. -It will appear in i2pd and I2P next releases packages. Don't place .key file, it must be shared betwwen you family members only. +It will appear in i2pd and I2P next releases packages. Dont place .key file, it must be shared between you family members only. + +How to join existing family +--------------------------- -Join existing family --------------------- -Once you and that family agree to do it, they must give you .key and .crt file and you must place to /family folder. +Once you and that family agree to do it, they must give you .key and .crt file and you must place in /certificates/family/ folder. Publish your family ------------------- -Run i2pd with parameter 'family=', make sure you have .key and .crt in your 'family' folder. -If everything is set properly, you router.info will contain two new fields: 'family' and 'family.sig'. +------------------- +Run i2pd with parameter 'family=', make sure you have .key and .crt in your 'family' folder. +If everything is set properly, you router.info will contain two new fields: 'family' and 'family.sig'. +Otherwise your router will complain on startup with log messages starting with "Family:" prefix and severity 'warn' or 'error'. diff --git a/docs/i2pd.conf b/docs/i2pd.conf index 81bcc634..e85eaa17 100644 --- a/docs/i2pd.conf +++ b/docs/i2pd.conf @@ -6,109 +6,104 @@ ## that begin with just "#" are disabled commands: you can enable them ## by removing the "#" symbol. -## Tunnels config file +## Tunnels config file ## Default: ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf -#tunconf = /var/lib/i2pd/tunnels.conf +# tunconf = /var/lib/i2pd/tunnels.conf ## Where to write pidfile (don't write by default) -#pidfile = /var/run/i2pd.pid +# pidfile = /var/run/i2pd.pid ## Logging configuration section -## By default logs go to stdout with level info +## By default logs go to stdout with level 'info' and higher ## -## Logs destination (stdout, file, syslog) -## stdout - print log entries to stdout -## file - log entries to a file -## syslog - use syslog, see man 3 syslog -#log = file +## Logs destination (valid values: stdout, file, syslog) +## * stdout - print log entries to stdout +## * file - log entries to a file +## * syslog - use syslog, see man 3 syslog +# log = file ## Path to logfile (default - autodetect) -#logfile = /var/log/i2pd.log +# logfile = /var/log/i2pd.log ## Log messages above this level (debug, *info, warn, error) -#loglevel = info +# loglevel = info ## Path to storage of i2pd data (RI, keys, peer profiles, ...) ## Default: ~/.i2pd or /var/lib/i2pd -#datadir = /var/lib/i2pd +# datadir = /var/lib/i2pd ## Daemon mode. Router will go to background after start -#daemon = true +# daemon = true ## Run as a service. Router will use system folders like ‘/var/lib/i2pd’ -#service = true +# service = true ## External IP address to listen for connections ## By default i2pd sets IP automatically -#host = 1.2.3.4 +# host = 1.2.3.4 + ## Port to listen for connections -## By default i2pd picks random port. You MUST pick a random number too, +## By default i2pd picks random port. You MUST pick a random number too, ## don't just uncomment this -#port = 4321 -##Enable communication through ipv6 +# port = 4321 + +## Enable communication through ipv6 ipv6 = true + ## Bandwidth configuration ## L limit bandwidth to 32Kbs/sec, O - to 256Kbs/sec, P - unlimited ## Default is P for floodfill, L for regular node -#bandwidth = L +# bandwidth = L ## Router will not accept transit tunnels at startup -#notransit = true +# notransit = true ## Router will be floodfill -#floodfill = true +# floodfill = true -## Section for Web Console -## By default it's available at 127.0.0.1:7070 even if it's not configured [http] -## The address to listen on -address = 127.0.0.1 -## The port to listen on -port = 7070 +## Uncomment and set to 'false' to disable Web Console +# enabled = true +## Address and port service will listen on +address = 127.0.0.1 +port = 7070 -## Section for HTTP proxy -## By default it's available at 127.0.0.1:4444 even if it's not configured [httpproxy] -## The address to listen on -address = 127.0.0.1 -## The port to listen on -port = 4444 +## Uncomment and set to 'false' to disable HTTP Proxy +# enabled = true +## Address and port service will listen on +# address = 127.0.0.1 +# port = 4444 ## Optional keys file for proxy local destination -#keys = http-proxy-keys.dat -## Uncomment if you want to disable HTTP proxy -#enabled = false - -## Section for Socks proxy -## By default it's available at 127.0.0.1:4447 even if it's not configured -#[socksproxy] -## The address to listen on -#address = 127.0.0.1 -## The port to listen on -#port = 4447 +# keys = http-proxy-keys.dat + +[socksproxy] +## Uncomment and set to 'false' to disable SOCKS Proxy +# enabled = true +## Address and port service will listen on +# address = 127.0.0.1 +# port = 4447 ## Optional keys file for proxy local destination -#keys = socks-proxy-keys.dat -## Uncomment if you want to disable Socks proxy -#enabled = false +# keys = socks-proxy-keys.dat ## Socks outproxy. Example below is set to use Tor for all connections except i2p -## Address of outproxy -#outproxy = 127.0.0.1 -## Outproxy remote port -#outproxyport = 9050 - -## Section for SAM bridge -#[sam] -## The address to listen on -#address = 127.0.0.1 -## Port of SAM bridge -#port = 7656 - -## Section for BOB command channel -#[bob] -## The address to listen on -#address = 127.0.0.1 -## Port of BOB command channel. Usually 2827. BOB is off if not specified -#port = 2827 - -## Section for I2PControl protocol -#[i2pcontrol] -## The address to listen on -#address = 127.0.0.1 -## Port of I2P control service -#port = 7650 +## Address and port of outproxy +# outproxy = 127.0.0.1 +# outproxyport = 9050 + +[sam] +## Uncomment and set to 'true' to enable SAM Bridge +# enabled = false +## Address and port service will listen on +# address = 127.0.0.1 +# port = 7656 + +[bob] +## Uncomment and set to 'true' to enable BOB command channel +# enabled = false +## Address and port service will listen on +# address = 127.0.0.1 +# port = 2827 + +[i2pcontrol] +## Uncomment and set to 'true' to enable I2PControl protocol +# enabled = false +## Address and port service will listen on +# address = 127.0.0.1 +# port = 7650 From 38103aaac5d77161858e021dbf94061aa82e00f4 Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 28 Mar 2016 14:00:00 +0000 Subject: [PATCH 21/27] * logger: explicit allow log output --- Daemon.cpp | 1 + Log.cpp | 3 --- Log.h | 3 +++ api.cpp | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index d4803195..3adfdb71 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -111,6 +111,7 @@ namespace i2p } else { // use stdout -- default } + i2p::log::Logger().Ready(); LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); LogPrint(eLogDebug, "FS: main config file: ", config); diff --git a/Log.cpp b/Log.cpp index 9dd75d6b..06aabac5 100644 --- a/Log.cpp +++ b/Log.cpp @@ -127,7 +127,6 @@ namespace log { m_Logfile = path; m_Destination = eLogFile; m_LogStream = os; - m_IsReady = true; return; } LogPrint(eLogError, "Log: can't open file ", path); @@ -135,7 +134,6 @@ namespace log { void Log::SendTo (std::shared_ptr os) { m_Destination = eLogStream; - m_IsReady = true; m_LogStream = os; } @@ -143,7 +141,6 @@ namespace log { void Log::SendTo(const char *name, int facility) { m_Destination = eLogSyslog; m_LogStream = nullptr; - m_IsReady = true; openlog(name, LOG_CONS | LOG_PID, facility); } #endif diff --git a/Log.h b/Log.h index ba755ae4..6cda62f6 100644 --- a/Log.h +++ b/Log.h @@ -118,6 +118,9 @@ namespace log { */ void Append(std::shared_ptr &); + /** @brief Allow log output */ + void Ready() { m_IsReady = true; } + /** @brief Flushes the output log stream */ void Flush(); diff --git a/api.cpp b/api.cpp index 3bef3f8e..64648743 100644 --- a/api.cpp +++ b/api.cpp @@ -43,6 +43,7 @@ namespace api i2p::log::Logger().SendTo (logStream); else i2p::log::Logger().SendTo (i2p::fs::DataDirPath (i2p::fs::GetAppName () + ".log")); + i2p::log::Logger().Ready(); LogPrint(eLogInfo, "API: starting NetDB"); i2p::data::netdb.Start(); LogPrint(eLogInfo, "API: starting Transports"); From 1fae3baaa3270081c68c645c1db03ecce9dc6d24 Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 28 Mar 2016 14:00:00 +0000 Subject: [PATCH 22/27] * logger: print also thread id --- Log.cpp | 16 +++++++++++++--- Log.h | 4 +++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Log.cpp b/Log.cpp index 06aabac5..36fcebf3 100644 --- a/Log.cpp +++ b/Log.cpp @@ -92,22 +92,32 @@ namespace log { */ void Log::Process() { std::unique_lock l(m_OutputLock); + 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) { #ifndef _WIN32 case eLogSyslog: - syslog(GetSyslogPrio(msg->level), "%s", msg->text.c_str()); + syslog(GetSyslogPrio(msg->level), "[%03u] %s", short_tid, msg->text.c_str()); break; #endif case eLogFile: case eLogStream: - *m_LogStream << TimeAsString(msg->timestamp) << "/" << g_LogLevelStr[msg->level] << " - " << msg->text << std::endl; + *m_LogStream << TimeAsString(msg->timestamp) + << "@" << short_tid + << "/" << g_LogLevelStr[msg->level] + << " - " << msg->text << std::endl; break; + case eLogStdout: default: - std::cout << TimeAsString(msg->timestamp) << "/" << g_LogLevelStr[msg->level] << " - " << msg->text << std::endl; + std::cout << TimeAsString(msg->timestamp) + << "@" << short_tid + << "/" << g_LogLevelStr[msg->level] + << " - " << msg->text << std::endl; break; } // switch } // while diff --git a/Log.h b/Log.h index 6cda62f6..ebb73a12 100644 --- a/Log.h +++ b/Log.h @@ -138,8 +138,9 @@ namespace log { std::time_t timestamp; std::string text; /**< message text as single string */ LogLevel level; /**< message level */ + std::thread::id tid; /**< id of thread that generated message */ - LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {}; + LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl), tid(0) {}; }; Log & Logger(); @@ -178,6 +179,7 @@ void LogPrint (LogLevel level, TArgs... args) LogPrint (ss, args ...); auto msg = std::make_shared(level, std::time(nullptr), ss.str()); + msg->tid = std::this_thread::get_id(); log.Append(msg); } From e3451617635493e65b4c34193c2393f07194e3ee Mon Sep 17 00:00:00 2001 From: xcps Date: Mon, 28 Mar 2016 14:33:55 -0400 Subject: [PATCH 23/27] default subscription address to inr, jump services b32 --- AddressBook.h | 2 +- HTTPServer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AddressBook.h b/AddressBook.h index 24a7e151..56f8145c 100644 --- a/AddressBook.h +++ b/AddressBook.h @@ -18,7 +18,7 @@ namespace i2p { namespace client { - const char DEFAULT_SUBSCRIPTION_ADDRESS[] = "http://udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p/hosts.txt"; + const char DEFAULT_SUBSCRIPTION_ADDRESS[] = "http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt"; const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 1aa5d273..b6ec3522 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -525,8 +525,8 @@ namespace util s << ""; s << "
\r\n"; s << "Jump services for " << address << ""; - s << ""; + s << ""; } void HTTPConnection::ShowLocalDestinations (std::stringstream& s) From f5e1077e200e1d6cd660d4deb69d8d622955baf9 Mon Sep 17 00:00:00 2001 From: Manas Bhatnagar Date: Mon, 28 Mar 2016 17:05:39 -0400 Subject: [PATCH 24/27] i2p family cert file --- contrib/certificates/family/i2p.crt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 contrib/certificates/family/i2p.crt diff --git a/contrib/certificates/family/i2p.crt b/contrib/certificates/family/i2p.crt new file mode 100644 index 00000000..59d160ce --- /dev/null +++ b/contrib/certificates/family/i2p.crt @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBsTCCAVigAwIBAgIJAN5fDNQVePgoMAkGByqGSM49BAEwXzELMAkGA1UEBhMC +QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp +dHMgUHR5IEx0ZDEYMBYGA1UEAwwPLmZhbWlseS5pMnAubmV0MB4XDTE2MDMyODE5 +NDUyNFoXDTI2MDMyNjE5NDUyNFowXzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNv +bWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEYMBYG +A1UEAwwPLmZhbWlseS5pMnAubmV0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +nq+UQQ6Wm/HIbEx41jY+kT7oP0NXU5Nsxsku97KPMtHNwYQD4CJYLwsTICd2ZtrK +jn8adUWmmXd+NbX1KrtMtDAJBgcqhkjOPQQBA0gAMEUCIQCTSNPVfjH2vwXzFEMy +V/4Q8sQ56TIjANcZ3ubAUQbA6wIgNu/bekl9tB1pRqPIm38v6Y6sxxZ8kOL++Q24 +YotZ7o0= +-----END CERTIFICATE----- From 0a3c4f131e16ea2e44b826ddd3ab9fec13f7a680 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 28 Mar 2016 17:15:27 -0400 Subject: [PATCH 25/27] fix issue #449 failed build of freebsd 10.1 --- Log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Log.h b/Log.h index ebb73a12..33bd5868 100644 --- a/Log.h +++ b/Log.h @@ -140,7 +140,7 @@ namespace log { LogLevel level; /**< message level */ std::thread::id tid; /**< id of thread that generated message */ - LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl), tid(0) {}; + LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {}; }; Log & Logger(); From 0828065a623565f55cf5cc5ba92bc9d132f8a2ae Mon Sep 17 00:00:00 2001 From: Manas Bhatnagar Date: Mon, 28 Mar 2016 17:51:24 -0400 Subject: [PATCH 26/27] Rename i2p.crt to mca2-i2p.crt --- contrib/certificates/family/{i2p.crt => mca2-i2p.crt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename contrib/certificates/family/{i2p.crt => mca2-i2p.crt} (100%) diff --git a/contrib/certificates/family/i2p.crt b/contrib/certificates/family/mca2-i2p.crt similarity index 100% rename from contrib/certificates/family/i2p.crt rename to contrib/certificates/family/mca2-i2p.crt From ed6851863b8244af3fd1c758db578218dda5910c Mon Sep 17 00:00:00 2001 From: Manas Bhatnagar Date: Mon, 28 Mar 2016 18:08:11 -0400 Subject: [PATCH 27/27] update mca2-i2p.crt --- contrib/certificates/family/mca2-i2p.crt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/contrib/certificates/family/mca2-i2p.crt b/contrib/certificates/family/mca2-i2p.crt index 59d160ce..f5b57303 100644 --- a/contrib/certificates/family/mca2-i2p.crt +++ b/contrib/certificates/family/mca2-i2p.crt @@ -1,12 +1,12 @@ -----BEGIN CERTIFICATE----- -MIIBsTCCAVigAwIBAgIJAN5fDNQVePgoMAkGByqGSM49BAEwXzELMAkGA1UEBhMC +MIIBwTCCAWigAwIBAgIJAOZBC10+/38EMAkGByqGSM49BAEwZzELMAkGA1UEBhMC QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp -dHMgUHR5IEx0ZDEYMBYGA1UEAwwPLmZhbWlseS5pMnAubmV0MB4XDTE2MDMyODE5 -NDUyNFoXDTI2MDMyNjE5NDUyNFowXzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNv -bWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEYMBYG -A1UEAwwPLmZhbWlseS5pMnAubmV0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -nq+UQQ6Wm/HIbEx41jY+kT7oP0NXU5Nsxsku97KPMtHNwYQD4CJYLwsTICd2ZtrK -jn8adUWmmXd+NbX1KrtMtDAJBgcqhkjOPQQBA0gAMEUCIQCTSNPVfjH2vwXzFEMy -V/4Q8sQ56TIjANcZ3ubAUQbA6wIgNu/bekl9tB1pRqPIm38v6Y6sxxZ8kOL++Q24 -YotZ7o0= +dHMgUHR5IEx0ZDEgMB4GA1UEAwwXbWNhMi1pMnAuZmFtaWx5LmkycC5uZXQwHhcN +MTYwMzI4MjIwMjMxWhcNMjYwMzI2MjIwMjMxWjBnMQswCQYDVQQGEwJBVTETMBEG +A1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg +THRkMSAwHgYDVQQDDBdtY2EyLWkycC5mYW1pbHkuaTJwLm5ldDBZMBMGByqGSM49 +AgEGCCqGSM49AwEHA0IABNNyfzJr/rMSUeWliVBbJHRF2+qMypOlHEZ9m1nNATVX +64OhuyuVCmbF9R3oDkcZZJQQK1ovXd/EsbAIWDI8K/gwCQYHKoZIzj0EAQNIADBF +AiEApmv2tvMwzlvPjHJG1/5aXOSjYWw2s4ETeGt4abWPQkACIBbF3RuCHuzg+KN8 +N0n9hAJztAqhRCdG3hilxF4fbVLp -----END CERTIFICATE-----