Browse Source

support reseed throught the Yggdrasil

pull/1626/head
orignal 4 years ago
parent
commit
d13fbe5549
  1. 3
      libi2pd/Config.cpp
  2. 7
      libi2pd/HTTP.cpp
  3. 75
      libi2pd/Reseed.cpp
  4. 5
      libi2pd/Reseed.h

3
libi2pd/Config.cpp

@ -205,6 +205,9 @@ namespace config {
"https://reseed.i2pgit.org/," "https://reseed.i2pgit.org/,"
"https://i2p.novg.net/" "https://i2p.novg.net/"
), "Reseed URLs, separated by comma") ), "Reseed URLs, separated by comma")
("reseed.yggurls", value<std::string>()->default_value(
"http://[324:9de3:fea4:f6ac::ace]:7070/"
), "Reseed URLs through the Yggdrasil, separated by comma")
; ;
options_description addressbook("AddressBook options"); options_description addressbook("AddressBook options");

7
libi2pd/HTTP.cpp

@ -111,6 +111,13 @@ namespace http {
pos_p = pos_c + 1; pos_p = pos_c + 1;
} }
/* hostname[:port][/path] */ /* hostname[:port][/path] */
if (url[pos_p] == '[') // ipv6
{
auto pos_b = url.find(']', pos_p);
if (pos_b == std::string::npos) return false;
pos_c = url.find_first_of(":/", pos_b);
}
else
pos_c = url.find_first_of(":/", pos_p); pos_c = url.find_first_of(":/", pos_p);
if (pos_c == std::string::npos) { if (pos_c == std::string::npos) {
/* only hostname, without post and path */ /* only hostname, without post and path */

75
libi2pd/Reseed.cpp

@ -86,7 +86,15 @@ namespace data
std::vector<std::string> httpsReseedHostList; std::vector<std::string> httpsReseedHostList;
boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on); boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on);
if (reseedURLs.length () == 0) std::vector<std::string> yggReseedHostList;
if (!i2p::util::net::GetYggdrasilAddress ().is_unspecified ())
{
LogPrint (eLogInfo, "Reseed: yggdrasil is supported");
std::string yggReseedURLs; i2p::config::GetOption("reseed.yggurls", yggReseedURLs);
boost::split(yggReseedHostList, yggReseedURLs, boost::is_any_of(","), boost::token_compress_on);
}
if (httpsReseedHostList.empty () && yggReseedHostList.empty())
{ {
LogPrint (eLogWarning, "Reseed: No reseed servers specified"); LogPrint (eLogWarning, "Reseed: No reseed servers specified");
return 0; return 0;
@ -95,9 +103,12 @@ namespace data
int reseedRetries = 0; int reseedRetries = 0;
while (reseedRetries < 10) while (reseedRetries < 10)
{ {
auto ind = rand () % httpsReseedHostList.size (); auto ind = rand () % (httpsReseedHostList.size () + yggReseedHostList.size ());
std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3"; bool isHttps = ind < httpsReseedHostList.size ();
auto num = ReseedFromSU3Url (reseedUrl); std::string reseedUrl = isHttps ? httpsReseedHostList[ind] :
yggReseedHostList[ind - httpsReseedHostList.size ()];
reseedUrl += "i2pseeds.su3";
auto num = ReseedFromSU3Url (reseedUrl, isHttps);
if (num > 0) return num; // success if (num > 0) return num; // success
reseedRetries++; reseedRetries++;
} }
@ -110,10 +121,10 @@ namespace data
* @param url * @param url
* @return number of entries added to netDb * @return number of entries added to netDb
*/ */
int Reseeder::ReseedFromSU3Url (const std::string& url) int Reseeder::ReseedFromSU3Url (const std::string& url, bool isHttps)
{ {
LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url); LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url);
std::string su3 = HttpsRequest (url); std::string su3 = isHttps ? HttpsRequest (url) : YggdrasilRequest (url);
if (su3.length () > 0) if (su3.length () > 0)
{ {
std::stringstream s(su3); std::stringstream s(su3);
@ -667,8 +678,22 @@ namespace data
if (!ecode) if (!ecode)
{ {
LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port); LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port);
return ReseedRequest (s, url.to_string());
}
else
LogPrint (eLogError, "Reseed: SSL handshake failed: ", ecode.message ());
}
else
LogPrint (eLogError, "Reseed: Couldn't connect to ", url.host, ": ", ecode.message ());
return "";
}
template<typename Stream>
std::string Reseeder::ReseedRequest (Stream& s, const std::string& uri)
{
boost::system::error_code ecode;
i2p::http::HTTPReq req; i2p::http::HTTPReq req;
req.uri = url.to_string(); req.uri = uri;
req.AddHeader("User-Agent", "Wget/1.11.4"); req.AddHeader("User-Agent", "Wget/1.11.4");
req.AddHeader("Connection", "close"); req.AddHeader("Connection", "close");
s.write_some (boost::asio::buffer (req.to_string())); s.write_some (boost::asio::buffer (req.to_string()));
@ -684,31 +709,51 @@ namespace data
i2p::http::HTTPRes res; i2p::http::HTTPRes res;
int len = res.parse(data); int len = res.parse(data);
if (len <= 0) { if (len <= 0) {
LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", url.host); LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", uri);
return ""; return "";
} }
if (res.code != 200) { if (res.code != 200) {
LogPrint(eLogError, "Reseed: failed to reseed from ", url.host, ", http code ", res.code); LogPrint(eLogError, "Reseed: failed to reseed from ", uri, ", http code ", res.code);
return ""; return "";
} }
data.erase(0, len); /* drop http headers from response */ data.erase(0, len); /* drop http headers from response */
LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", url.host); LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", uri);
if (res.is_chunked()) { if (res.is_chunked()) {
std::stringstream in(data), out; std::stringstream in(data), out;
if (!i2p::http::MergeChunkedResponse(in, out)) { if (!i2p::http::MergeChunkedResponse(in, out)) {
LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", url.host); LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", uri);
return ""; return "";
} }
LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", url.host); LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", uri);
data = out.str(); data = out.str();
} }
return data; return data;
} }
else
LogPrint (eLogError, "Reseed: SSL handshake failed: ", ecode.message ()); std::string Reseeder::YggdrasilRequest (const std::string& address)
{
i2p::http::URL url;
if (!url.parse(address))
{
LogPrint(eLogError, "Reseed: failed to parse url: ", address);
return "";
}
url.schema = "http";
if (!url.port) url.port = 80;
boost::system::error_code ecode;
boost::asio::io_service service;
boost::asio::ip::tcp::socket s(service, boost::asio::ip::tcp::v6());
s.connect (boost::asio::ip::tcp::endpoint (boost::asio::ip::address_v6::from_string (url.host), url.port), ecode);
if (!ecode)
{
LogPrint (eLogDebug, "Reseed: Connected to yggdrasil ", url.host, ":", url.port);
return ReseedRequest (s, url.to_string());
} }
else else
LogPrint (eLogError, "Reseed: Couldn't connect to ", url.host, ": ", ecode.message ()); LogPrint (eLogError, "Reseed: Couldn't connect to yggdrasil ", url.host, ": ", ecode.message ());
return ""; return "";
} }
} }

5
libi2pd/Reseed.h

@ -31,7 +31,6 @@ namespace data
~Reseeder(); ~Reseeder();
void Bootstrap (); void Bootstrap ();
int ReseedFromServers (); int ReseedFromServers ();
int ReseedFromSU3Url (const std::string& url);
int ProcessSU3File (const char * filename); int ProcessSU3File (const char * filename);
int ProcessZIPFile (const char * filename); int ProcessZIPFile (const char * filename);
@ -39,6 +38,7 @@ namespace data
private: private:
int ReseedFromSU3Url (const std::string& url, bool isHttps = true);
void LoadCertificate (const std::string& filename); void LoadCertificate (const std::string& filename);
int ProcessSU3Stream (std::istream& s); int ProcessSU3Stream (std::istream& s);
@ -47,6 +47,9 @@ namespace data
bool FindZipDataDescriptor (std::istream& s); bool FindZipDataDescriptor (std::istream& s);
std::string HttpsRequest (const std::string& address); std::string HttpsRequest (const std::string& address);
std::string YggdrasilRequest (const std::string& address);
template<typename Stream>
std::string ReseedRequest (Stream& s, const std::string& uri);
private: private:

Loading…
Cancel
Save