Commit 99c02ffe authored by William Sobel's avatar William Sobel

Added the output stream and protocol support in the http server. This allows the…

Added the output stream and protocol support in the http server. This allows the server to handle pass the request type and handle streaming connections as well. Added a read_with_limit method that makes the server secure against attackes with buffer overflow and the like.
parent 187f0fef
...@@ -71,6 +71,7 @@ namespace dlib ...@@ -71,6 +71,7 @@ namespace dlib
std::string path; std::string path;
std::string request_type; std::string request_type;
std::string content_type; std::string content_type;
std::string protocol;
std::string body; std::string body;
key_value_map queries; key_value_map queries;
...@@ -91,6 +92,7 @@ namespace dlib ...@@ -91,6 +92,7 @@ namespace dlib
key_value_map headers; key_value_map headers;
unsigned short http_return; unsigned short http_return;
std::string http_return_status; std::string http_return_status;
std::ostream *out;
}; };
...@@ -203,7 +205,29 @@ namespace dlib ...@@ -203,7 +205,29 @@ namespace dlib
sin >> word; sin >> word;
} }
} }
bool read_with_limit(std::istream& in, const size_t max, char *buffer, int delim = '\n')
{
using namespace std;
in.get(buffer, max, delim);
buffer[max] = '\0';
// Make sure the last char is the delim.
if (in.get() != delim) {
in.setstate(ios::badbit);
buffer[0] = '\0';
return false;
} else {
// Read the remaining delimiters
if (delim == ' ') {
while (in.peek() == ' ')
in.get();
}
return true;
}
}
void on_connect ( void on_connect (
std::istream& in, std::istream& in,
std::ostream& out, std::ostream& out,
...@@ -215,11 +239,16 @@ namespace dlib ...@@ -215,11 +239,16 @@ namespace dlib
) )
{ {
bool my_fault = true; bool my_fault = true;
const size_t max_buffer_length = 16 * 1024;
const size_t max_line_length = max_buffer_length - 1;
const size_t max_content_length = 1024 * 1024;
using namespace std; using namespace std;
try try
{ {
char buffer[max_buffer_length];
incoming_things incoming; incoming_things incoming;
outgoing_things outgoing; outgoing_things outgoing;
...@@ -228,10 +257,16 @@ namespace dlib ...@@ -228,10 +257,16 @@ namespace dlib
incoming.local_ip = local_ip; incoming.local_ip = local_ip;
incoming.local_port = local_port; incoming.local_port = local_port;
in >> incoming.request_type; read_with_limit(in, 16, buffer, ' ');
incoming.request_type = buffer;
// get the path // get the path
in >> incoming.path; read_with_limit(in, max_line_length, buffer, ' ');
incoming.path = buffer;
// Get the HTTP/1.1 - Ignore for now...
read_with_limit(in, 16, buffer);
incoming.protocol = buffer;
key_value_map& incoming_headers = incoming.headers; key_value_map& incoming_headers = incoming.headers;
key_value_map& cookies = incoming.cookies; key_value_map& cookies = incoming.cookies;
...@@ -240,7 +275,8 @@ namespace dlib ...@@ -240,7 +275,8 @@ namespace dlib
unsigned long content_length = 0; unsigned long content_length = 0;
string line; string line;
getline(in,line); read_with_limit(in, max_line_length, buffer);
line = buffer;
string first_part_of_header; string first_part_of_header;
string::size_type position_of_double_point; string::size_type position_of_double_point;
// now loop over all the incoming_headers // now loop over all the incoming_headers
...@@ -320,12 +356,19 @@ namespace dlib ...@@ -320,12 +356,19 @@ namespace dlib
} }
} }
} // no ':' in it! } // no ':' in it!
getline(in,line); if (!read_with_limit(in, max_line_length, buffer))
break;
line = buffer;
} // while (line.size() > 2 ) } // while (line.size() > 2 )
// If there is data being posted back to us then load it into the incoming.body // If there is data being posted back to us then load it into the incoming.body
// string. // string.
if ( content_length > 0 ) if (content_length > max_content_length)
{
dlog << LERROR << "Request from: " << foreign_ip << " - body content length " << content_length << " exceeded max content length of " << max_content_length;
in.setstate(ios::badbit);
}
else if ( content_length > 0)
{ {
incoming.body.resize(content_length); incoming.body.resize(content_length);
in.read(&incoming.body[0],content_length); in.read(&incoming.body[0],content_length);
...@@ -333,7 +376,8 @@ namespace dlib ...@@ -333,7 +376,8 @@ namespace dlib
// If there is data being posted back to us as a query string then // If there is data being posted back to us as a query string then
// pick out the queries using parse_url. // pick out the queries using parse_url.
if (strings_equal_ignore_case(incoming.request_type, "POST") && if ((strings_equal_ignore_case(incoming.request_type, "POST") ||
strings_equal_ignore_case(incoming.request_type, "PUT")) &&
strings_equal_ignore_case(left_substr(content_type,";"), "application/x-www-form-urlencoded")) strings_equal_ignore_case(left_substr(content_type,";"), "application/x-www-form-urlencoded"))
{ {
parse_url(incoming.body, incoming.queries); parse_url(incoming.body, incoming.queries);
...@@ -353,12 +397,18 @@ namespace dlib ...@@ -353,12 +397,18 @@ namespace dlib
// Set some defaults // Set some defaults
outgoing.http_return = 200; outgoing.http_return = 200;
outgoing.http_return_status = "OK"; outgoing.http_return_status = "OK";
outgoing.out = &out;
// if there wasn't a problem with the input stream at some point // if there wasn't a problem with the input stream at some point
// then lets trigger this request callback. // then lets trigger this request callback.
std::string result; std::string result;
if (in) if (in)
result = on_request(incoming, outgoing); result = on_request(incoming, outgoing);
else {
dlog << LERROR << "Request from: " << foreign_ip << " - Invalid request - Request Entity Too Large";
outgoing.http_return = 413;
outgoing.http_return_status = "Request Entity Too Large";
}
my_fault = true; my_fault = true;
// only send this header if the user hasn't told us to send another kind // only send this header if the user hasn't told us to send another kind
......
...@@ -95,6 +95,7 @@ namespace dlib ...@@ -95,6 +95,7 @@ namespace dlib
std::string path; std::string path;
std::string request_type; std::string request_type;
std::string content_type; std::string content_type;
std::string protocol;
std::string body; std::string body;
key_value_map queries; key_value_map queries;
...@@ -113,6 +114,7 @@ namespace dlib ...@@ -113,6 +114,7 @@ namespace dlib
key_value_map headers; key_value_map headers;
unsigned short http_return; unsigned short http_return;
std::string http_return_status; std::string http_return_status;
std::ostream *out;
}; };
private: private:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment