From 12c45db320d9b9815adf93b31bda98f54232c35a Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 19 May 2017 10:36:16 -0400 Subject: [PATCH 11/31] FIXME: get a barebones JSON-RPC server running inside cc1 --- gcc/http-server.c | 19 ++++++++++--------- gcc/http-server.h | 10 +++++----- gcc/json.c | 9 +++++++-- gcc/lsp-main.c | 30 ++++++++++++++++++++++++++++-- gcc/testsuite/gcc.dg/lsp/test.py | 5 ++++- 5 files changed, 54 insertions(+), 19 deletions(-) diff --git a/gcc/http-server.c b/gcc/http-server.c index 3f7f7cd..74652b8 100644 --- a/gcc/http-server.c +++ b/gcc/http-server.c @@ -147,13 +147,13 @@ server::read_from_client (int filedes) else { /* Data read. */ - on_read (nbytes, buffer); + on_read (filedes, nbytes, buffer); return 0; } } void -httpish_server::on_read (size_t sz, const char *buf) +httpish_server::on_read (int fd, size_t sz, const char *buf) { if (m_verbose) fprintf (stderr, "httpish_server::on_read: `%s'\n", buf); // FIXME: respect sz @@ -168,14 +168,14 @@ httpish_server::on_read (size_t sz, const char *buf) { line_start = i + 2; // FIXME: respect the "Content-Length" header - on_content (sz - line_start, buf + line_start); + on_content (fd, sz - line_start, buf + line_start); //line_start += ; return; //break; } else { - parse_header (i - line_start, buf + line_start); + parse_header (fd, i - line_start, buf + line_start); line_start = i + 2; break; } @@ -185,12 +185,13 @@ httpish_server::on_read (size_t sz, const char *buf) } void -httpish_server::parse_header (size_t sz, const char *buf) +httpish_server::parse_header (int fd, size_t sz, const char *buf) { for (size_t colon_idx = 0; colon_idx + 1 < sz; colon_idx++) if (buf[colon_idx] == ':' && buf[colon_idx + 1] == ' ') { - on_header (colon_idx, buf, sz - (colon_idx + 2), buf + colon_idx +2); + on_header (fd, colon_idx, buf, + sz - (colon_idx + 2), buf + colon_idx +2); return; } // FIXME: error-handling @@ -210,7 +211,7 @@ class test_server : public httpish_server ~test_server () { free (m_user_agent); free (m_content); } - void on_header (size_t key_sz, const char *key, + void on_header (int fd, size_t key_sz, const char *key, size_t value_sz, const char *value) FINAL OVERRIDE { if (key_sz == strlen ("User-Agent") @@ -218,7 +219,7 @@ class test_server : public httpish_server m_user_agent = xstrndup (value, value_sz); } - void on_content (size_t sz, const char *buf) FINAL OVERRIDE + void on_content (int fd, size_t sz, const char *buf) FINAL OVERRIDE { m_content = xstrndup (buf, sz); } @@ -244,7 +245,7 @@ test_http_server () "User-Agent: test-user-agent\r\n" "\r\n" "test-content"); - s.on_read (strlen (in), in); + s.on_read (0, strlen (in), in); ASSERT_STREQ ("test-user-agent", s.m_user_agent); ASSERT_STREQ ("test-content", s.m_content); } diff --git a/gcc/http-server.h b/gcc/http-server.h index 08d27b0..2e700f5 100644 --- a/gcc/http-server.h +++ b/gcc/http-server.h @@ -28,7 +28,7 @@ class server virtual ~server () {} void serve (int port); - virtual void on_read (size_t sz, const char *buf) = 0; + virtual void on_read (int fd, size_t sz, const char *buf) = 0; private: int read_from_client (int filedes); @@ -43,14 +43,14 @@ class httpish_server : public server public: httpish_server (bool verbose) : m_verbose (verbose) {} - void on_read (size_t sz, const char *buf) OVERRIDE FINAL; + void on_read (int fd, size_t sz, const char *buf) OVERRIDE FINAL; - virtual void on_header (size_t key_sz, const char *key, + virtual void on_header (int fd, size_t key_sz, const char *key, size_t value_sz, const char *value) = 0; - virtual void on_content (size_t sz, const char *buf) = 0; + virtual void on_content (int fd, size_t sz, const char *buf) = 0; private: - void parse_header (size_t sz, const char *buf); + void parse_header (int fd, size_t sz, const char *buf); private: bool m_verbose; diff --git a/gcc/json.c b/gcc/json.c index 44044ee..f773719 100644 --- a/gcc/json.c +++ b/gcc/json.c @@ -152,7 +152,12 @@ array::print (pretty_printer *pp) const value * array::clone () const { - gcc_unreachable (); // FIXME + array *other = new array (); + unsigned i; + value *v; + FOR_EACH_VEC_ELT (m_elements, i, v) + other->append (v->clone ()); + return other; } void @@ -176,7 +181,7 @@ string::print (pretty_printer *pp) const value * string::clone () const { - gcc_unreachable (); // FIXME + return new string (m_utf8); } void diff --git a/gcc/lsp-main.c b/gcc/lsp-main.c index fd66683..7712dea 100644 --- a/gcc/lsp-main.c +++ b/gcc/lsp-main.c @@ -25,24 +25,36 @@ along with GCC; see the file COPYING3. If not see #include "json-rpc.h" #include "selftest.h" +// TODO: a filedescriptor class, to avoid naked "int" + class jsonrpc_server : public httpish_server { public: jsonrpc_server (jsonrpc::server &handler) : httpish_server (true), m_handler (handler) {} - void on_header (size_t key_sz, const char *key, + void on_header (int fd, size_t key_sz, const char *key, size_t value_sz, const char *value) OVERRIDE FINAL { fprintf (stderr, "got header: key: '%.*s' value: '%.*s'\n", (int)key_sz, key, (int)value_sz, value); } - void on_content (size_t sz, const char *buf) OVERRIDE FINAL + void on_content (int fd, size_t sz, const char *buf) OVERRIDE FINAL { fprintf (stderr, "got content: '%.*s'\n", (int)sz, buf); json::value *response = m_handler.handle_request (sz, buf); // FIXME: send the response back to the client + char *response_str = response->to_str (); + fprintf (stderr, "sending response: %s\n", response_str); + write (fd, "HTTP/1.1 200 OK\r\n", strlen ("HTTP/1.1 200 OK\r\n")); + size_t len = strlen (response_str); + char tmp[100]; + sprintf (tmp, "Content-Length: %zi\r\n", len); + write (fd, tmp, strlen (tmp)); + write (fd, "\r\n", 2); + write (fd, response_str, len); + free (response_str); } private: @@ -64,12 +76,26 @@ class test_server : public jsonrpc::server dispatch (const char *method, const json::value *params, const json::value *id) FINAL OVERRIDE { + if (0 == strcmp (method, "echo")) + return do_echo (params, id); if (0 == strcmp (method, "subtract")) return do_subtract (params, id); return make_method_not_found (id, method); } json::value * + do_echo (const json::value *params, const json::value *id) + { + const json::array *positional = params->as_array (); + if (!positional) + return make_invalid_params (id, "params was not an array"); + if (positional->get_length () != 1) + return make_invalid_params (id, "length of params was not 1"); + const json::value *arg0 = positional->get (0); + return make_success (id, arg0->clone ()); + } + + json::value * do_subtract (const json::value *params, const json::value *id) { const json::array *positional = params->as_array (); diff --git a/gcc/testsuite/gcc.dg/lsp/test.py b/gcc/testsuite/gcc.dg/lsp/test.py index 9e36bf9..5acae6b 100644 --- a/gcc/testsuite/gcc.dg/lsp/test.py +++ b/gcc/testsuite/gcc.dg/lsp/test.py @@ -19,7 +19,10 @@ def main(): "id": 0, } response = requests.post( - url, data=json.dumps(payload), headers=headers).json() + url, data=json.dumps(payload), headers=headers) + print('response: %r' % response) + response = response.json() + print('response.json(): %r' % response) assert response["result"] == "echome!" assert response["jsonrpc"] -- 1.8.5.3