From d95b4befaa66b8047398075391e3591b1e2a9e84 Mon Sep 17 00:00:00 2001 From: Meeh Date: Sat, 1 Feb 2014 04:09:55 +0100 Subject: [PATCH 1/4] Adding support for config file Example: -port=17070 --port=17070 cat /home/$USER/.i2pd/i2p.conf port=17070 --- Makefile | 2 +- i2p.cpp | 21 +++++- util.cpp | 216 ++++++++++++++++++++++++++++++++++++++++++------------- util.h | 24 +++++-- 4 files changed, 207 insertions(+), 56 deletions(-) diff --git a/Makefile b/Makefile index 240e4a3b..b5739c46 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ OBJECTS = obj/i2p.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transpor obj/TunnelGateway.o obj/TransitTunnel.o obj/I2NPProtocol.o obj/Log.o obj/Garlic.o \ obj/HTTPServer.o obj/Streaming.o obj/Identity.o obj/SSU.o obj/util.o obj/Reseed.o INCFLAGS = -LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lpthread +LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread LIBS = all: obj i2p diff --git a/i2p.cpp b/i2p.cpp index 5c0bd378..82a69671 100644 --- a/i2p.cpp +++ b/i2p.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "Log.h" #include "base64.h" #include "Transports.h" @@ -14,7 +15,7 @@ int main( int argc, char* argv[] ) { - i2p::util::OptionParser(argc,argv); + i2p::util::config::OptionParser(argc,argv); #ifdef _WIN32 setlocale(LC_CTYPE, ""); SetConsoleCP(1251); @@ -22,10 +23,24 @@ int main( int argc, char* argv[] ) setlocale(LC_ALL, "Russian"); #endif + LogPrint("\n\n\n\ni2pd starting\n"); + LogPrint("default data directory: ", i2p::util::filesystem::GetDefaultDataDir().string()); + if (!boost::filesystem::exists( i2p::util::filesystem::GetDefaultDataDir() )) + { + // Create data directory + if (!boost::filesystem::create_directory( i2p::util::filesystem::GetDefaultDataDir() )) + { + LogPrint("Failed to create data directory, exiting! :("); + return -1; + } + } + i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); + //TODO: This is an ugly workaround. fix it. //TODO: Autodetect public IP. - i2p::context.OverrideNTCPAddress(i2p::util::GetCharArg("--host", "127.0.0.1"), i2p::util::GetIntArg("--port", 17070)); - int httpport = i2p::util::GetIntArg("--httpport", 7070); + i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"), + i2p::util::config::GetArg("-port", 17070)); + int httpport = i2p::util::config::GetArg("-httpport", 7070); i2p::util::HTTPServer httpServer (httpport); diff --git a/util.cpp b/util.cpp index a33414ac..ff013035 100644 --- a/util.cpp +++ b/util.cpp @@ -3,7 +3,13 @@ #include #include #include +#include #include +#include +#include +#include +#include +#include #include "util.h" #include "Log.h" @@ -11,40 +17,154 @@ namespace i2p { namespace util { -std::map mapArgs; -void OptionParser(int argc, const char* const argv[]) +namespace config { - mapArgs.clear(); - for (int i = 1; i < argc; i++) - { - std::string strKey (argv[i]); - std::string strValue; - size_t has_data = strKey.find('='); - if (has_data != std::string::npos) - { - strValue = strKey.substr(has_data+1); - strKey = strKey.substr(0, has_data); - } - if (strKey[0] != '-') - break; - - mapArgs[strKey] = strValue; - } -} + std::map mapArgs; + std::map > mapMultiArgs; -int GetIntArg(const std::string& strArg, int nDefault) -{ - if (mapArgs.count(strArg)) - return atoi(mapArgs[strArg].c_str()); - return nDefault; + void OptionParser(int argc, const char* const argv[]) + { + mapArgs.clear(); + mapMultiArgs.clear(); + for (int i = 1; i < argc; i++) + { + std::string strKey (argv[i]); + std::string strValue; + size_t has_data = strKey.find('='); + if (has_data != std::string::npos) + { + strValue = strKey.substr(has_data+1); + strKey = strKey.substr(0, has_data); + } + +#ifdef WIN32 + boost::to_lower(strKey); + if (boost::algorithm::starts_with(strKey, "/")) + strKey = "-" + strKey.substr(1); +#endif + if (strKey[0] != '-') + break; + + mapArgs[strKey] = strValue; + mapMultiArgs[strKey].push_back(strValue); + } + + BOOST_FOREACH(PAIRTYPE(const std::string,std::string)& entry, mapArgs) + { + std::string name = entry.first; + + // interpret --foo as -foo (as long as both are not set) + if (name.find("--") == 0) + { + std::string singleDash(name.begin()+1, name.end()); + if (mapArgs.count(singleDash) == 0) + mapArgs[singleDash] = entry.second; + name = singleDash; + } + } + } + + const char* GetCharArg(const std::string& strArg, const std::string& nDefault) + { + if (mapArgs.count(strArg)) + return mapArgs[strArg].c_str(); + return nDefault.c_str(); + } + + std::string GetArg(const std::string& strArg, const std::string& strDefault) + { + if (mapArgs.count(strArg)) + return mapArgs[strArg]; + return strDefault; + } + + int GetArg(const std::string& strArg, int nDefault) + { + if (mapArgs.count(strArg)) + return atoi(mapArgs[strArg].c_str()); + return nDefault; + } } -const char* GetCharArg(const std::string& strArg, const std::string& nDefault) +namespace filesystem { - if (mapArgs.count(strArg)) - return mapArgs[strArg].c_str(); - return nDefault.c_str(); + const boost::filesystem::path &GetDataDir(bool fNetSpecific) + { + + static boost::filesystem::path path; + + if (config::mapArgs.count("--datadir")) { + path = boost::filesystem::system_complete(config::mapArgs["--datadir"]); + if (!boost::filesystem::is_directory(path)) { + path = ""; + return path; + } + } else { + path = GetDefaultDataDir(); + } + + boost::filesystem::create_directory(path); + + return path; + } + + boost::filesystem::path GetConfigFile() + { + boost::filesystem::path pathConfigFile(i2p::util::config::GetArg("-conf", "i2p.conf")); + if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; + return pathConfigFile; + } + + void ReadConfigFile(std::map& mapSettingsRet, + std::map >& mapMultiSettingsRet) + { + boost::filesystem::ifstream streamConfig(GetConfigFile()); + if (!streamConfig.good()) + return; // No i2pd.conf file is OK + + std::set setOptions; + setOptions.insert("*"); + + for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it) + { + // Don't overwrite existing settings so command line settings override i2pd.conf + std::string strKey = std::string("-") + it->string_key; + if (mapSettingsRet.count(strKey) == 0) + { + mapSettingsRet[strKey] = it->value[0]; + } + mapMultiSettingsRet[strKey].push_back(it->value[0]); + } + } + + boost::filesystem::path GetDefaultDataDir() + { + // Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd + // Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd + // Mac: ~/Library/Application Support/i2pd + // Unix: ~/.i2pd +#ifdef WIN32 + // Windows + return GetSpecialFolderPath(CSIDL_APPDATA) / "i2pd"; +#else + boost::filesystem::path pathRet; + char* pszHome = getenv("HOME"); + if (pszHome == NULL || strlen(pszHome) == 0) + pathRet = boost::filesystem::path("/"); + else + pathRet = boost::filesystem::path(pszHome); +#ifdef MAC_OSX + // Mac + pathRet /= "Library/Application Support"; + boost::filesystem::create_directory(pathRet); + return pathRet / "i2pd"; +#else + // Unix + return pathRet / ".i2pd"; +#endif +#endif + } } namespace http @@ -102,26 +222,26 @@ namespace http void url::parse(const std::string& url_s) { - const std::string prot_end("://"); - std::string::const_iterator prot_i = search(url_s.begin(), url_s.end(), - prot_end.begin(), prot_end.end()); - protocol_.reserve(distance(url_s.begin(), prot_i)); - transform(url_s.begin(), prot_i, - back_inserter(protocol_), - std::ptr_fun(tolower)); // protocol is icase - if( prot_i == url_s.end() ) - return; - advance(prot_i, prot_end.length()); - std::string::const_iterator path_i = find(prot_i, url_s.end(), '/'); - host_.reserve(distance(prot_i, path_i)); - transform(prot_i, path_i, - back_inserter(host_), - std::ptr_fun(tolower)); // host is icase - std::string::const_iterator query_i = find(path_i, url_s.end(), '?'); - path_.assign(path_i, query_i); - if( query_i != url_s.end() ) - ++query_i; - query_.assign(query_i, url_s.end()); + const std::string prot_end("://"); + std::string::const_iterator prot_i = search(url_s.begin(), url_s.end(), + prot_end.begin(), prot_end.end()); + protocol_.reserve(distance(url_s.begin(), prot_i)); + transform(url_s.begin(), prot_i, + back_inserter(protocol_), + std::ptr_fun(tolower)); // protocol is icase + if( prot_i == url_s.end() ) + return; + advance(prot_i, prot_end.length()); + std::string::const_iterator path_i = find(prot_i, url_s.end(), '/'); + host_.reserve(distance(prot_i, path_i)); + transform(prot_i, path_i, + back_inserter(host_), + std::ptr_fun(tolower)); // host is icase + std::string::const_iterator query_i = find(path_i, url_s.end(), '?'); + path_.assign(path_i, query_i); + if( query_i != url_s.end() ) + ++query_i; + query_.assign(query_i, url_s.end()); } } diff --git a/util.h b/util.h index 7643e0d0..7f22e3f1 100644 --- a/util.h +++ b/util.h @@ -4,14 +4,30 @@ #include #include +#define PAIRTYPE(t1, t2) std::pair + namespace i2p { namespace util { - extern std::map mapArgs; - void OptionParser(int argc, const char* const argv[]); - int GetIntArg(const std::string& strArg, int nDefault); - const char* GetCharArg(const std::string& strArg, const std::string& nDefault); + namespace config + { + extern std::map mapArgs; + extern std::map > mapMultiArgs; + void OptionParser(int argc, const char* const argv[]); + int GetArg(const std::string& strArg, int nDefault); + std::string GetArg(const std::string& strArg, const std::string& strDefault); + const char* GetCharArg(const std::string& strArg, const std::string& nDefault); + } + + namespace filesystem + { + boost::filesystem::path GetDefaultDataDir(); + boost::filesystem::path GetConfigFile(); + void ReadConfigFile(std::map& mapSettingsRet, + std::map >& mapMultiSettingsRet); + } + namespace http { std::string httpRequest(const std::string& address); From 56f1f627ef8af1ba1592561ae42abba68d090c0f Mon Sep 17 00:00:00 2001 From: Meeh Date: Sat, 1 Feb 2014 04:15:19 +0100 Subject: [PATCH 2/4] use single dash to query options --- util.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util.cpp b/util.cpp index ff013035..2da8fdb5 100644 --- a/util.cpp +++ b/util.cpp @@ -94,8 +94,8 @@ namespace filesystem static boost::filesystem::path path; - if (config::mapArgs.count("--datadir")) { - path = boost::filesystem::system_complete(config::mapArgs["--datadir"]); + if (config::mapArgs.count("-datadir")) { + path = boost::filesystem::system_complete(config::mapArgs["-datadir"]); if (!boost::filesystem::is_directory(path)) { path = ""; return path; From 2fd31c6c8d77637a828c09b2d0ac3e9ba3ccbfa6 Mon Sep 17 00:00:00 2001 From: Meeh Date: Sat, 1 Feb 2014 04:51:58 +0100 Subject: [PATCH 3/4] Custom datadir + cleanup --- i2p.cpp | 11 +---------- util.cpp | 27 +++++++++++++++++---------- util.h | 1 + 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/i2p.cpp b/i2p.cpp index 82a69671..aed38cd0 100644 --- a/i2p.cpp +++ b/i2p.cpp @@ -24,16 +24,7 @@ int main( int argc, char* argv[] ) #endif LogPrint("\n\n\n\ni2pd starting\n"); - LogPrint("default data directory: ", i2p::util::filesystem::GetDefaultDataDir().string()); - if (!boost::filesystem::exists( i2p::util::filesystem::GetDefaultDataDir() )) - { - // Create data directory - if (!boost::filesystem::create_directory( i2p::util::filesystem::GetDefaultDataDir() )) - { - LogPrint("Failed to create data directory, exiting! :("); - return -1; - } - } + LogPrint("data directory: ", i2p::util::filesystem::GetDataDir().string()); i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); //TODO: This is an ugly workaround. fix it. diff --git a/util.cpp b/util.cpp index 2da8fdb5..1c64cc75 100644 --- a/util.cpp +++ b/util.cpp @@ -89,30 +89,37 @@ namespace config namespace filesystem { - const boost::filesystem::path &GetDataDir(bool fNetSpecific) + const boost::filesystem::path &GetDataDir() { static boost::filesystem::path path; - if (config::mapArgs.count("-datadir")) { - path = boost::filesystem::system_complete(config::mapArgs["-datadir"]); - if (!boost::filesystem::is_directory(path)) { - path = ""; - return path; - } + if (i2p::util::config::mapArgs.count("-datadir")) { + path = boost::filesystem::system_complete(i2p::util::config::mapArgs["-datadir"]); } else { path = GetDefaultDataDir(); } - boost::filesystem::create_directory(path); - + if (!boost::filesystem::exists( path )) + { + // Create data directory + if (!boost::filesystem::create_directory( path )) + { + LogPrint("Failed to create data directory!"); + return ""; + } + } + if (!boost::filesystem::is_directory(path)) { + path = GetDefaultDataDir(); + } + LogPrint("Debug: ",path.string()); return path; } boost::filesystem::path GetConfigFile() { boost::filesystem::path pathConfigFile(i2p::util::config::GetArg("-conf", "i2p.conf")); - if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; + if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir() / pathConfigFile; return pathConfigFile; } diff --git a/util.h b/util.h index 7f22e3f1..7090294f 100644 --- a/util.h +++ b/util.h @@ -22,6 +22,7 @@ namespace util namespace filesystem { + const boost::filesystem::path &GetDataDir(); boost::filesystem::path GetDefaultDataDir(); boost::filesystem::path GetConfigFile(); void ReadConfigFile(std::map& mapSettingsRet, From ef9801f704ce012cdfacf00a3175dc87cc649a77 Mon Sep 17 00:00:00 2001 From: Meeh Date: Sat, 1 Feb 2014 05:25:59 +0100 Subject: [PATCH 4/4] Remove debug --- util.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/util.cpp b/util.cpp index 1c64cc75..e988427c 100644 --- a/util.cpp +++ b/util.cpp @@ -112,7 +112,6 @@ namespace filesystem if (!boost::filesystem::is_directory(path)) { path = GetDefaultDataDir(); } - LogPrint("Debug: ",path.string()); return path; }