Browse Source

* I2PControl.cpp :

* use new http classes for parsing request
  * implement correct reading rest of json data if HTTP/Content-length is used
  * general cleanup
pull/503/head
hagen 9 years ago
parent
commit
0ab5f993c7
  1. 69
      I2PControl.cpp

69
I2PControl.cpp

@ -191,56 +191,55 @@ namespace client
} else { } else {
try try
{ {
bool isHtml = !memcmp (buf->data (), "POST", 4); std::stringstream json;
std::string content; std::string response;
std::stringstream ss; bool isHTTP = false;
ss.write (buf->data (), bytes_transferred); if (memcmp (buf->data (), "POST", 4) == 0) {
if (isHtml) long int remains = 0;
{ isHTTP = true;
std::string header; i2p::http::HTTPReq req;
size_t contentLength = 0; std::size_t len = req.parse(buf->data(), bytes_transferred);
while (!ss.eof () && header != "\r") if (len <= 0) {
{ LogPrint(eLogError, "I2PControl: incomplete/malformed POST request");
std::getline(ss, header); return;
auto colon = header.find (':');
if (colon != std::string::npos && header.substr (0, colon) == "Content-Length")
contentLength = std::stoi (header.substr (colon + 1));
}
if (ss.eof ())
{
LogPrint (eLogError, "I2PControl: malformed request, HTTP header expected");
return; // TODO:
} }
std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read /* append to json chunk of data from 1st request */
if (rem > 0) json.write(buf->begin() + len, bytes_transferred - len);
{ remains = req.length() - len;
bytes_transferred = boost::asio::read (*socket, boost::asio::buffer (buf->data (), rem)); /* if request has Content-Length header, fetch rest of data and store to json buffer */
ss.write (buf->data (), bytes_transferred); while (remains > 0) {
len = ((long int) buf->size() < remains) ? buf->size() : remains;
bytes_transferred = boost::asio::read (*socket, boost::asio::buffer (buf->data (), len));
json.write(buf->begin(), bytes_transferred);
remains -= bytes_transferred;
} }
} else {
json.write(buf->begin(), bytes_transferred);
} }
std::ostringstream response; LogPrint(eLogDebug, "I2PControl: json from request: ", json.str());
#if GCC47_BOOST149 #if GCC47_BOOST149
LogPrint (eLogError, "I2PControl: json_read is not supported due bug in boost 1.49 with gcc 4.7"); LogPrint (eLogError, "I2PControl: json_read is not supported due bug in boost 1.49 with gcc 4.7");
BuildErrorResponse(content, 32603, "JSON requests is not supported with this version of boost"); BuildErrorResponse(response, 32603, "JSON requests is not supported with this version of boost");
#else #else
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
boost::property_tree::read_json (ss, pt); boost::property_tree::read_json (json, pt);
std::string id = pt.get<std::string>("id"); std::string id = pt.get<std::string>("id");
std::string method = pt.get<std::string>("method"); std::string method = pt.get<std::string>("method");
auto it = m_MethodHandlers.find (method); auto it = m_MethodHandlers.find (method);
if (it != m_MethodHandlers.end ()) if (it != m_MethodHandlers.end ())
{ {
response << "{\"id\":" << id << ",\"result\":{"; std::ostringstream ss;
(this->*(it->second))(pt.get_child ("params"), response); ss << "{\"id\":" << id << ",\"result\":{";
response << "},\"jsonrpc\":\"2.0\"}"; (this->*(it->second))(pt.get_child ("params"), ss);
content = response.str(); ss << "},\"jsonrpc\":\"2.0\"}";
response = ss.str();
} else { } else {
LogPrint (eLogWarning, "I2PControl: unknown method ", method); LogPrint (eLogWarning, "I2PControl: unknown method ", method);
BuildErrorResponse(content, 32601, "Method not found"); BuildErrorResponse(response, 32601, "Method not found");
} }
#endif #endif
SendResponse (socket, buf, content, isHtml); SendResponse (socket, buf, response, isHTTP);
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
@ -282,9 +281,9 @@ namespace client
} }
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket, void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
std::shared_ptr<I2PControlBuffer> buf, std::string& content, bool isHtml) std::shared_ptr<I2PControlBuffer> buf, std::string& content, bool isHTTP)
{ {
if (isHtml) { if (isHTTP) {
i2p::http::HTTPRes res; i2p::http::HTTPRes res;
res.code = 200; res.code = 200;
res.add_header("Content-Type", "application/json"); res.add_header("Content-Type", "application/json");

Loading…
Cancel
Save