mirror of https://github.com/PurpleI2P/i2pd.git
chertov
11 years ago
24 changed files with 1167 additions and 221 deletions
@ -1,26 +1,31 @@ |
|||||||
|
|
||||||
CC = g++ |
CC = g++ |
||||||
CFLAGS = -g -Wall -std=c++0x |
CFLAGS = -g -Wall -std=c++0x |
||||||
OBJECTS = i2p.o base64.o NTCPSession.o RouterInfo.o Transports.o RouterContext.o \
|
OBJECTS = obj/i2p.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transports.o \
|
||||||
NetDb.o LeaseSet.o Tunnel.o TunnelEndpoint.o TunnelGateway.o TransitTunnel.o \
|
obj/RouterContext.o obj/NetDb.o obj/LeaseSet.o obj/Tunnel.o obj/TunnelEndpoint.o \
|
||||||
I2NPProtocol.o Log.o Garlic.o HTTPServer.o Streaming.o Identity.o SSU.o |
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 = |
INCFLAGS = |
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem |
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread |
||||||
LIBS = |
LIBS = |
||||||
|
|
||||||
all: i2p |
all: obj i2p |
||||||
|
|
||||||
i2p: $(OBJECTS) |
i2p: $(OBJECTS:obj/%=obj/%) |
||||||
$(CC) -o i2p $(OBJECTS) $(LDFLAGS) $(LIBS) |
$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) |
||||||
|
|
||||||
.SUFFIXES: |
.SUFFIXES: |
||||||
.SUFFIXES: .c .cc .C .cpp .o |
.SUFFIXES: .c .cc .C .cpp .o |
||||||
|
|
||||||
.cpp.o : |
obj/%.o : %.cpp |
||||||
$(CC) -o $@ -c $(CFLAGS) $< $(INCFLAGS) |
$(CC) -o $@ $< -c $(CFLAGS) $(INCFLAGS) |
||||||
|
|
||||||
|
obj: |
||||||
|
mkdir -p obj |
||||||
|
|
||||||
clean: |
clean: |
||||||
rm -f *.o |
rm -fr obj i2p |
||||||
|
|
||||||
.PHONY: all |
.PHONY: all |
||||||
.PHONY: clean |
.PHONY: clean |
||||||
|
|
||||||
|
@ -0,0 +1,101 @@ |
|||||||
|
#include <iostream> |
||||||
|
#include <fstream> |
||||||
|
#include <boost/regex.hpp> |
||||||
|
#include <boost/filesystem.hpp> |
||||||
|
#include "Reseed.h" |
||||||
|
#include "Log.h" |
||||||
|
#include "util.h" |
||||||
|
|
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace data |
||||||
|
{ |
||||||
|
|
||||||
|
static std::vector<std::string> httpReseedHostList = { |
||||||
|
"http://193.150.121.66/netDb/", |
||||||
|
"http://netdb.i2p2.no/", |
||||||
|
"http://reseed.i2p-projekt.de/", |
||||||
|
"http://cowpuncher.drollette.com/netdb/", |
||||||
|
"http://i2p.mooo.com/netDb/", |
||||||
|
"http://reseed.info/", |
||||||
|
"http://reseed.pkol.de/", |
||||||
|
"http://uk.reseed.i2p2.no/", |
||||||
|
"http://i2p-netdb.innovatio.no/", |
||||||
|
"http://ieb9oopo.mooo.com" |
||||||
|
}; |
||||||
|
|
||||||
|
//TODO: Implement v2 reseeding. Lightweight zip library is needed.
|
||||||
|
//TODO: Implement SU3, utils.
|
||||||
|
Reseeder::Reseeder() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
Reseeder::~Reseeder() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
bool Reseeder::reseedNow() |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
std::string reseedHost = httpReseedHostList[(rand() % httpReseedHostList.size())]; |
||||||
|
LogPrint("Reseeding from ", reseedHost); |
||||||
|
std::string content = i2p::util::http::httpRequest(reseedHost); |
||||||
|
if (content == "") |
||||||
|
{ |
||||||
|
LogPrint("Reseed failed"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
boost::regex e("<\\s*A\\s+[^>]*href\\s*=\\s*\"([^\"]*)\"", boost::regex::normal | boost::regbase::icase); |
||||||
|
boost::sregex_token_iterator i(content.begin(), content.end(), e, 1); |
||||||
|
boost::sregex_token_iterator j; |
||||||
|
//TODO: Ugly code, try to clean up.
|
||||||
|
//TODO: Try to reduce N number of variables
|
||||||
|
std::string name; |
||||||
|
std::string routerInfo; |
||||||
|
std::string tmpUrl; |
||||||
|
std::string filename; |
||||||
|
std::string ignoreFileSuffix = ".zip"; |
||||||
|
boost::filesystem::path root = i2p::util::filesystem::GetDataDir(); |
||||||
|
while (i != j) |
||||||
|
{ |
||||||
|
name = *i++; |
||||||
|
if (name.find(ignoreFileSuffix)!=std::string::npos) |
||||||
|
continue; |
||||||
|
LogPrint("Downloading ", name); |
||||||
|
tmpUrl = reseedHost; |
||||||
|
tmpUrl.append(name); |
||||||
|
routerInfo = i2p::util::http::httpRequest(tmpUrl); |
||||||
|
if (routerInfo.size()==0) |
||||||
|
continue; |
||||||
|
filename = root.string(); |
||||||
|
#ifndef _WIN32 |
||||||
|
filename += "/netDb/r"; |
||||||
|
#else |
||||||
|
filename += "\\netDb\\r"; |
||||||
|
#endif |
||||||
|
filename += name.at(11); // first char in id
|
||||||
|
#ifndef _WIN32 |
||||||
|
filename.append("/"); |
||||||
|
#else |
||||||
|
filename.append("\\"); |
||||||
|
#endif |
||||||
|
filename.append(name.c_str()); |
||||||
|
std::ofstream outfile (filename, std::ios::binary); |
||||||
|
outfile << routerInfo; |
||||||
|
outfile.close(); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
catch (std::exception& ex) |
||||||
|
{ |
||||||
|
//TODO: error reporting
|
||||||
|
return false; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,23 @@ |
|||||||
|
#ifndef RESEED_H |
||||||
|
#define RESEED_H |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace data |
||||||
|
{ |
||||||
|
|
||||||
|
class Reseeder |
||||||
|
{ |
||||||
|
public: |
||||||
|
Reseeder(); |
||||||
|
~Reseeder(); |
||||||
|
bool reseedNow(); |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,261 @@ |
|||||||
|
#include <string> |
||||||
|
#include <algorithm> |
||||||
|
#include <cctype> |
||||||
|
#include <functional> |
||||||
|
#include <fstream> |
||||||
|
#include <set> |
||||||
|
#include <boost/asio.hpp> |
||||||
|
#include <boost/filesystem.hpp> |
||||||
|
#include <boost/filesystem/fstream.hpp> |
||||||
|
#include <boost/foreach.hpp> |
||||||
|
#include <boost/program_options/detail/config_file.hpp> |
||||||
|
#include <boost/program_options/parsers.hpp> |
||||||
|
#include "util.h" |
||||||
|
#include "Log.h" |
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace util |
||||||
|
{ |
||||||
|
|
||||||
|
namespace config |
||||||
|
{ |
||||||
|
std::map<std::string, std::string> mapArgs; |
||||||
|
std::map<std::string, std::vector<std::string> > mapMultiArgs; |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace filesystem |
||||||
|
{ |
||||||
|
const boost::filesystem::path &GetDataDir() |
||||||
|
{ |
||||||
|
static boost::filesystem::path path; |
||||||
|
|
||||||
|
if (i2p::util::config::mapArgs.count("-datadir")) { |
||||||
|
path = boost::filesystem::system_complete(i2p::util::config::mapArgs["-datadir"]); |
||||||
|
} else { |
||||||
|
path = GetDefaultDataDir(); |
||||||
|
} |
||||||
|
|
||||||
|
if (!boost::filesystem::exists( path )) |
||||||
|
{ |
||||||
|
// Create data directory
|
||||||
|
if (!boost::filesystem::create_directory( path )) |
||||||
|
{ |
||||||
|
LogPrint("Failed to create data directory!"); |
||||||
|
path = ""; |
||||||
|
return path; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!boost::filesystem::is_directory(path)) { |
||||||
|
path = GetDefaultDataDir(); |
||||||
|
} |
||||||
|
return path; |
||||||
|
} |
||||||
|
|
||||||
|
boost::filesystem::path GetConfigFile() |
||||||
|
{ |
||||||
|
boost::filesystem::path pathConfigFile(i2p::util::config::GetArg("-conf", "i2p.conf")); |
||||||
|
if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir() / pathConfigFile; |
||||||
|
return pathConfigFile; |
||||||
|
} |
||||||
|
|
||||||
|
void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, |
||||||
|
std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet) |
||||||
|
{ |
||||||
|
boost::filesystem::ifstream streamConfig(GetConfigFile()); |
||||||
|
if (!streamConfig.good()) |
||||||
|
return; // No i2pd.conf file is OK
|
||||||
|
|
||||||
|
std::set<std::string> 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 |
||||||
|
{ |
||||||
|
std::string httpRequest(const std::string& address) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
i2p::util::http::url u(address); |
||||||
|
boost::asio::ip::tcp::iostream site; |
||||||
|
// please don't uncomment following line because it's not compatible with boost 1.46
|
||||||
|
// 1.46 is default boost for Ubuntu 12.04 LTS
|
||||||
|
//site.expires_from_now (boost::posix_time::seconds(30));
|
||||||
|
site.connect(u.host_, "http"); |
||||||
|
if (site) |
||||||
|
{ |
||||||
|
// User-Agent is needed to get the server list routerInfo files.
|
||||||
|
site << "GET " << u.path_ << " HTTP/1.0\r\nHost: " << u.host_ |
||||||
|
<< "\r\nAccept: */*\r\n" << "User-Agent: Wget/1.11.4\r\n" << "Connection: close\r\n\r\n"; |
||||||
|
// read response
|
||||||
|
std::string version, statusMessage; |
||||||
|
site >> version; // HTTP version
|
||||||
|
int status; |
||||||
|
site >> status; // status
|
||||||
|
std::getline (site, statusMessage); |
||||||
|
if (status == 200) // OK
|
||||||
|
{ |
||||||
|
std::string header; |
||||||
|
while (std::getline(site, header) && header != "\r"){} |
||||||
|
std::stringstream ss; |
||||||
|
ss << site.rdbuf(); |
||||||
|
return ss.str(); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
LogPrint ("HTTP response ", status); |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
LogPrint ("Can't connect to ", address); |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
catch (std::exception& ex) |
||||||
|
{ |
||||||
|
LogPrint ("Failed to download ", address, " : ", ex.what ()); |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
url::url(const std::string& url_s) |
||||||
|
{ |
||||||
|
parse(url_s); |
||||||
|
} |
||||||
|
|
||||||
|
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<int,int>(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<int,int>(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()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // Namespace end
|
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
#ifndef UTIL_H |
||||||
|
#define UTIL_H |
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
#include <boost/filesystem.hpp> |
||||||
|
#include <boost/filesystem/fstream.hpp> |
||||||
|
|
||||||
|
#define PAIRTYPE(t1, t2) std::pair<t1, t2> |
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace util |
||||||
|
{ |
||||||
|
namespace config |
||||||
|
{ |
||||||
|
extern std::map<std::string, std::string> mapArgs; |
||||||
|
extern std::map<std::string, std::vector<std::string> > 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 |
||||||
|
{ |
||||||
|
const boost::filesystem::path &GetDataDir(); |
||||||
|
boost::filesystem::path GetDefaultDataDir(); |
||||||
|
boost::filesystem::path GetConfigFile(); |
||||||
|
void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, |
||||||
|
std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet); |
||||||
|
} |
||||||
|
|
||||||
|
namespace http |
||||||
|
{ |
||||||
|
std::string httpRequest(const std::string& address); |
||||||
|
struct url { |
||||||
|
url(const std::string& url_s); // omitted copy, ==, accessors, ...
|
||||||
|
private: |
||||||
|
void parse(const std::string& url_s); |
||||||
|
public: |
||||||
|
std::string protocol_, host_, path_, query_; |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue