commit 97ec78d1e268f68e9971444afa7735994a32ede7
parent f7b0ebc55151031b850e113eeddcbe9e68de3c26
Author: Yersa Nordman <yersa@finwo.nl>
Date: Thu, 26 Oct 2023 22:10:05 +0200
Add method of shutting down the http server while keeping re-listen functionality
Diffstat:
4 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/example.c b/example.c
@@ -1,3 +1,4 @@
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -14,19 +15,24 @@ void onServing(char *addr, uint16_t port, void *udata) {
printf("Serving at %s:%d\n", addr, port);
}
-int ticksHad = 0;
+const int countDownOrg = 60;
+int countDown = countDownOrg;
void onTick(void *udata) {
- printf("Tick %d\n", ticksHad);
- if (++ticksHad >= 10) {
- printf("10 seconds have passed\n");
- ticksHad = 0;
+ struct http_server_opts *opts = udata;
+
+ // Handle auto-shutdown
+ printf("Shutdown in %d second(s)\n", --countDown);
+ if (countDown <= 0) {
+ opts->shutdown = true;
+ return;
}
- struct http_server_opts *opts = udata;
+ // Handle port re-assign
if (opts->port != targetPort) {
opts->port = targetPort;
fnet_close(opts->listen_connection);
}
+
}
void route_get_hello(struct http_server_reqdata *reqdata) {
@@ -35,6 +41,7 @@ void route_get_hello(struct http_server_reqdata *reqdata) {
reqdata->reqres->response->body->data = strdup("Hello World\n");
reqdata->reqres->response->body->len = strlen(reqdata->reqres->response->body->data);
http_server_response_send(reqdata, true);
+ countDown = countDownOrg;
return;
}
@@ -76,4 +83,7 @@ int main() {
http_server_route("POST", "/port" , route_post_port);
http_server_main(&opts);
+ fnet_shutdown();
+
+ printf("Server has shut down\n");
}
diff --git a/package.ini b/package.ini
@@ -1,11 +1,10 @@
[dependencies]
finwo/fnet=https://github.com/finwo/c-fnet/archive/refs/tags/edge.tar.gz
finwo/http-parser=https://github.com/finwo/http-parser/archive/refs/tags/edge.tar.gz
-
+pierreguillot/thread=https://raw.githubusercontent.com/finwo/dep-repository/main/pierreguillot/thread/package.ini
[export]
config.mk=config.mk
include/finwo/http-server.h=src/http-server.h
-
[package]
deps=lib
name=finwo/http-parser
diff --git a/src/http-server.c b/src/http-server.c
@@ -1,12 +1,33 @@
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "finwo/http-parser.h"
#include "finwo/fnet.h"
+#include "pierreguillot/thread.h"
#include "http-server.h"
+#ifndef UNUSED(x)
+#define UNUSED(x) (void)x
+#endif
+
+static void sleep_ms(long ms) {
+#if defined(__APPLE__)
+ usleep(ms * 1000);
+#elif defined(_WIN32)
+ Sleep(ms);
+#else
+ time_t sec = (int)(ms / 1000);
+ const long t = ms -(sec * 1000);
+ struct timespec req;
+ req.tv_sec = sec;
+ req.tv_nsec = t * 1000000L;
+ while(-1 == nanosleep(&req, &req));
+#endif
+}
+
struct fnet_udata {
struct http_server_opts *opts;
struct fnet_options_t *fnet_opts;
@@ -124,12 +145,20 @@ void _hs_onListenClose(struct fnet_ev *ev) {
ludata->opts->listen_connection = fnet_listen(ludata->opts->addr, ludata->opts->port, ludata->fnet_opts);
}
+void _thread_network(void *arg) {
+ UNUSED(arg);
+ FNET_RETURNCODE ret = fnet_main();
+}
+
void http_server_main(struct http_server_opts *opts) {
if (!opts) exit(1);
+ opts->shutdown = false;
+ // Prepare http context
struct fnet_udata *ludata = calloc(1, sizeof(struct fnet_udata));
ludata->opts = opts;
+ // Prepare network options
struct fnet_options_t fnet_opts = {
.proto = FNET_PROTO_TCP,
.flags = 0,
@@ -141,13 +170,22 @@ void http_server_main(struct http_server_opts *opts) {
.udata = ludata,
};
- ludata->fnet_opts = &fnet_opts;
+ // Track network options in http context
+ ludata->fnet_opts = &fnet_opts;
+ // Signal that we want our port
ludata->opts->listen_connection = fnet_listen(ludata->opts->addr, ludata->opts->port, ludata->fnet_opts);
if (!(ludata->opts->listen_connection)) {
exit(1);
}
- // This is a forever function
- fnet_main();
+ // Launch network management thread
+ // May or may not keep running (either is fine)
+ thd_thread thread;
+ thd_thread_detach(&thread, _thread_network, NULL);
+
+ // This is a forever function, controlled by network thread
+ while(!opts->shutdown) {
+ sleep_ms(100);
+ }
}
diff --git a/src/http-server.h b/src/http-server.h
@@ -16,6 +16,7 @@ struct http_server_opts {
char *addr;
uint16_t port;
void *udata;
+ bool shutdown;
struct fnet_t *listen_connection;
};