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 138 139 140 141 142 143 144 145
|
/*
* SPDX-FileCopyrightText: 2019 Oleg Burchakov
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "pistache/endpoint.h"
#include <signal.h>
#ifdef _WIN32
#include <Windows.h>
#include <WinCon.h>
// #include <ConsoleApi.h> // included in WinCon.h; needs Kernel32.lib
#endif
using namespace Pistache;
class HelloHandler : public Http::Handler
{
public:
HTTP_PROTOTYPE(HelloHandler)
void onRequest(const Http::Request& /*request*/, Http::ResponseWriter response) override
{
response.send(Pistache::Http::Code::Ok, "Hello World\n");
}
};
#ifdef _WIN32
static std::atomic<bool> lSigBool = false;
static std::mutex lMutex;
static std::condition_variable cv;
#define CTRL_TYPE_EMPTY 0xDEADDEAD
static DWORD lCtrlType = CTRL_TYPE_EMPTY;
static BOOL consoleCtrlHandler(DWORD dwCtrlType)
{
std::unique_lock<std::mutex> lock(lMutex);
if (lCtrlType == 0)
{
lCtrlType = dwCtrlType;
lSigBool = true;
cv.notify_one();
}
return(TRUE);// We have handled the ctrl signal
}
#endif // of ifdef _WIN32
int main()
{
#ifdef _WIN32
// Note: SetConsoleCtrlHandler can be used for console apps or GUI apps;
// for GUI apps, the notification from WM_QUERYENDSESSION _may_ arrive
// before the call to consoleCtrlHandler
BOOL set_cch_res = SetConsoleCtrlHandler(consoleCtrlHandler,
true /*Add*/);
if (!set_cch_res)
{
perror("install ctrl-c-handler failed");
return 1;
}
#else
sigset_t signals;
if (sigemptyset(&signals) != 0
|| sigaddset(&signals, SIGTERM) != 0
|| sigaddset(&signals, SIGINT) != 0
|| sigaddset(&signals, SIGHUP) != 0
|| pthread_sigmask(SIG_BLOCK, &signals, nullptr) != 0)
{
perror("install signal handler failed");
return 1;
}
#endif
Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(9080));
auto opts = Pistache::Http::Endpoint::options()
.threads(1);
Http::Endpoint server(addr);
server.init(opts);
server.setHandler(Http::make_handler<HelloHandler>());
server.serveThreaded();
#ifdef _WIN32
std::unique_lock<std::mutex> lock(lMutex);
cv.wait(lock, [&] {return(lSigBool.load());});
switch(lCtrlType)
{
case CTRL_TYPE_EMPTY:
perror("ctrl-type not set");
break;
case CTRL_C_EVENT:
std::cout <<
"ctrl-c received from keyboard or GenerateConsoleCtrlEvent" <<
std::endl;
break;
case CTRL_BREAK_EVENT:
std::cout <<
"ctrl-break received from keyboard or GenerateConsoleCtrlEvent" <<
std::endl;
break;
case CTRL_CLOSE_EVENT:
std::cout <<
"Attached console closed" << std::endl;
break;
case CTRL_LOGOFF_EVENT:
std::cout <<
"User logging off" << std::endl;
break;
case CTRL_SHUTDOWN_EVENT:
std::cout <<
"System shutting down" << std::endl;
break;
default:
perror("ctrl-type unknown");
break;
}
#else // not ifdef _WIN32
int signal = 0;
int status = sigwait(&signals, &signal);
if (status == 0)
{
std::cout << "received signal " << signal << std::endl;
}
else
{
std::cerr << "sigwait returns " << status << std::endl;
}
#endif // of ifdef _WIN32... else...
server.shutdown();
}
|