Repository navigation
Expand file tree
/
Copy pathdaemon_lifecycle.hpp
More file actions
137 lines (116 loc) · 6.31 KB
/
Copy pathdaemon_lifecycle.hpp
File metadata and controls
137 lines (116 loc) · 6.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
This file is part of libhttpserver
Copyright (C) 2011-2026 Sebastiano Merlino
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
*/
// MHD daemon handle + start/stop state, plus the option-array and
// start-flag builders that construct the daemon. Internal header; only
// reachable when compiling libhttpserver translation units. NOT part of the
// installed surface.
#if !defined(HTTPSERVER_COMPILATION)
#error "daemon_lifecycle.hpp is internal; only reachable when compiling libhttpserver."
#endif
#ifndef SRC_HTTPSERVER_DETAIL_DAEMON_LIFECYCLE_HPP_
#define SRC_HTTPSERVER_DETAIL_DAEMON_LIFECYCLE_HPP_
#include <microhttpd.h>
#include <atomic>
#include <vector>
namespace httpserver {
class webserver;
namespace detail {
class webserver_impl;
// daemon_lifecycle -- owns the libmicrohttpd daemon handle and the
// start/stop state, and knows how to construct the daemon (the MHD
// option-array + start-flag builders).
//
// State ownership: the atomic `daemon` handle, the caller-supplied
// pre-bound `bind_socket`, and the atomic `running` flag used both for
// lock-free status reads and blocking-start wakeup.
//
// The option-array / flag builders read the const config bag and register
// the dispatch trampolines. They reach both through a back-pointer to the
// owning webserver_impl (`owner_`): owner_->parent is the webserver* whose
// config they read and which is the closure pointer for the MHD callbacks;
// owner_->ws_ tells compose_runtime_flags whether to request
// MHD_ALLOW_UPGRADE. This is the one collaborator that legitimately needs
// broad config access, hence the back-pointer (the other collaborators
// take per-call arguments instead).
//
// Members are public: webserver's start/stop/is_running/get_bound_port/
// run/... methods (webserver_lifecycle.cpp) poke the handle + flags
// directly, the same posture as webserver_impl / route_table / hook_bus.
class daemon_lifecycle {
public:
// @p bind_socket_val is the caller-supplied pre-bound socket from
// create_webserver().bind_socket(), or MHD_INVALID_SOCKET if none was
// provided. @p owner is the owning webserver_impl (never null; the
// builders reach parent config + the ws registry through it).
explicit daemon_lifecycle(webserver_impl* owner,
MHD_socket bind_socket_val = MHD_INVALID_SOCKET);
~daemon_lifecycle() = default;
daemon_lifecycle(const daemon_lifecycle&) = delete;
daemon_lifecycle& operator=(const daemon_lifecycle&) = delete;
daemon_lifecycle(daemon_lifecycle&&) = delete;
daemon_lifecycle& operator=(daemon_lifecycle&&) = delete;
// Assemble the full MHD_OptionItem array (base + TLS + GnuTLS +
// extended + HTTPS-extra options, terminated with MHD_OPTION_END).
void build_mhd_option_array(std::vector<MHD_OptionItem>& iov) const;
void add_base_mhd_options(std::vector<MHD_OptionItem>& iov) const;
void add_tls_mhd_options(std::vector<MHD_OptionItem>& iov) const;
void add_gnutls_mhd_options(std::vector<MHD_OptionItem>& iov) const;
void add_extended_mhd_options(std::vector<MHD_OptionItem>& iov) const;
void add_https_extra_options(std::vector<MHD_OptionItem>& iov) const;
// Compose the daemon start-flag bitmask (start method + transport +
// runtime flags), reading the const config bag on owner_->parent.
int compose_start_flags() const;
int compose_transport_flags() const;
int compose_runtime_flags() const;
// --- Daemon handle + start/stop state ---------------------------------
// Atomic so start() publishes the daemon pointer (and the immutable
// MHD daemon struct it points at, including the ephemeral bind port set
// before publication) with release semantics, and get_bound_port() et al.
// read it with acquire. This lets the ephemeral port be read safely from
// another thread while a blocking start() runs on a worker thread; fixes
// a TSan-flagged data race in the ws_start_stop integ test.
std::atomic<struct MHD_Daemon*> daemon{nullptr};
// Acquire-load the published daemon handle, or nullptr when the daemon
// is not currently started. Single home for the acquire-semantics
// contract documented on `daemon` above, so webserver's run/info
// accessors (webserver_lifecycle.cpp) don't each repeat the load + the
// memory_order argument.
struct MHD_Daemon* handle() const noexcept {
return daemon.load(std::memory_order_acquire);
}
// MHD_socket (int on POSIX, SOCKET on Windows) for a caller-supplied
// pre-bound socket passed via create_webserver().bind_socket().
// MHD_INVALID_SOCKET is the sentinel meaning "no pre-bound socket".
MHD_socket bind_socket = MHD_INVALID_SOCKET;
// Atomic to allow lock-free reads in stop()/is_running() concurrent with
// stop()'s store. blocking start() waits on this same atomic; its value
// check happens before waiting, so a stop that completes first cannot be
// missed. Unlike a pthread mutex/cond pair, atomic wait does not submit a
// new pthread lock object at allocator-reused storage. That matters under
// Valgrind 3.22 Helgrind: a stale rwlock record can otherwise make a valid
// mutex at a reused address look like an rwlock and fail the CI lane.
std::atomic<bool> running{false};
private:
// Back-pointer to the owning webserver_impl. Used by the builders to
// reach owner_->parent (webserver*, for config + callback cls) and
// owner_->ws_ (registry, for the MHD_ALLOW_UPGRADE decision). Never
// dereferenced during construction.
webserver_impl* owner_;
};
} // namespace detail
} // namespace httpserver
#endif // SRC_HTTPSERVER_DETAIL_DAEMON_LIFECYCLE_HPP_