9 static const char rcsid[] __attribute__((used)) =
"$Id: httpd.cpp 1664 2016-04-04 03:57:40Z sella $";
20 #include <condition_variable>
24 #include "sella/util/Log.h"
25 #include "sella/util/String.h"
26 #include "sella/server/HTTP.h"
27 #include "sella/server/callbacks.h"
28 #include "sella/util/CommandLine.h"
29 #include "sella/net/IPAddressPort.h"
33 bool running =
true, restart =
false;
34 size_t workers = sella::server::HTTP::MinimumWorkersDefault;
35 std::string listeners =
"0.0.0.0:8080, [::]:8080";
36 std::string secureListeners =
"0.0.0.0:8443, [::]:8443";
37 std::string root = sella::server::HTTP::RootDefault();
39 std::condition_variable cv;
40 enum Mode { NonBlock, Block, Async } mode = Block;
45 using namespace sella::httpd;
46 using namespace sella::util;
47 using namespace sella::net;
48 using namespace sella::server;
50 bool init_config(
int argc,
char **argv);
51 bool init_signals(
void);
52 void sighandler(
int sig);
54 bool acl_callback(HTTPConnection::shared connection) {
58 bool authentication_callback(HTTPConnection::shared connection) {
62 bool request_callback(HTTPConnection::shared connection) {
63 const auto &r = connection->getRequest();
65 INFO(
"%s: %s - %s {%s}", r.getMethodRaw().c_str(), r.getHost().c_str(), r.getURI().c_str(), r.getUserAgent().c_str());
67 return http::request_callback(connection);
70 bool error_callback(HTTPConnection::shared connection,
int code,
const std::string &detail = std::string()) {
71 return http::error_callback(connection, code, detail);
74 int main(
int argc,
char **argv) {
76 SET_IDENTIFIER(
"httpd");
77 SET_OPTION(Log::WithStderrOption);
79 init_config(argc, argv);
82 INFO(
"Using %s v%s", libutilxx__package(), libutilxx__version());
86 http.setListeners(listeners);
87 http.setSecureListeners(secureListeners);
89 http.setCustomHeaders({
"X-Powered-By: unicorn tears",
"Age: 0" });
90 http.setAllows({ HTTPRequest::Options, HTTPRequest::Get, HTTPRequest::Head, HTTPRequest::Trace });
92 http.setCertificateFile(
"../contrib/cert.pem");
93 http.setPrivateKeyFile(
"../contrib/key.pem");
97 http.setACLCallback(acl_callback);
98 http.setAuthenticationCallback(authentication_callback);
99 http.setRequestCallback(request_callback);
100 http.setErrorCallback(error_callback);
102 if (IS_TRACE(
"print")) {
108 std::unique_lock<std::mutex> lock(mutex);
110 INFO(
"Starting up on unsecure port(s): %s", http.getListenersString().c_str());
111 INFO(
"Starting up on secure port(s): %s", http.getSecureListenersString().c_str());
115 }
else if (mode == NonBlock) {
118 INFO(
"%s - Startup complete", http.getBanner().c_str());
125 }
else if (mode == Async) {
129 INFO(
"Doing something else...");
133 WARNING(
"Guru Meditation #00000004.0000AAC0");
144 INFO(
"%s - Shutdown complete", http.getBanner().c_str());
145 }
catch (ServerException &e) {
154 bool init_config(
int argc,
char **argv) {
158 cmdln.add(
'm',
"mode",
"use MODE block, nonblock or async",
"MODE",
"block");
159 cmdln.add(
'r',
"root",
"use DIR as root directory",
"DIR", root);
160 cmdln.add(
'l',
"listeners",
"use LIST as addresses/ports to listen",
"LIST", listeners);
161 cmdln.add(
's',
"secure-listeners",
"use LIST as addresses/ports to secure listen",
"LIST", secureListeners);
162 cmdln.add(
'w',
"workers",
"use INT workers",
"INT", workers, 1, 256);
163 cmdln.add(
'd',
"debug",
"set debug level to INT",
"INT", debug, 0, 9);
165 cmdln.add(
'h',
"help",
"display this help screen");
166 cmdln.add(
'v',
"version",
"display version information");
168 std::map<std::string, std::string> conf = cmdln.parse(stdin);
170 if (conf.find(
"help") != conf.end()) {
171 printf(
"%s v%s\n", libutilxx__package(), libutilxx__version());
172 cmdln.usage(stdout, EXIT_SUCCESS);
173 }
else if (conf.find(
"version") != conf.end()) {
174 printf(
"%s v%s\n", libutilxx__package(), libutilxx__version());
179 if (conf.find(
"mode") != conf.end()) {
180 if (conf[
"mode"] ==
"block") {
182 }
else if (conf[
"mode"] ==
"nonblock") {
184 }
else if (conf[
"mode"] ==
"async") {
189 if (conf.find(
"listeners") != conf.end()) {
190 listeners = conf[
"listeners"];
193 if (conf.find(
"root") != conf.end()) {
197 if (conf.find(
"workers") != conf.end()) {
198 workers = atoi(conf[
"workers"].c_str());
201 if (conf.find(
"debug") != conf.end()) {
202 debug = atoi(conf[
"debug"].c_str());
207 SET_LOGMASK(LOG_UPTO(LOG_DEBUG));
210 SET_TRACE(PACKAGE
"-detail");
223 bool init_signals(
void) {
224 struct sigaction act, old;
226 act.sa_handler = sighandler;
227 sigemptyset(&act.sa_mask);
228 act.sa_flags = SA_RESTART;
230 if (sigaction(SIGINT, NULL, &old) < 0) {
231 fprintf(stderr,
"Failed to retrieve signal handler for SIGINT.\n");
232 }
else if (old.sa_handler == SIG_DFL) {
233 if (sigaction(SIGINT, &act, NULL) < 0) {
234 fprintf(stderr,
"Failed to install signal handler for SIGINT.\n");
238 if (sigaction(SIGTERM, NULL, &old) < 0) {
239 fprintf(stderr,
"Failed to retrieve signal handler for SIGTERM.\n");
240 }
else if (old.sa_handler == SIG_DFL) {
241 if (sigaction(SIGTERM, &act, NULL) < 0) {
242 fprintf(stderr,
"Failed to install signal handler for SIGTERM.\n");
246 if (sigaction(SIGHUP, NULL, &old) < 0) {
247 fprintf(stderr,
"Failed to retrieve signal handler for SIGHUP.\n");
248 }
else if (old.sa_handler == SIG_DFL) {
249 if (sigaction(SIGHUP, &act, NULL) < 0) {
250 fprintf(stderr,
"Failed to install signal handler for SIGHUP.\n");
254 if (sigaction(SIGUSR1, NULL, &old) < 0) {
255 fprintf(stderr,
"Failed to retrieve signal handler for SIGUSR1.\n");
256 }
else if (old.sa_handler == SIG_DFL) {
257 if (sigaction(SIGUSR1, &act, NULL) < 0) {
258 fprintf(stderr,
"Failed to install signal handler for SIGUSR1.\n");
262 if (sigaction(SIGUSR2, NULL, &old) < 0) {
263 fprintf(stderr,
"Failed to retrieve signal handler for SIGUSR2.\n");
264 }
else if (old.sa_handler == SIG_DFL) {
265 if (sigaction(SIGUSR2, &act, NULL) < 0) {
266 fprintf(stderr,
"Failed to install signal handler for SIGUSR2.\n");
270 if (sigaction(SIGPIPE, NULL, &old) < 0) {
271 fprintf(stderr,
"Failed to retrieve signal handler for SIGPIPE.\n");
272 }
else if (old.sa_handler == SIG_DFL) {
273 if (sigaction(SIGPIPE, &act, NULL) < 0) {
274 fprintf(stderr,
"Failed to install signal handler for SIGPIPE.\n");
281 void sighandler(
int sig) {