From f0ce1cdcae520b312eabff09dd9a9c1a186f4623 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 18 Feb 2019 10:40:21 -0800 Subject: [PATCH] ircd: Split up resource.h. --- include/ircd/ircd.h | 2 +- include/ircd/resource.h | 244 ------------------------------- include/ircd/resource/method.h | 75 ++++++++++ include/ircd/resource/request.h | 68 +++++++++ include/ircd/resource/resource.h | 83 +++++++++++ include/ircd/resource/response.h | 58 ++++++++ ircd/resource.cc | 16 +- 7 files changed, 298 insertions(+), 248 deletions(-) delete mode 100644 include/ircd/resource.h create mode 100644 include/ircd/resource/method.h create mode 100644 include/ircd/resource/request.h create mode 100644 include/ircd/resource/resource.h create mode 100644 include/ircd/resource/response.h diff --git a/include/ircd/ircd.h b/include/ircd/ircd.h index a7b5de085..bf3d8dfbf 100644 --- a/include/ircd/ircd.h +++ b/include/ircd/ircd.h @@ -55,7 +55,7 @@ #include "net/net.h" #include "server/server.h" #include "m/m.h" -#include "resource.h" +#include "resource/resource.h" #include "client.h" /// \brief Internet Relay Chat daemon. This is the principal namespace for IRCd. diff --git a/include/ircd/resource.h b/include/ircd/resource.h deleted file mode 100644 index 9fc9a9b42..000000000 --- a/include/ircd/resource.h +++ /dev/null @@ -1,244 +0,0 @@ -// Matrix Construct -// -// Copyright (C) Matrix Construct Developers, Authors & Contributors -// Copyright (C) 2016-2018 Jason Volk -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice is present in all copies. The -// full license for this software is available in the LICENSE file. - -#pragma once -#define HAVE_IRCD_RESOURCE_H - -namespace ircd -{ - struct client; - struct resource; -} - -/// The target of an HTTP request specified by clients with a path. -/// -struct ircd::resource -{ - IRCD_EXCEPTION(ircd::error, error) - - enum flag :uint; - struct opts; - struct method; - struct request; - struct response; - - static log::log log; - static std::map resources; - - string_view path; - std::unique_ptr opts; - std::map methods; - unique_const_iterator resources_it; - - string_view allow_methods_list(const mutable_buffer &buf) const; - - public: - method &operator[](const string_view &name) const; - - resource(const string_view &path, struct opts); - resource(const string_view &path); - resource() = default; - ~resource() noexcept; - - static resource &find(const string_view &path); -}; - -enum ircd::resource::flag -:uint -{ - DIRECTORY = 0x01, -}; - -struct ircd::resource::opts -{ - /// developer's literal description of the resource - string_view description - { - "no description" - }; - - /// flags for the resource - flag flags - { - flag(0) - }; - - /// parameter count limits (DIRECTORY only) - std::pair parc - { - 0, // minimum params - 15 // maximum params - }; -}; - -struct ircd::resource::method -{ - enum flag :uint; - struct opts; - struct stats; - using handler = std::function; - - static conf::item x_matrix_verify_origin; - static conf::item x_matrix_verify_destination; - - struct resource *resource; - string_view name; - handler function; - std::unique_ptr opts; - std::unique_ptr stats; - unique_const_iterator methods_it; - - string_view verify_origin(client &, request &) const; - string_view authenticate(client &, request &) const; - void handle_timeout(client &) const; - void call_handler(client &, request &); - - public: - void operator()(client &, const http::request::head &, const string_view &content_partial); - - method(struct resource &, const string_view &name, handler, struct opts); - method(struct resource &, const string_view &name, handler); - ~method() noexcept; -}; - -enum ircd::resource::method::flag -:uint -{ - REQUIRES_AUTH = 0x01, - RATE_LIMITED = 0x02, - VERIFY_ORIGIN = 0x04, - CONTENT_DISCRETION = 0x08, -}; - -struct ircd::resource::method::opts -{ - flag flags {(flag)0}; - - /// Timeout specific to this resource. - seconds timeout {30s}; - - /// The maximum size of the Content-Length for this method. Anything - /// larger will be summarily rejected with a 413. - size_t payload_max {128_KiB}; - - /// MIME type; first part is the Registry (i.e application) and second - /// part is the format (i.e json). Empty value means nothing rejected. - std::pair mime; -}; - -struct ircd::resource::method::stats -{ - uint64_t requests {0}; // The method was found and called. - uint64_t timeouts {0}; // The method's timeout was exceeded. - uint64_t completions {0}; // The handler returned without throwing. - uint64_t internal_errors {0}; // The handler threw a very bad exception. -}; - -struct ircd::resource::request -:json::object -{ - template struct object; - - http::request::head head; - string_view content; - http::query::string query; - string_view origin; - string_view access_token; - vector_view parv; - string_view param[8]; - m::user::id::buf user_id; - m::node::id::buf node_id; - - request(const http::request::head &head, - const string_view &content) - :json::object{content} - ,head{head} - ,content{content} - ,query{this->head.query} - {} - - request() = default; -}; - -template -struct ircd::resource::request::object -:tuple -{ - resource::request &r; - const http::request::head &head; - const string_view &content; - const http::query::string &query; - const decltype(r.origin) &origin; - const decltype(r.user_id) &user_id; - const decltype(r.node_id) &node_id; - const decltype(r.access_token) &access_token; - const vector_view &parv; - const json::object &body; - - object(resource::request &r) - :tuple{r} - ,r{r} - ,head{r.head} - ,content{r.content} - ,query{r.query} - ,origin{r.origin} - ,user_id{r.user_id} - ,node_id{r.node_id} - ,access_token{r.access_token} - ,parv{r.parv} - ,body{r} - {} -}; - -struct ircd::resource::response -{ - struct chunked; - - static const size_t HEAD_BUF_SZ; - static conf::item access_control_allow_origin; - - response(client &, const http::code &, const string_view &content_type, const size_t &content_length, const string_view &headers = {}); - response(client &, const string_view &str, const string_view &content_type, const http::code &, const vector_view &); - response(client &, const string_view &str, const string_view &content_type, const http::code & = http::OK, const string_view &headers = {}); - response(client &, const json::object &str, const http::code & = http::OK); - response(client &, const json::array &str, const http::code & = http::OK); - response(client &, const json::members & = {}, const http::code & = http::OK); - response(client &, const json::value &, const http::code & = http::OK); - response(client &, const json::iov &, const http::code & = http::OK); - response(client &, const http::code &, const json::members &); - response(client &, const http::code &, const json::value &); - response(client &, const http::code &, const json::iov &); - response(client &, const http::code &); - response() = default; -}; - -struct ircd::resource::response::chunked -:resource::response -{ - static conf::item default_buffer_size; - - client *c {nullptr}; - unique_buffer buf; - - size_t write(const const_buffer &chunk); - const_buffer flush(const const_buffer &); - bool finish(); - - std::function flusher(); - - chunked(client &, const http::code &, const string_view &content_type, const string_view &headers = {}); - chunked(client &, const http::code &, const string_view &content_type, const vector_view &); - chunked(client &, const http::code &, const vector_view &); - chunked(client &, const http::code &); - chunked(const chunked &) = delete; - chunked(chunked &&) noexcept; - chunked() = default; - ~chunked() noexcept; -}; diff --git a/include/ircd/resource/method.h b/include/ircd/resource/method.h new file mode 100644 index 000000000..17feadc62 --- /dev/null +++ b/include/ircd/resource/method.h @@ -0,0 +1,75 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_RESOURCE_METHOD_H + +struct ircd::resource::method +{ + enum flag :uint; + struct opts; + struct stats; + using handler = std::function; + + static conf::item x_matrix_verify_origin; + static conf::item x_matrix_verify_destination; + + struct resource *resource; + string_view name; + handler function; + std::unique_ptr opts; + std::unique_ptr stats; + unique_const_iterator methods_it; + + string_view verify_origin(client &, request &) const; + string_view authenticate(client &, request &) const; + void handle_timeout(client &) const; + void call_handler(client &, request &); + + public: + void operator()(client &, const http::request::head &, const string_view &content_partial); + + method(struct resource &, const string_view &name, handler, struct opts); + method(struct resource &, const string_view &name, handler); + ~method() noexcept; +}; + +enum ircd::resource::method::flag +:uint +{ + REQUIRES_AUTH = 0x01, + RATE_LIMITED = 0x02, + VERIFY_ORIGIN = 0x04, + CONTENT_DISCRETION = 0x08, +}; + +struct ircd::resource::method::opts +{ + flag flags {(flag)0}; + + /// Timeout specific to this resource. + seconds timeout {30s}; + + /// The maximum size of the Content-Length for this method. Anything + /// larger will be summarily rejected with a 413. + size_t payload_max {128_KiB}; + + /// MIME type; first part is the Registry (i.e application) and second + /// part is the format (i.e json). Empty value means nothing rejected. + std::pair mime; +}; + +struct ircd::resource::method::stats +{ + uint64_t requests {0}; // The method was found and called. + uint64_t timeouts {0}; // The method's timeout was exceeded. + uint64_t completions {0}; // The handler returned without throwing. + uint64_t internal_errors {0}; // The handler threw a very bad exception. +}; diff --git a/include/ircd/resource/request.h b/include/ircd/resource/request.h new file mode 100644 index 000000000..924361a12 --- /dev/null +++ b/include/ircd/resource/request.h @@ -0,0 +1,68 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_RESOURCE_REQUEST_H + +struct ircd::resource::request +:json::object +{ + template struct object; + + http::request::head head; + string_view content; + http::query::string query; + string_view origin; + string_view access_token; + vector_view parv; + string_view param[8]; + m::user::id::buf user_id; + m::node::id::buf node_id; + + request(const http::request::head &head, + const string_view &content) + :json::object{content} + ,head{head} + ,content{content} + ,query{this->head.query} + {} + + request() = default; +}; + +template +struct ircd::resource::request::object +:tuple +{ + resource::request &r; + const http::request::head &head; + const string_view &content; + const http::query::string &query; + const decltype(r.origin) &origin; + const decltype(r.user_id) &user_id; + const decltype(r.node_id) &node_id; + const decltype(r.access_token) &access_token; + const vector_view &parv; + const json::object &body; + + object(resource::request &r) + :tuple{r} + ,r{r} + ,head{r.head} + ,content{r.content} + ,query{r.query} + ,origin{r.origin} + ,user_id{r.user_id} + ,node_id{r.node_id} + ,access_token{r.access_token} + ,parv{r.parv} + ,body{r} + {} +}; diff --git a/include/ircd/resource/resource.h b/include/ircd/resource/resource.h new file mode 100644 index 000000000..47dcf07b6 --- /dev/null +++ b/include/ircd/resource/resource.h @@ -0,0 +1,83 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_RESOURCE_RESOURCE_H + +namespace ircd +{ + struct client; + struct resource; +} + +/// The target of an HTTP request specified by clients with a path. +/// +struct ircd::resource +{ + IRCD_EXCEPTION(ircd::error, error) + + enum flag :uint; + struct opts; + struct method; + struct request; + struct response; + + static log::log log; + static std::map resources; + + string_view path; + std::unique_ptr opts; + std::map methods; + unique_const_iterator resources_it; + + string_view allow_methods_list(const mutable_buffer &buf) const; + + public: + method &operator[](const string_view &name) const; + + resource(const string_view &path, struct opts); + resource(const string_view &path); + resource() = default; + ~resource() noexcept; + + static resource &find(const string_view &path); +}; + +#include "method.h" +#include "request.h" +#include "response.h" + +enum ircd::resource::flag +:uint +{ + DIRECTORY = 0x01, +}; + +struct ircd::resource::opts +{ + /// developer's literal description of the resource + string_view description + { + "no description" + }; + + /// flags for the resource + flag flags + { + flag(0) + }; + + /// parameter count limits (DIRECTORY only) + std::pair parc + { + 0, // minimum params + 15 // maximum params + }; +}; diff --git a/include/ircd/resource/response.h b/include/ircd/resource/response.h new file mode 100644 index 000000000..df7a7de91 --- /dev/null +++ b/include/ircd/resource/response.h @@ -0,0 +1,58 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_RESOURCE_RESPONSE_H + +struct ircd::resource::response +{ + struct chunked; + + static const size_t HEAD_BUF_SZ; + static conf::item access_control_allow_origin; + + response(client &, const http::code &, const string_view &content_type, const size_t &content_length, const string_view &headers = {}); + response(client &, const string_view &str, const string_view &content_type, const http::code &, const vector_view &); + response(client &, const string_view &str, const string_view &content_type, const http::code & = http::OK, const string_view &headers = {}); + response(client &, const json::object &str, const http::code & = http::OK); + response(client &, const json::array &str, const http::code & = http::OK); + response(client &, const json::members & = {}, const http::code & = http::OK); + response(client &, const json::value &, const http::code & = http::OK); + response(client &, const json::iov &, const http::code & = http::OK); + response(client &, const http::code &, const json::members &); + response(client &, const http::code &, const json::value &); + response(client &, const http::code &, const json::iov &); + response(client &, const http::code &); + response() = default; +}; + +struct ircd::resource::response::chunked +:resource::response +{ + static conf::item default_buffer_size; + + client *c {nullptr}; + unique_buffer buf; + + size_t write(const const_buffer &chunk); + const_buffer flush(const const_buffer &); + bool finish(); + + std::function flusher(); + + chunked(client &, const http::code &, const string_view &content_type, const string_view &headers = {}); + chunked(client &, const http::code &, const string_view &content_type, const vector_view &); + chunked(client &, const http::code &, const vector_view &); + chunked(client &, const http::code &); + chunked(const chunked &) = delete; + chunked(chunked &&) noexcept; + chunked() = default; + ~chunked() noexcept; +}; diff --git a/ircd/resource.cc b/ircd/resource.cc index cd81b7671..787494e62 100644 --- a/ircd/resource.cc +++ b/ircd/resource.cc @@ -1,7 +1,7 @@ // Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors -// Copyright (C) 2016-2018 Jason Volk +// Copyright (C) 2016-2019 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -95,7 +95,7 @@ ircd::resource::find(const string_view &path_) } // -// resource +// resource::resource // ircd::resource::resource(const string_view &path) @@ -198,8 +198,9 @@ const return { data(buf), len }; } +/////////////////////////////////////////////////////////////////////////////// // -// method::method +// resource/method.h // namespace ircd @@ -208,6 +209,10 @@ namespace ircd static void cache_warm_origin(const string_view &origin); } +// +// method::method +// + ircd::resource::method::method(struct resource &resource, const string_view &name, handler function) @@ -708,6 +713,11 @@ catch(const std::exception &e) }; } +/////////////////////////////////////////////////////////////////////////////// +// +// resource/response.h +// + // // resource::response::chunked //