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
|
#include "abstractServer.hpp"
namespace cpr {
void AbstractServer::SetUp() {
Start();
}
void AbstractServer::TearDown() {
Stop();
}
void AbstractServer::Start() {
should_run = true;
serverThread = std::make_shared<std::thread>(&AbstractServer::Run, this);
serverThread->detach();
std::unique_lock<std::mutex> server_lock(server_mutex);
server_start_cv.wait(server_lock);
}
void AbstractServer::Stop() {
should_run = false;
std::unique_lock<std::mutex> server_lock(server_mutex);
server_stop_cv.wait(server_lock);
}
static void EventHandler(mg_connection* conn, int event, void* event_data, void* context) {
switch (event) {
case MG_EV_READ:
case MG_EV_WRITE:
/** Do nothing. Just for housekeeping. **/
break;
case MG_EV_POLL:
/** Do nothing. Just for housekeeping. **/
break;
case MG_EV_CLOSE:
/** Do nothing. Just for housekeeping. **/
break;
case MG_EV_ACCEPT:
/* Initialize HTTPS connection if Server is an HTTPS Server */
static_cast<AbstractServer*>(context)->acceptConnection(conn);
break;
case MG_EV_CONNECT:
/** Do nothing. Just for housekeeping. **/
break;
case MG_EV_HTTP_CHUNK: {
/** Do nothing. Just for housekeeping. **/
} break;
case MG_EV_HTTP_MSG: {
AbstractServer* server = static_cast<AbstractServer*>(context);
server->OnRequest(conn, static_cast<mg_http_message*>(event_data));
} break;
default:
break;
}
}
void AbstractServer::Run() {
// Setup a new mongoose http server.
memset(&mgr, 0, sizeof(mg_mgr));
initServer(&mgr, EventHandler);
// Notify the main thread that the server is up and runing:
server_start_cv.notify_all();
// Main server loop:
while (should_run) {
// NOLINTNEXTLINE (cppcoreguidelines-avoid-magic-numbers)
mg_mgr_poll(&mgr, 100);
}
// Shutdown and cleanup:
timer_args.clear();
mg_mgr_free(&mgr);
// Notify the main thread that we have shut down everything:
server_stop_cv.notify_all();
}
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
/**
* Decodes the given BASE64 string to a normal string.
* Source: https://gist.github.com/williamdes/308b95ac9ef1ee89ae0143529c361d37
**/
std::string AbstractServer::Base64Decode(const std::string& in) {
std::string out;
std::vector<int> T(256, -1);
for (size_t i = 0; i < 64; i++)
T[base64_chars[i]] = static_cast<int>(i);
int val = 0;
int valb = -8;
for (unsigned char c : in) {
if (T[c] == -1) {
break;
}
val = (val << 6) + T[c];
valb += 6;
if (valb >= 0) {
out.push_back(char((val >> valb) & 0xFF));
valb -= 8;
}
}
return out;
}
// Sends error similar like in mongoose 6 method mg_http_send_error
// https://github.com/cesanta/mongoose/blob/6.18/mongoose.c#L7081-L7089
void AbstractServer::SendError(mg_connection* conn, int code, std::string& reason) {
std::string headers{"Content-Type: text/plain\r\nConnection: close\r\n"};
mg_http_reply(conn, code, headers.c_str(), reason.c_str());
}
// Checks whether a pointer to a connection is still managed by a mg_mgr.
// This check tells whether it is still possible to send a message via the given connection
// Note that it is still possible that the pointer of an old connection object may be reused by mongoose.
// In this case, the active connection might refer to a different connection than the one the caller refers to
bool AbstractServer::IsConnectionActive(mg_mgr* mgr, mg_connection* conn) {
mg_connection* c{mgr->conns};
while (c) {
if (c == conn) {
return true;
}
c = c->next;
}
return false;
}
uint16_t AbstractServer::GetRemotePort(const mg_connection* conn) {
return (conn->rem.port >> 8) | (conn->rem.port << 8);
}
uint16_t AbstractServer::GetLocalPort(const mg_connection* conn) {
return (conn->loc.port >> 8) | (conn->loc.port << 8);
}
} // namespace cpr
|