summaryrefslogtreecommitdiff
path: root/server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'server.cpp')
-rw-r--r--server.cpp99
1 files changed, 82 insertions, 17 deletions
diff --git a/server.cpp b/server.cpp
index a454b68..4ad0a3f 100644
--- a/server.cpp
+++ b/server.cpp
@@ -1,8 +1,15 @@
1// Standard C++ 1// Standard C++
2#include <atomic> 2#include <atomic>
3#include <cerrno>
3#include <csignal> 4#include <csignal>
4#include <cstdlib> 5#include <cstdlib>
6#include <cstring>
7#include <exception>
5#include <iostream> 8#include <iostream>
9#include <sstream>
10#include <string>
11#include <string_view>
12#include <utility>
6 13
7// FastCGI 14// FastCGI
8#include <fcgiapp.h> 15#include <fcgiapp.h>
@@ -10,10 +17,14 @@
10using namespace std; 17using namespace std;
11 18
12namespace { 19namespace {
13static atomic_bool quit; 20struct Configuration {
14static atomic_bool reload; 21 int value;
22};
15 23
16static void 24atomic_bool quit{ false };
25atomic_bool reload{ false };
26
27void
17handler(int signal) 28handler(int signal)
18{ 29{
19 if ( signal == SIGINT || signal == SIGTERM ) { 30 if ( signal == SIGINT || signal == SIGTERM ) {
@@ -24,7 +35,7 @@ handler(int signal)
24 } 35 }
25} 36}
26 37
27static void 38void
28init_signal_handler() 39init_signal_handler()
29{ 40{
30 struct sigaction sa; 41 struct sigaction sa;
@@ -36,19 +47,48 @@ init_signal_handler()
36 sigaction(SIGINT, &sa, NULL); 47 sigaction(SIGINT, &sa, NULL);
37 sigaction(SIGTERM, &sa, NULL); 48 sigaction(SIGTERM, &sa, NULL);
38 sigaction(SIGHUP, &sa, NULL); 49 sigaction(SIGHUP, &sa, NULL);
50
51 signal(SIGPIPE, SIG_IGN);
39} 52}
40 53
41static void 54bool
42load_configuration() 55load_configuration(Configuration& configuration)
43{ 56{
44 cerr << "Load configuration ...\n"; 57 cerr << "Load configuration ...\n";
58 configuration.value = 1;
59 return true;
60}
61
62void
63handle_request(char** env, const Configuration&, string_view body, ostream& out)
64{
65 const char* methode = FCGX_GetParam("REQUEST_METHOD", env);
66
67 out << "Content-Type: text/html; charset=utf-8\r\n\r\n";
68 out << "<h1>Verbindung erfolgreich verarbeitet!</h1>";
69 out << "<p>Methode: " << (methode ? methode : "?") << ", Body: " << body.size() << " Bytes</p>";
45} 70}
46 71
47static void 72void
48handle_request(const FCGX_Request& request) 73send_internal_error(const FCGX_Request& request)
49{ 74{
50 FCGX_FPrintF(request.out, "Content-type: text/html\r\n\r\n"); 75 FCGX_FPrintF(request.out, "Status: 500 Internal Server Error\r\n");
51 FCGX_FPrintF(request.out, "<h1>Verbindung erfolgreich verarbeitet!</h1>"); 76 FCGX_FPrintF(request.out, "Content-Type: text/plain; charset=utf-8\r\n\r\n");
77 FCGX_FPrintF(request.out, "Die Anfrage konnte nicht verarbeitet werden.\n");
78}
79
80string
81read_request_body(const FCGX_Request& request)
82{
83 string body;
84 char buffer[8192];
85 int gelesen;
86
87 while ( (gelesen = FCGX_GetStr(buffer, sizeof buffer, request.in)) > 0 ) {
88 body.append(buffer, gelesen);
89 }
90
91 return body;
52} 92}
53} // namespace 93} // namespace
54 94
@@ -70,26 +110,51 @@ main()
70 } 110 }
71 111
72 init_signal_handler(); 112 init_signal_handler();
73 load_configuration();
74 113
75 quit = false; 114 Configuration configuration{};
76 reload = false; 115 if ( !load_configuration(configuration) ) {
116 cerr << "Die Konfiguration konnte nicht geladen werden.\n";
117 return EXIT_FAILURE;
118 }
77 119
78 cout << "Handle Requests...\n"; 120 cout << "Handle Requests...\n";
79 121
80 while ( !quit ) { 122 while ( !quit ) {
81 if ( reload ) { 123 if ( reload.exchange(false) ) {
82 load_configuration(); 124 Configuration new_configuration{};
83 reload = false; 125
126 if ( load_configuration(new_configuration) ) {
127 configuration = std::move(new_configuration);
128 }
129 else {
130 cerr << "Neue Konfiguration nicht lesbar, die bisherige bleibt in Kraft.\n";
131 }
84 } 132 }
85 133
86 if ( FCGX_Accept_r(&request) < 0 ) { 134 if ( FCGX_Accept_r(&request) < 0 ) {
135 if ( errno != EINTR ) {
136 cerr << "Fehler beim Annehmen der Verbindung: " << strerror(errno) << '\n';
137 break;
138 }
87 continue; 139 continue;
88 } 140 }
89 141
90 handle_request(request); 142 try {
143 const string body = read_request_body(request);
144
145 ostringstream response;
146 handle_request(request.envp, configuration, body, response);
147
148 const string_view text = response.view();
149 FCGX_PutStr(text.data(), static_cast<int>(text.size()), request.out);
150 }
151 catch ( const exception& e ) {
152 FCGX_FPrintF(request.err, "Fehler beim Verarbeiten der Anfrage: %s\n", e.what());
153 send_internal_error(request);
154 }
91 155
92 FCGX_Finish_r(&request); 156 FCGX_Finish_r(&request);
93 } 157 }
158
94 cout << "shutdown...\n"; 159 cout << "shutdown...\n";
95} 160}