mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 21:37:17 +01:00
support reseed throught the Yggdrasil
This commit is contained in:
parent
ed4c00e4f4
commit
d13fbe5549
|
@ -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");
|
||||||
|
|
|
@ -111,7 +111,14 @@ namespace http {
|
||||||
pos_p = pos_c + 1;
|
pos_p = pos_c + 1;
|
||||||
}
|
}
|
||||||
/* hostname[:port][/path] */
|
/* hostname[:port][/path] */
|
||||||
pos_c = url.find_first_of(":/", pos_p);
|
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);
|
||||||
if (pos_c == std::string::npos) {
|
if (pos_c == std::string::npos) {
|
||||||
/* only hostname, without post and path */
|
/* only hostname, without post and path */
|
||||||
host = url.substr(pos_p, std::string::npos);
|
host = url.substr(pos_p, std::string::npos);
|
||||||
|
|
|
@ -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,42 +678,7 @@ namespace data
|
||||||
if (!ecode)
|
if (!ecode)
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port);
|
LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port);
|
||||||
i2p::http::HTTPReq req;
|
return ReseedRequest (s, url.to_string());
|
||||||
req.uri = url.to_string();
|
|
||||||
req.AddHeader("User-Agent", "Wget/1.11.4");
|
|
||||||
req.AddHeader("Connection", "close");
|
|
||||||
s.write_some (boost::asio::buffer (req.to_string()));
|
|
||||||
// read response
|
|
||||||
std::stringstream rs;
|
|
||||||
char recv_buf[1024]; size_t l = 0;
|
|
||||||
do {
|
|
||||||
l = s.read_some (boost::asio::buffer (recv_buf, sizeof(recv_buf)), ecode);
|
|
||||||
if (l) rs.write (recv_buf, l);
|
|
||||||
} while (!ecode && l);
|
|
||||||
// process response
|
|
||||||
std::string data = rs.str();
|
|
||||||
i2p::http::HTTPRes res;
|
|
||||||
int len = res.parse(data);
|
|
||||||
if (len <= 0) {
|
|
||||||
LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", url.host);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (res.code != 200) {
|
|
||||||
LogPrint(eLogError, "Reseed: failed to reseed from ", url.host, ", http code ", res.code);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
data.erase(0, len); /* drop http headers from response */
|
|
||||||
LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", url.host);
|
|
||||||
if (res.is_chunked()) {
|
|
||||||
std::stringstream in(data), out;
|
|
||||||
if (!i2p::http::MergeChunkedResponse(in, out)) {
|
|
||||||
LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", url.host);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", url.host);
|
|
||||||
data = out.str();
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Reseed: SSL handshake failed: ", ecode.message ());
|
LogPrint (eLogError, "Reseed: SSL handshake failed: ", ecode.message ());
|
||||||
|
@ -711,5 +687,74 @@ namespace data
|
||||||
LogPrint (eLogError, "Reseed: Couldn't connect to ", url.host, ": ", ecode.message ());
|
LogPrint (eLogError, "Reseed: Couldn't connect to ", url.host, ": ", ecode.message ());
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Stream>
|
||||||
|
std::string Reseeder::ReseedRequest (Stream& s, const std::string& uri)
|
||||||
|
{
|
||||||
|
boost::system::error_code ecode;
|
||||||
|
i2p::http::HTTPReq req;
|
||||||
|
req.uri = uri;
|
||||||
|
req.AddHeader("User-Agent", "Wget/1.11.4");
|
||||||
|
req.AddHeader("Connection", "close");
|
||||||
|
s.write_some (boost::asio::buffer (req.to_string()));
|
||||||
|
// read response
|
||||||
|
std::stringstream rs;
|
||||||
|
char recv_buf[1024]; size_t l = 0;
|
||||||
|
do {
|
||||||
|
l = s.read_some (boost::asio::buffer (recv_buf, sizeof(recv_buf)), ecode);
|
||||||
|
if (l) rs.write (recv_buf, l);
|
||||||
|
} while (!ecode && l);
|
||||||
|
// process response
|
||||||
|
std::string data = rs.str();
|
||||||
|
i2p::http::HTTPRes res;
|
||||||
|
int len = res.parse(data);
|
||||||
|
if (len <= 0) {
|
||||||
|
LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", uri);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (res.code != 200) {
|
||||||
|
LogPrint(eLogError, "Reseed: failed to reseed from ", uri, ", http code ", res.code);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
data.erase(0, len); /* drop http headers from response */
|
||||||
|
LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", uri);
|
||||||
|
if (res.is_chunked()) {
|
||||||
|
std::stringstream in(data), out;
|
||||||
|
if (!i2p::http::MergeChunkedResponse(in, out)) {
|
||||||
|
LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", uri);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", uri);
|
||||||
|
data = out.str();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
LogPrint (eLogError, "Reseed: Couldn't connect to yggdrasil ", url.host, ": ", ecode.message ());
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,7 +47,10 @@ 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:
|
||||||
|
|
||||||
std::map<std::string, PublicKey> m_SigningKeys;
|
std::map<std::string, PublicKey> m_SigningKeys;
|
||||||
|
|
Loading…
Reference in a new issue