Open joegasewicz opened 5 days ago
I think I need to set the host, is this done via the ulfius_init_instance
functions's bind_address
parameter?
Hello,
It's hard to say without the server source code, which doesn't seem to be hosted in the repo you mention.
But my first guess is that you don't make your server waiting right after starting the ulfius endpoint. Ulfius webserver is executed in a non blocking thread so your server can do other things.
In the example programs, I usually use getchar()
to keep the program running but that's not a good method for a server.
You can search for "daemon programming c" to get some examples.
Here's the current server code:
#include <stdio.h>
#include <stdlib.h>
#include <ulfius.h>
#include <jansson.h>
#include <string.h>
#include <stdbool.h>
#include <netinet/in.h>
#include "tcp.h"
#include "queue.h"
#include "config.h"
static int callback_consumer(const struct _u_request *request,
struct _u_response *response, void *queue)
{
JSON_INDENT(4);
const FMQ_Queue *q = (FMQ_Queue*)queue;
const FMQ_QNode *node = FMQ_Queue_dequeue((FMQ_Queue*)queue);
if (node == NULL)
{
FMQ_LOGGER(q->log_level ,"Queue is empty\n");
ulfius_set_json_body_response(response, 204, json_pack("{s:s}", "message", NULL));
return U_CALLBACK_CONTINUE;
}
const FMQ_Data *dataPtr = (FMQ_Data*)node->data;
FMQ_LOGGER(q->log_level, "Successfully dequeued message for consumer\n");
ulfius_set_json_body_response(response, 200, json_pack("{s:s}", "message", dataPtr->message));
free((FMQ_Data*)node->data);
free((FMQ_QNode*)node);
return U_CALLBACK_CONTINUE;
}
static int callback_provider(const struct _u_request *request,
struct _u_response *response, void *queue)
{
const FMQ_Queue *q = (FMQ_Queue*)queue;
JSON_INDENT(4);
json_t *json_body = ulfius_get_json_body_request(request, NULL);
const char *message = json_string_value(json_object_get(json_body, "message"));
bool destroy = json_boolean_value(json_object_get(json_body, "destroy"));
if (destroy) {
FMQ_QUEUE_destroy((FMQ_Queue*)queue);
FMQ_LOGGER(q->log_level, "Successfully destroyed queue\n");
ulfius_set_json_body_response(response, 200, json_pack("{s:s}", "message", message));
return U_CALLBACK_CONTINUE;
}
FMQ_LOGGER(q->log_level, "Received: %s\n", message);
FMQ_Data *data = (FMQ_Data*)malloc(sizeof(FMQ_Queue));
data->message = malloc(sizeof(char) * q->msg_size);
strcpy(data->message, message);
FMQ_Queue_enqueue((FMQ_Queue*)queue, data);
ulfius_set_json_body_response(response, 200, json_pack("{s:s}", "message", message));
json_decref(json_body);
return U_CALLBACK_CONTINUE;
}
static int start_server(FMQ_TCP *tcp)
{
struct _u_instance instance;
if (ulfius_init_instance(&instance, tcp->port, NULL, NULL) != U_OK)
{
fprintf(stderr, "Error starting ulfius server\n");
exit(EXIT_FAILURE);
}
ulfius_add_endpoint_by_val(&instance, "POST", "/consumer", NULL, 0, &callback_consumer, tcp->queue);
ulfius_add_endpoint_by_val(&instance, "POST", "/provider", NULL, 0, &callback_provider, tcp->queue);
if (ulfius_start_framework(&instance) == U_OK)
{
printf("Starting server on http://localhost:%d\n", instance.port);
getchar();
}
else
{
fprintf(stderr, "Error starting server...\n");
printf("Error: \n\t- Tip: Check that port %d is not busy\n", tcp->port);
}
FMQ_LOGGER(tcp->log_level, "Stopping server \n");
ulfius_stop_framework(&instance);
ulfius_clean_instance(&instance);
return 0;
}
FMQ_TCP *FMQ_TCP_new(FMQ_Queue *queue, const u_int16_t port, const int8_t log_level)
{
FMQ_TCP *tcp = (FMQ_TCP*)malloc(sizeof(FMQ_TCP));
tcp->queue = queue;
tcp->start = start_server;
tcp->port = port;
tcp->log_level = log_level;
return tcp;
}
This is the Dockerfile
FROM --platform=linux/amd64 ubuntu:22.04
WORKDIR /forestmq
COPY . .
ENV APPLE = 0
ENV UNIX = 1
RUN apt update
RUN apt install -y libulfius-dev uwsc
RUN apt install -y libmicrohttpd-dev
RUN apt install -y libjansson-dev
RUN apt install -y libcurl4-gnutls-dev
RUN apt install -y libgnutls28-dev
RUN apt install -y libgcrypt20-dev
RUN apt install -y libsystemd-dev
RUN apt install -y pkg-config
RUN apt install -y cmake
#RUN mkdir build
RUN cmake -S . -B build
RUN make -C build
EXPOSE 8005
CMD ["./build/forest_mq"]
@babelouest
Yes I am blocking the main thread with getchar()
as per your example -
if (ulfius_start_framework(&instance) == U_OK)
{
printf("Starting server on http://localhost:%d\n", instance.port);
getchar();
}
Is it possible to set the host, for example to 0.0.0.0
?
@babelouest Is it possible to set the host, for example to
0.0.0.0
?
I'm not sure what tout expect if you set the host, but setting the bind_address
won't change the server exiting right after starting ulfius webserver.
Your problem doesn't seem to be how to use ulfius but how to program a daemon in C.
My best guess is to look for examples, to help you build a program running in docker.
@babelouest ok thanks for the advice.
I got it working using -it
arg to start the container in the interactive mode... might help someone else with this issue.
e.g
docker run -it -p 8005:8005 $(IMG_NAME)
Describe the issue I want to dockerize an app that uses ulfius, it builds and runs successfully but then exists 0 straight away For example:
To Reproduce You can pull down the code from https://github.com/joegasewicz/forestmq
Expected behavior I expect the ulfius server to persist when run inside a docker container
System (please complete the following information):
2.7.15