From 58c5c2f6885df65087cd3fc0be6c932f36d4bd53 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 19 May 2017 12:59:48 -0400 Subject: [PATCH 15/31] FIXME: flesh out http::request --- gcc/http-server.c | 167 ++++++++++++++++++++++++++---------------------------- gcc/http-server.h | 13 ++++- 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/gcc/http-server.c b/gcc/http-server.c index 1906500..ba5fc13 100644 --- a/gcc/http-server.c +++ b/gcc/http-server.c @@ -25,7 +25,9 @@ along with GCC; see the file COPYING3. If not see #include "selftest.h" #include "diagnostic.h" -/* class message. */ +/* class http::message. */ + +/* FIXME. */ void http::message::set_content (size_t length, const char *content) @@ -34,38 +36,37 @@ http::message::set_content (size_t length, const char *content) m_buffer = xstrndup (content, length); } -/* class request : public message. */ +/* class http::request : public http::message. */ -size_t -http::request::parse_buffer (size_t length, const char *buf) +http::request::~request() { - return 0; // FIXME + for (header_map_t::iterator it = m_header_map.begin (); + it != m_header_map.end (); ++it) + { + free (const_cast ((*it).first)); + free (const_cast ((*it).second)); + } } -/* class response : public message. */ +/* FIXME. */ -char * -http::response::to_str () const +const char * +http::request::get_header (const char *header) const { - pretty_printer pp; - pp_string (&pp, "HTTP/1.1 200 OK\r\n"); - pp_printf (&pp, "Content-Length: %i\r\n", (int)get_content_length ()); - pp_string (&pp, "\r\n"); - if (get_content ()) - pp_string (&pp, get_content ()); - return xstrdup (pp_formatted_text (&pp)); + char **slot = const_cast (this)->m_header_map.get (header); + if (slot) + return *slot; + return NULL; } -void -http::server::on_read (file_descriptor fd, size_t length, const char *buf) +/* FIXME. */ + +size_t +http::request::parse_buffer (size_t length, const char *buf) { - if (m_verbose) - inform (UNKNOWN_LOCATION, "received http request: %qs", - buf); // FIXME respect length size_t line_start = 0; while (line_start < length) { - request req; for (size_t i = line_start; i + 1 < length; i++) { if (buf[i] == '\r' && buf[i + 1] == '\n') @@ -74,79 +75,90 @@ http::server::on_read (file_descriptor fd, size_t length, const char *buf) { line_start = i + 2; // FIXME: respect the "Content-Length" header - req.set_content (length - line_start, buf + line_start); - - http::response resp; - on_request (req, resp); - - char *resp_str = resp.to_str (); - if (1) - inform (UNKNOWN_LOCATION, "sending http response: %qs", - resp_str); - write (fd.m_fd, resp_str, strlen (resp_str)); - free (resp_str); - //line_start += ; - return; - //break; + set_content (length - line_start, buf + line_start); + return line_start + get_content_length (); } else { - parse_header (fd, i - line_start, buf + line_start); + parse_header (i - line_start, buf + line_start); line_start = i + 2; break; } } } } + + return line_start; } +/* FIXME. */ + void -http::server::parse_header (file_descriptor fd, size_t length, const char *buf) +http::request::parse_header (size_t length, const char *buf) { for (size_t colon_idx = 0; colon_idx + 1 < length; colon_idx++) if (buf[colon_idx] == ':' && buf[colon_idx + 1] == ' ') { -#if 0 - on_header (fd, colon_idx, buf, - length - (colon_idx + 2), buf + colon_idx +2); -#endif + char *key = xstrndup (buf, colon_idx); + char *value = xstrndup (buf + colon_idx + 2, + length - (colon_idx + 2)); + m_header_map.put (key, value); return; } // FIXME: error-handling } -#if CHECKING_P - -namespace selftest { +/* class http::response : public http::message. */ -namespace { +/* FIXME. */ -class test_server : public http::server +char * +http::response::to_str () const { - public: - test_server () - : http::server (false), m_user_agent (NULL), m_content (NULL) {} + pretty_printer pp; + pp_string (&pp, "HTTP/1.1 200 OK\r\n"); + pp_printf (&pp, "Content-Length: %i\r\n", (int)get_content_length ()); + pp_string (&pp, "\r\n"); + if (get_content ()) + pp_string (&pp, get_content ()); + return xstrdup (pp_formatted_text (&pp)); +} - ~test_server () { free (m_user_agent); free (m_content); } +/* FIXME. */ - void on_request (const http::request &request, - http::response &response) OVERRIDE FINAL - { -#if 0 - if (key_sz == strlen ("User-Agent") - && 0 == strncmp (key, "User-Agent", key_sz)) - m_user_agent = xstrndup (value, value_sz); -#endif - } +void +http::server::on_read (file_descriptor fd, size_t length, const char *buf) +{ + if (m_verbose) + inform (UNKNOWN_LOCATION, "received http request: %qs", + buf); // FIXME respect length - char *m_user_agent; - char *m_content; -}; + /* FIXME: this assumes we have a full request i.e. two "\r\n\r\n" + If we don't we should read more until we do. */ + size_t req_start = 0; + while (req_start < length) + { + request req; + req_start += req.parse_buffer (length, buf); + http::response resp; + on_request (req, resp); + char *resp_str = resp.to_str (); + if (1) + inform (UNKNOWN_LOCATION, "sending http response: %qs", + resp_str); + write (fd.m_fd, resp_str, strlen (resp_str)); + free (resp_str); + } +} -} // anonymous namespace +#if CHECKING_P + +namespace selftest { /* Selftests. */ +/* FIXME. */ + static void test_parse_request () { @@ -160,15 +172,17 @@ test_parse_request () "\r\n" "test-content"); http::request r; -#if 0 size_t consumed = r.parse_buffer (strlen (in), in); ASSERT_EQ (consumed, strlen (in)); - //ASSERT_STREQ ("test-user-agent", r.get_header ("User-Agent")); + ASSERT_STREQ ("test-user-agent", r.get_header ("User-Agent")); + ASSERT_STREQ ("12", r.get_header ("Content-Length")); + ASSERT_EQ (NULL, r.get_header ("Not-A-Header")); ASSERT_EQ (12, r.get_content_length ()); ASSERT_TRUE (0 == strncmp ("test-content", r.get_content (), 12)); -#endif } +/* Verify http::response::to_str. */ + static void test_emit_response () { @@ -184,26 +198,6 @@ test_emit_response () free (str); } -static void -test_http_server () -{ - test_server s; - const char *in = ("POST /jsonrpc HTTP/1.1\r\n" - "Host: localhost:4000\r\n" - "Content-Length: 12\r\n" - "content-type: application/json\r\n" - "Accept-Encoding: gzip, deflate, compress\r\n" - "Accept: */*\r\n" - "User-Agent: test-user-agent\r\n" - "\r\n" - "test-content"); - s.on_read (file_descriptor (2), strlen (in), in); -#if 0 - ASSERT_STREQ ("test-user-agent", s.m_user_agent); - ASSERT_STREQ ("test-content", s.m_content); -#endif -} - /* Run all of the selftests within this file. */ void @@ -211,7 +205,6 @@ http_server_c_tests () { test_parse_request (); test_emit_response (); - test_http_server (); } } // namespace selftest diff --git a/gcc/http-server.h b/gcc/http-server.h index 4983a42..8a28ce8 100644 --- a/gcc/http-server.h +++ b/gcc/http-server.h @@ -43,7 +43,17 @@ class message class request : public message { public: + ~request(); + + const char *get_header (const char *header) const; size_t parse_buffer (size_t length, const char *buf); + + private: + void parse_header (size_t sz, const char *buf); + + typedef hash_map > header_map_t; + header_map_t m_header_map; }; class response : public message @@ -68,9 +78,6 @@ class server : public ::server http::response &response) = 0; private: - void parse_header (file_descriptor fd, size_t sz, const char *buf); - - private: bool m_verbose; }; -- 1.8.5.3