Browse Source

* HTTPServer.{cpp,h}: extract html-rendering methods from class

pull/489/head
hagen 9 years ago
parent
commit
4d98a64000
  1. 316
      HTTPServer.cpp
  2. 16
      HTTPServer.h

316
HTTPServer.cpp

@ -230,100 +230,7 @@ namespace http {
{ "stats.i2p", "http://7tbay5p4kzeekxvyvbf6v7eauazemsnnl2aoyqhg5jzpr5eke7tq.b32.i2p/cgi-bin/jump.cgi?a=" }, { "stats.i2p", "http://7tbay5p4kzeekxvyvbf6v7eauazemsnnl2aoyqhg5jzpr5eke7tq.b32.i2p/cgi-bin/jump.cgi?a=" },
}; };
void HTTPConnection::Receive () void ShowStatus (std::stringstream& s)
{
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, HTTP_CONNECTION_BUFFER_SIZE),
std::bind(&HTTPConnection::HandleReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2));
}
void HTTPConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
if (ecode) {
if (ecode != boost::asio::error::operation_aborted)
Terminate (ecode);
return;
}
m_Buffer[bytes_transferred] = '\0';
m_BufferLen = bytes_transferred;
RunRequest();
Receive ();
}
void HTTPConnection::RunRequest ()
{
HTTPReq request;
int ret = request.parse(m_Buffer);
if (ret < 0) {
m_Buffer[0] = '\0';
m_BufferLen = 0;
return; /* error */
}
if (ret == 0)
return; /* need more data */
HandleRequest (request.uri);
}
void HTTPConnection::Terminate (const boost::system::error_code& ecode)
{
if (ecode == boost::asio::error::operation_aborted)
return;
boost::system::error_code ignored_ec;
m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
m_Socket->close ();
}
void HTTPConnection::HandleRequest (const std::string &uri)
{
std::stringstream s;
// Html5 head start
s <<
"<!DOCTYPE html>\r\n"
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
" <head>\r\n"
" <meta charset=\"UTF-8\">\r\n" /* TODO: Find something to parse html/template system. This is horrible. */
" <link rel='shortcut icon' href='" << itoopieFavicon << "'>\r\n"
" <title>Purple I2P " VERSION " Webconsole</title>\r\n"
<< cssStyles <<
"</head>\r\n";
s <<
"<body>\r\n"
"<div class=header><b>i2pd</b> webconsole</div>\r\n"
"<div class=wrapper>\r\n"
"<div class=left>\r\n"
" <a href=/>Main page</a><br>\r\n<br>\r\n"
" <a href=/?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << ">Local destinations</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_TUNNELS << ">Tunnels</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_TRANSIT_TUNNELS << ">Transit tunnels</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_TRANSPORTS << ">Transports</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_I2P_TUNNELS << ">I2P tunnels</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_JUMPSERVICES << "&address=example.i2p>Jump services</a><br>\r\n"
;
if (i2p::client::context.GetSAMBridge ())
s << " <a href=/?page=" << HTTP_PAGE_SAM_SESSIONS << ">SAM sessions</a><br>\r\n";
/* commands */
s << " <br>\r\n";
s << " <a href=/?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << ">Run peer test</a><br>\r\n";
if (i2p::context.AcceptsTunnels ())
s << " <a href=/?cmd=" << HTTP_COMMAND_STOP_ACCEPTING_TUNNELS << ">Stop accepting tunnels</a><br>\r\n";
else
s << " <a href=/?cmd=" << HTTP_COMMAND_START_ACCEPTING_TUNNELS << ">Start accepting tunnels</a><br>\r\n";
s << "</div>\r\n";
s << "<div class=right>";
if (uri.find("page=") != std::string::npos)
HandlePage (s, uri);
else if (uri.find("cmd=") != std::string::npos)
HandleCommand (s, uri);
else
ShowStatus (s);
s <<
"</div></div>\r\n"
"</body>\r\n"
"</html>\r\n";
SendReply (s.str ());
}
void HTTPConnection::ShowStatus (std::stringstream& s)
{ {
s << "<b>Uptime:</b> " << boost::posix_time::to_simple_string ( s << "<b>Uptime:</b> " << boost::posix_time::to_simple_string (
boost::posix_time::time_duration (boost::posix_time::seconds ( boost::posix_time::time_duration (boost::posix_time::seconds (
@ -392,59 +299,7 @@ namespace http {
s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n"; s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n";
} }
void HTTPConnection::HandlePage (std::stringstream& s, const std::string & uri) void ShowJumpServices (std::stringstream& s, const std::string& address)
{
std::map<std::string, std::string> params;
std::string page("");
URL url;
url.parse(uri);
url.parse_query(params);
page = params["page"];
if (page == HTTP_PAGE_TRANSPORTS)
ShowTransports (s);
else if (page == HTTP_PAGE_TUNNELS)
ShowTunnels (s);
else if (page == HTTP_PAGE_JUMPSERVICES)
ShowJumpServices (s, params["address"]);
else if (page == HTTP_PAGE_TRANSIT_TUNNELS)
ShowTransitTunnels (s);
else if (page == HTTP_PAGE_LOCAL_DESTINATIONS)
ShowLocalDestinations (s);
else if (page == HTTP_PAGE_LOCAL_DESTINATION)
ShowLocalDestination (s, params["b32"]);
else if (page == HTTP_PAGE_SAM_SESSIONS)
ShowSAMSessions (s);
else if (page == HTTP_PAGE_SAM_SESSION)
ShowSAMSession (s, params["sam_id"]);
else if (page == HTTP_PAGE_I2P_TUNNELS)
ShowI2PTunnels (s);
else
SendError("Unknown page: " + page);
}
void HTTPConnection::HandleCommand (std::stringstream& s, const std::string & uri)
{
std::map<std::string, std::string> params;
std::string cmd("");
URL url;
url.parse(uri);
url.parse_query(params);
cmd = params["cmd"];
if (cmd == HTTP_COMMAND_START_ACCEPTING_TUNNELS)
StartAcceptingTunnels (s);
else if (cmd == HTTP_COMMAND_STOP_ACCEPTING_TUNNELS)
StopAcceptingTunnels (s);
else if (cmd == HTTP_COMMAND_RUN_PEER_TEST)
RunPeerTest (s);
else
SendError("Unknown command: " + cmd);
}
void HTTPConnection::ShowJumpServices (std::stringstream& s, const std::string& address)
{ {
s << "<form type=\"GET\" action=\"/\">"; s << "<form type=\"GET\" action=\"/\">";
s << "<input type=\"hidden\" name=\"page\" value=\"jumpservices\">"; s << "<input type=\"hidden\" name=\"page\" value=\"jumpservices\">";
@ -458,7 +313,7 @@ namespace http {
s << "</ul>\r\n"; s << "</ul>\r\n";
} }
void HTTPConnection::ShowLocalDestinations (std::stringstream& s) void ShowLocalDestinations (std::stringstream& s)
{ {
s << "<b>Local Destinations:</b><br>\r\n<br>\r\n"; s << "<b>Local Destinations:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetDestinations ()) for (auto& it: i2p::client::context.GetDestinations ())
@ -469,7 +324,7 @@ namespace http {
} }
} }
void HTTPConnection::ShowLocalDestination (std::stringstream& s, const std::string& b32) void ShowLocalDestination (std::stringstream& s, const std::string& b32)
{ {
s << "<b>Local Destination:</b><br>\r\n<br>\r\n"; s << "<b>Local Destination:</b><br>\r\n<br>\r\n";
i2p::data::IdentHash ident; i2p::data::IdentHash ident;
@ -555,7 +410,7 @@ namespace http {
} }
} }
void HTTPConnection::ShowTunnels (std::stringstream& s) void ShowTunnels (std::stringstream& s)
{ {
s << "<b>Tunnels:</b><br>\r\n<br>\r\n"; s << "<b>Tunnels:</b><br>\r\n<br>\r\n";
s << "<b>Queue size:</b> " << i2p::tunnel::tunnels.GetQueueSize () << "<br>\r\n"; s << "<b>Queue size:</b> " << i2p::tunnel::tunnels.GetQueueSize () << "<br>\r\n";
@ -584,7 +439,7 @@ namespace http {
} }
} }
void HTTPConnection::ShowTransitTunnels (std::stringstream& s) void ShowTransitTunnels (std::stringstream& s)
{ {
s << "<b>Transit tunnels:</b><br>\r\n<br>\r\n"; s << "<b>Transit tunnels:</b><br>\r\n<br>\r\n";
for (auto it: i2p::tunnel::tunnels.GetTransitTunnels ()) for (auto it: i2p::tunnel::tunnels.GetTransitTunnels ())
@ -599,7 +454,7 @@ namespace http {
} }
} }
void HTTPConnection::ShowTransports (std::stringstream& s) void ShowTransports (std::stringstream& s)
{ {
s << "<b>Transports:</b><br>\r\n<br>\r\n"; s << "<b>Transports:</b><br>\r\n<br>\r\n";
auto ntcpServer = i2p::transport::transports.GetNTCPServer (); auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
@ -648,7 +503,7 @@ namespace http {
} }
} }
void HTTPConnection::ShowSAMSessions (std::stringstream& s) void ShowSAMSessions (std::stringstream& s)
{ {
s << "<b>SAM Sessions:</b><br>\r\n<br>\r\n"; s << "<b>SAM Sessions:</b><br>\r\n<br>\r\n";
auto sam = i2p::client::context.GetSAMBridge (); auto sam = i2p::client::context.GetSAMBridge ();
@ -662,7 +517,7 @@ namespace http {
} }
} }
void HTTPConnection::ShowSAMSession (std::stringstream& s, const std::string& id) void ShowSAMSession (std::stringstream& s, const std::string& id)
{ {
s << "<b>SAM Session:</b><br>\r\n<br>\r\n"; s << "<b>SAM Session:</b><br>\r\n<br>\r\n";
auto sam = i2p::client::context.GetSAMBridge (); auto sam = i2p::client::context.GetSAMBridge ();
@ -698,7 +553,7 @@ namespace http {
} }
} }
void HTTPConnection::ShowI2PTunnels (std::stringstream& s) void ShowI2PTunnels (std::stringstream& s)
{ {
s << "<b>Client Tunnels:</b><br>\r\n<br>\r\n"; s << "<b>Client Tunnels:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetClientTunnels ()) for (auto& it: i2p::client::context.GetClientTunnels ())
@ -721,27 +576,172 @@ namespace http {
} }
} }
void HTTPConnection::StopAcceptingTunnels (std::stringstream& s) void StopAcceptingTunnels (std::stringstream& s)
{ {
s << "<b>Stop Accepting Tunnels:</b><br>\r\n<br>\r\n"; s << "<b>Stop Accepting Tunnels:</b><br>\r\n<br>\r\n";
i2p::context.SetAcceptsTunnels (false); i2p::context.SetAcceptsTunnels (false);
s << "Accepting tunnels stopped" << std::endl; s << "Accepting tunnels stopped" << std::endl;
} }
void HTTPConnection::StartAcceptingTunnels (std::stringstream& s) void StartAcceptingTunnels (std::stringstream& s)
{ {
s << "<b>Start Accepting Tunnels:</b><br>\r\n<br>\r\n"; s << "<b>Start Accepting Tunnels:</b><br>\r\n<br>\r\n";
i2p::context.SetAcceptsTunnels (true); i2p::context.SetAcceptsTunnels (true);
s << "Accepting tunnels started" << std::endl; s << "Accepting tunnels started" << std::endl;
} }
void HTTPConnection::RunPeerTest (std::stringstream& s) void RunPeerTest (std::stringstream& s)
{ {
s << "<b>Run Peer Test:</b><br>\r\n<br>\r\n"; s << "<b>Run Peer Test:</b><br>\r\n<br>\r\n";
i2p::transport::transports.PeerTest (); i2p::transport::transports.PeerTest ();
s << "Peer test is running" << std::endl; s << "Peer test is running" << std::endl;
} }
void HTTPConnection::Receive ()
{
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, HTTP_CONNECTION_BUFFER_SIZE),
std::bind(&HTTPConnection::HandleReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2));
}
void HTTPConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
if (ecode) {
if (ecode != boost::asio::error::operation_aborted)
Terminate (ecode);
return;
}
m_Buffer[bytes_transferred] = '\0';
m_BufferLen = bytes_transferred;
RunRequest();
Receive ();
}
void HTTPConnection::RunRequest ()
{
HTTPReq request;
int ret = request.parse(m_Buffer);
if (ret < 0) {
m_Buffer[0] = '\0';
m_BufferLen = 0;
return; /* error */
}
if (ret == 0)
return; /* need more data */
HandleRequest (request.uri);
}
void HTTPConnection::Terminate (const boost::system::error_code& ecode)
{
if (ecode == boost::asio::error::operation_aborted)
return;
boost::system::error_code ignored_ec;
m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
m_Socket->close ();
}
void HTTPConnection::HandleRequest (const std::string &uri)
{
std::stringstream s;
// Html5 head start
s <<
"<!DOCTYPE html>\r\n"
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
" <head>\r\n"
" <meta charset=\"UTF-8\">\r\n" /* TODO: Find something to parse html/template system. This is horrible. */
" <link rel='shortcut icon' href='" << itoopieFavicon << "'>\r\n"
" <title>Purple I2P " VERSION " Webconsole</title>\r\n"
<< cssStyles <<
"</head>\r\n";
s <<
"<body>\r\n"
"<div class=header><b>i2pd</b> webconsole</div>\r\n"
"<div class=wrapper>\r\n"
"<div class=left>\r\n"
" <a href=/>Main page</a><br>\r\n<br>\r\n"
" <a href=/?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << ">Local destinations</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_TUNNELS << ">Tunnels</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_TRANSIT_TUNNELS << ">Transit tunnels</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_TRANSPORTS << ">Transports</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_I2P_TUNNELS << ">I2P tunnels</a><br>\r\n"
" <a href=/?page=" << HTTP_PAGE_JUMPSERVICES << "&address=example.i2p>Jump services</a><br>\r\n"
;
if (i2p::client::context.GetSAMBridge ())
s << " <a href=/?page=" << HTTP_PAGE_SAM_SESSIONS << ">SAM sessions</a><br>\r\n";
/* commands */
s << " <br>\r\n";
s << " <a href=/?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << ">Run peer test</a><br>\r\n";
if (i2p::context.AcceptsTunnels ())
s << " <a href=/?cmd=" << HTTP_COMMAND_STOP_ACCEPTING_TUNNELS << ">Stop accepting tunnels</a><br>\r\n";
else
s << " <a href=/?cmd=" << HTTP_COMMAND_START_ACCEPTING_TUNNELS << ">Start accepting tunnels</a><br>\r\n";
s << "</div>\r\n";
s << "<div class=right>";
if (uri.find("page=") != std::string::npos)
HandlePage (s, uri);
else if (uri.find("cmd=") != std::string::npos)
HandleCommand (s, uri);
else
ShowStatus (s);
s <<
"</div></div>\r\n"
"</body>\r\n"
"</html>\r\n";
SendReply (s.str ());
}
void HTTPConnection::HandlePage (std::stringstream& s, const std::string & uri)
{
std::map<std::string, std::string> params;
std::string page("");
URL url;
url.parse(uri);
url.parse_query(params);
page = params["page"];
if (page == HTTP_PAGE_TRANSPORTS)
ShowTransports (s);
else if (page == HTTP_PAGE_TUNNELS)
ShowTunnels (s);
else if (page == HTTP_PAGE_JUMPSERVICES)
ShowJumpServices (s, params["address"]);
else if (page == HTTP_PAGE_TRANSIT_TUNNELS)
ShowTransitTunnels (s);
else if (page == HTTP_PAGE_LOCAL_DESTINATIONS)
ShowLocalDestinations (s);
else if (page == HTTP_PAGE_LOCAL_DESTINATION)
ShowLocalDestination (s, params["b32"]);
else if (page == HTTP_PAGE_SAM_SESSIONS)
ShowSAMSessions (s);
else if (page == HTTP_PAGE_SAM_SESSION)
ShowSAMSession (s, params["sam_id"]);
else if (page == HTTP_PAGE_I2P_TUNNELS)
ShowI2PTunnels (s);
else
SendError("Unknown page: " + page);
}
void HTTPConnection::HandleCommand (std::stringstream& s, const std::string & uri)
{
std::map<std::string, std::string> params;
std::string cmd("");
URL url;
url.parse(uri);
url.parse_query(params);
cmd = params["cmd"];
if (cmd == HTTP_COMMAND_START_ACCEPTING_TUNNELS)
StartAcceptingTunnels (s);
else if (cmd == HTTP_COMMAND_STOP_ACCEPTING_TUNNELS)
StopAcceptingTunnels (s);
else if (cmd == HTTP_COMMAND_RUN_PEER_TEST)
RunPeerTest (s);
else
SendError("Unknown command: " + cmd);
}
void HTTPConnection::SendReply (const std::string& content, int code) void HTTPConnection::SendReply (const std::string& content, int code)
{ {
std::time_t time_now = std::time(nullptr); std::time_t time_now = std::time(nullptr);

16
HTTPServer.h

@ -29,22 +29,6 @@ namespace http {
void HandlePage (std::stringstream& s, const std::string& request); void HandlePage (std::stringstream& s, const std::string& request);
void HandleCommand (std::stringstream& s, const std::string& request); void HandleCommand (std::stringstream& s, const std::string& request);
/* pages */
void ShowJumpServices (std::stringstream& s, const std::string& address);
void ShowTransports (std::stringstream& s);
void ShowTunnels (std::stringstream& s);
void ShowStatus (std::stringstream& s);
void ShowTransitTunnels (std::stringstream& s);
void ShowLocalDestinations (std::stringstream& s);
void ShowLocalDestination (std::stringstream& s, const std::string& b32);
void ShowSAMSessions (std::stringstream& s);
void ShowSAMSession (std::stringstream& s, const std::string& id);
void ShowI2PTunnels (std::stringstream& s);
/* commands */
void StartAcceptingTunnels (std::stringstream& s);
void StopAcceptingTunnels (std::stringstream& s);
void RunPeerTest (std::stringstream& s);
private: private:
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket; std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;

Loading…
Cancel
Save