From 3f314d83551fc174b8a17bd482e5b8eb84105ce5 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 22 Dec 2014 21:20:39 -0500 Subject: [PATCH] merge chunked responses --- AddressBook.cpp | 14 ++++++++++++-- AddressBook.h | 2 +- util.cpp | 39 ++++++++++++++++++++++++++++++++++++--- util.h | 2 ++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index 1b453b7d..adcd7078 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -290,7 +290,7 @@ namespace client } - void AddressBook::LoadHostsFromStream (std::istream& f, bool isChunked) + void AddressBook::LoadHostsFromStream (std::istream& f) { std::unique_lock l(m_AddressBookMutex); int numAddresses = 0; @@ -432,7 +432,17 @@ namespace client } } if (!response.eof ()) - m_Book.LoadHostsFromStream (response, isChunked); + { + if (!isChunked) + m_Book.LoadHostsFromStream (response); + else + { + // merge chunks + std::stringstream merged; + i2p::util::http::MergeChunkedResponse (response, merged); + m_Book.LoadHostsFromStream (merged); + } + } } else LogPrint (eLogWarning, "Adressbook HTTP response ", status); diff --git a/AddressBook.h b/AddressBook.h index 20234144..0ae7788f 100644 --- a/AddressBook.h +++ b/AddressBook.h @@ -44,7 +44,7 @@ namespace client void InsertAddress (const std::string& address, const std::string& base64); // for jump service void InsertAddress (const i2p::data::IdentityEx& address); - void LoadHostsFromStream (std::istream& f, bool isChunked = false); + void LoadHostsFromStream (std::istream& f); void SetIsDownloading (bool isDownloading) { m_IsDownloading = isDownloading; }; private: diff --git a/util.cpp b/util.cpp index 0a945216..cf5628f3 100644 --- a/util.cpp +++ b/util.cpp @@ -239,7 +239,7 @@ namespace 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_ + site << "GET " << u.path_ << " HTTP/1.1\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; @@ -249,10 +249,25 @@ namespace http std::getline (site, statusMessage); if (status == 200) // OK { + bool isChunked = false; std::string header; - while (std::getline(site, header) && header != "\r"){} + while (!site.eof () && header != "\r") + { + std::getline(site, header); + auto colon = header.find (':'); + if (colon != std::string::npos) + { + std::string field = header.substr (0, colon); + if (field == i2p::util::http::TRANSFER_ENCODING) + isChunked = (header.find ("chunked", colon + 1) != std::string::npos); + } + } + std::stringstream ss; - ss << site.rdbuf(); + if (isChunked) + MergeChunkedResponse (site, ss); + else + ss << site.rdbuf(); return ss.str(); } else @@ -274,6 +289,24 @@ namespace http } } + void MergeChunkedResponse (std::istream& response, std::ostream& merged) + { + while (!response.eof ()) + { + std::string hexLen; + int len; + std::getline (response, hexLen); + std::istringstream iss (hexLen); + iss >> std::hex >> len; + if (!len) break; + char * buf = new char[len]; + response.read (buf, len); + merged.write (buf, len); + delete[] buf; + std::getline (response, hexLen); // read \r\n after chunk + } + } + int httpRequestViaI2pProxy(const std::string& address, std::string &content) { content = ""; diff --git a/util.h b/util.h index 29012137..04af97ae 100644 --- a/util.h +++ b/util.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -45,6 +46,7 @@ namespace util const char TRANSFER_ENCODING[] = "Transfer-Encoding"; std::string httpRequest(const std::string& address); + void MergeChunkedResponse (std::istream& response, std::ostream& merged); int httpRequestViaI2pProxy(const std::string& address, std::string &content); // return http code struct url {