aboutsummaryrefslogtreecommitdiff
path: root/web/apache/service.hxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-03-18 22:17:49 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-03-27 17:28:44 +0300
commit35359f038f571dc46de3d14af72a2bc911fb0a24 (patch)
treede3e89d678e78b9efc4d395274fd7ccc68f4a213 /web/apache/service.hxx
parent8ad672cc7211952716ffe1fbf76c179b4f1149e3 (diff)
Implement brep-monitor
Diffstat (limited to 'web/apache/service.hxx')
-rw-r--r--web/apache/service.hxx333
1 files changed, 0 insertions, 333 deletions
diff --git a/web/apache/service.hxx b/web/apache/service.hxx
deleted file mode 100644
index aaf006e..0000000
--- a/web/apache/service.hxx
+++ /dev/null
@@ -1,333 +0,0 @@
-// file : web/apache/service.hxx -*- C++ -*-
-// license : MIT; see accompanying LICENSE file
-
-#ifndef WEB_APACHE_SERVICE_HXX
-#define WEB_APACHE_SERVICE_HXX
-
-#include <apr_pools.h> // apr_pool_t
-#include <apr_hooks.h> // APR_HOOK_*
-
-#include <httpd.h> // request_rec, server_rec, HTTP_*, DECLINED
-#include <http_config.h> // module, cmd_parms, ap_hook_*()
-
-#include <map>
-#include <memory> // unique_ptr
-#include <string>
-#include <cassert>
-
-#include <web/module.hxx>
-#include <web/apache/log.hxx>
-#include <web/apache/request.hxx>
-
-namespace web
-{
- namespace apache
- {
- // Apache has 3 configuration scopes: main server, virtual server, and
- // directory (location). It provides configuration scope-aware modules
- // with the ability to build a hierarchy of configuration contexts. Later,
- // when processing a request, Apache passes the appropriate directory
- // configuration context to the request handler.
- //
- // This Apache service implementation first makes a copy of the provided
- // (in the constructor below) handler exemplar for each directory context.
- // It then initializes each of these "context exemplars" with the (merged)
- // set of configuration options. Finally, when handling a request, it
- // copies the corresponding "context exemplar" to create the "handling
- // instance". Note that the "context exemplars" are created as a copy of
- // the provided exemplar, which is never initialized. As a result, it is
- // possible to detect if the handler's copy constructor is used to create
- // a "context exemplar" or a "handling instance".
- //
- class service: ::module
- {
- public:
- // Note that the module exemplar is stored by-reference.
- //
- template <typename H>
- service (const std::string& name, H& exemplar)
- : ::module
- {
- STANDARD20_MODULE_STUFF,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- &register_hooks<H>
-
-#ifdef AP_MODULE_HAS_FLAGS
- , AP_MODULE_FLAG_NONE
-#endif
- },
- name_ (name),
- exemplar_ (exemplar)
- {
- init_directives ();
-
- // Set configuration context management hooks.
- //
- // The overall process of building the configuration hierarchy for a
- // handler is as follows:
- //
- // 1. Apache creates directory and server configuration contexts for
- // scopes containing handler-defined directives by calling the
- // create_{server,dir}_context() callback functions. For directives
- // at the server scope the special directory context is created as
- // well.
- //
- // 2. Apache calls parse_option() function for each handler-defined
- // directive. The function parses the directives and places the
- // resulting options into the corresponding configuration context.
- // It also establishes the directory-server contexts relations.
- //
- // 3. Apache calls merge_server_context() function for each virtual
- // server. The function complements virtual server context options
- // with the ones from the main server.
- //
- // 4. Apache calls config_finalizer() which complements the directory
- // contexts options with the ones from the enclosing servers.
- //
- // 5. Apache calls worker_initializer() which creates handler exemplar
- // for each directory configuration context that have
- // 'SetHandler <mod_name>' directive in effect for it.
- //
- // References:
- // http://www.apachetutor.org/dev/config
- // http://httpd.apache.org/docs/2.4/developer/modguide.html
- // http://wiki.apache.org/httpd/ModuleLife
- //
- create_server_config = &create_server_context;
- create_dir_config = &create_dir_context;
- merge_server_config = &merge_server_context<H>;
-
- // instance<H> () is invented to delegate processing from apache
- // request handler C function to the service non static member
- // function. This appoach resticts number of service objects per
- // specific handler implementation class with just one instance.
- //
- service*& srv (instance<H> ());
- assert (srv == nullptr);
- srv = this;
- }
-
- ~service ()
- {
- delete [] cmds;
- }
-
- private:
- template <typename H>
- static service*&
- instance () noexcept
- {
- static service* instance;
- return instance;
- }
-
- template <typename H>
- static void
- register_hooks (apr_pool_t*) noexcept
- {
- // The config_finalizer() function is called at the end of Apache
- // server configuration parsing.
- //
- ap_hook_post_config (&config_finalizer<H>, NULL, NULL, APR_HOOK_LAST);
-
- // The worker_initializer() function is called right after Apache
- // worker process is started. Called for every new process spawned.
- //
- ap_hook_child_init (
- &worker_initializer<H>, NULL, NULL, APR_HOOK_LAST);
-
- // The request_handler () function is called for each client request.
- //
- ap_hook_handler (&request_handler<H>, NULL, NULL, APR_HOOK_LAST);
- }
-
- template <typename H>
- static int
- config_finalizer (apr_pool_t*, apr_pool_t*, apr_pool_t*, server_rec* s)
- noexcept
- {
- instance<H> ()->finalize_config (s);
- return OK;
- }
-
- template <typename H>
- static void
- worker_initializer (apr_pool_t*, server_rec* s) noexcept
- {
- auto srv (instance<H> ());
- log l (s, srv);
- srv->template init_worker<H> (l);
- }
-
- template <typename H>
- static int
- request_handler (request_rec* r) noexcept;
-
- private:
-
- // Reflects the allowability of the request handling in the specific
- // configuration scope.
- //
- enum class request_handling
- {
- // Configuration scope has 'SetHandler <mod_name>' directive
- // specified. The handler is allowed to handle a request in the scope.
- //
- allowed,
-
- // Configuration scope has 'SetHandler <other_mod_name>|None'
- // directive specified. The handler is disallowed to handle a request
- // in the scope.
- //
- disallowed,
-
- //
- // Note that if there are several SetHandler directives specified
- // in the specific scope, then the latest one takes the precedence.
-
- // Configuration scope has no SetHandler directive specified. The
- // request handling allowability is established by the enclosing
- // scopes.
- //
- inherit
- };
-
- // Our representation of the Apache configuration context.
- //
- // The lifetime of this object is under the control of the Apache API,
- // which treats it as a raw sequence of bytes. In order not to tinker
- // with the C-style structures and APR memory pools, we will keep it a
- // (C++11) POD type with just the members required to maintain the
- // context hierarchy.
- //
- // We will then use the pointers to these context objects as keys in
- // maps to (1) the corresponding application-level option lists during
- // the configuration cycle and to (2) the corresponding handler exemplar
- // during the HTTP request handling phase. We will also use the same
- // type for both directory and server configuration contexts.
- //
- struct context
- {
- // Outer (server) configuration context for the directory
- // configuration context, NULL otherwise.
- //
- context* server = nullptr;
-
- // If module directives appear directly in the server configuration
- // scope, Apache creates a special directory context for them. This
- // context appears at the same hierarchy level as the user-defined
- // directory contexts of the same server scope.
- //
- bool special;
-
- // Request handling allowability for the corresponding configuration
- // scope.
- //
- request_handling handling = request_handling::inherit;
-
- // Create the server configuration context.
- //
- context (): special (false) {}
-
- // Create the directory configuration context. Due to the Apache API
- // implementation details it is not possible to detect the enclosing
- // server configuration context at the time of directory context
- // creation. As a result, the server member is set by the module's
- // parse_option() function.
- //
- context (bool s): special (s) {}
-
- // Ensure the object is only destroyed by Apache.
- //
- ~context () = delete;
- };
-
- static context*
- context_cast (void* config) noexcept
- {return static_cast<context*> (config);}
-
- private:
- void
- init_directives ();
-
- // Create the server configuration context. Called by the Apache API
- // whenever a new object of that type is required.
- //
- static void*
- create_server_context (apr_pool_t*, server_rec*) noexcept;
-
- // Create the server directory configuration context. Called by the
- // Apache API whenever a new object of that type is required.
- //
- static void*
- create_dir_context (apr_pool_t*, char* dir) noexcept;
-
- template <typename H>
- static void*
- merge_server_context (apr_pool_t*, void* enclosing, void* enclosed)
- noexcept
- {
- instance<H> ()->complement (
- context_cast (enclosed), context_cast (enclosing));
-
- return enclosed;
- }
-
- static const char*
- parse_option (cmd_parms* parms, void* conf, const char* args) noexcept;
-
- const char*
- add_option (context*, const char* name, optional<std::string> value);
-
- void
- finalize_config (server_rec*);
-
- void
- clear_config ();
-
- // Complement the enclosed context with options of the enclosing one.
- // If the 'handling' member of the enclosed context is set to
- // request_handling::inherit value, assign it a value from the enclosing
- // context.
- //
- void
- complement (context* enclosed, context* enclosing);
-
- template <typename H>
- void
- init_worker (log&);
-
- template <typename H>
- int
- handle (request&, const context*, log&) const;
-
- private:
- std::string name_;
- handler& exemplar_;
- option_descriptions option_descriptions_;
-
- // The context objects pointed to by the key can change during the
- // configuration phase.
- //
- using options = std::map<context*, name_values>;
- options options_;
-
- // The context objects pointed to by the key can not change during the
- // request handling phase.
- //
- using exemplars = std::map<const context*, std::unique_ptr<handler>>;
- exemplars exemplars_;
-
- bool options_parsed_ = false;
- bool version_logged_ = false;
- };
- }
-}
-
-#include <web/apache/service.txx>
-
-#endif // WEB_APACHE_SERVICE_HXX