29#include <netinet/in.h>
32#include <sys/socket.h>
43 int client_fd = (int)(intptr_t)arg;
44 int rd_num = (rand() % (5 - 1 + 1)) + 1;
52 int body_len = snprintf(
54 "<!DOCTYPE html><html><head><title>12-http-server-example</title>"
55 "<body><h1>%d</h1></body></html>",
63 response,
sizeof(response),
65 "Content-Type: text/html; charset=UTF-8\r\n"
66 "Content-Length: %d\r\n"
67 "Connection: close\r\n\r\n"
75 printf(
"Failed to write: %s\n", result.maybe_error->msg);
78 printf(
"[%s] Replied back to the client\n", self->
name);
91 printf(
"server: accept failed: %s\n", conn.maybe_error->msg);
101 int fl = fcntl(fd, F_GETFL, 0);
102 (void)fcntl(fd, F_SETFL, fl | O_NONBLOCK);
110 int sock = socket(AF_INET, SOCK_STREAM, 0);
111 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one,
sizeof(
int));
114 struct sockaddr_in a = {
115 .sin_family = AF_INET,
116 .sin_addr = {INADDR_ANY},
117 .sin_port = htons(port),
120 if (sock < 0 || bind(sock, (
struct sockaddr *)&a,
sizeof(a)) != 0 || listen(sock, 128) != 0) {
121 perror(
"listener setup");
126 socklen_t al =
sizeof(a);
127 if (getsockname(sock, (
struct sockaddr *)&a, &al) != 0) {
128 perror(
"getsockname");
132 printf(
"Running the webserver on 0.0.0.0:%d\n", port);
static srn_fiber_result_t server(srn_context_t *ctx, void *arg)
static void set_nonblock(int fd)
static srn_fiber_result_t srn_fiber_web_worker(srn_context_t *ctx, void *arg)
static srn_fiber_result_t server(srn_context_t *ctx, void *arg)
srn_context_t * srn_context_make(srn_engine_t *engine)
Make an empty context, by allocating a new memory block.
int srn_context_release(srn_context_t *ctx)
#define HAS_ERROR(x)
True when x – a value carrying an ERROR_HEADER – has an error attached.
srn_fiber_t * srn_fiber_spawn(srn_context_t *ctx, srn_fiber_entry_t entry, void *arg)
Make and schedule a fiber with every default, the engine's scheduler, the configured stack size,...
void * srn_fiber_result_t
What a fiber's entry produces, type-erased.
srn_io_size_result_t srn_fiber_write(int fd, const void *buf, size_t len, int64_t offset)
Write len bytes from buf to fd, suspending the calling fiber until the operation completes rather tha...
srn_io_accept_result_t srn_fiber_accept(int fd, struct sockaddr *addr, socklen_t addr_cap)
Accept a pending connection on the listening socket fd, suspending the calling fiber until one arrive...
srn_error_t * srn_fiber_sleep(uint64_t duration)
Suspend the calling fiber for at least duration seconds, letting its worker run other fibers meanwhil...
srn_io_size_result_t srn_fiber_read(int fd, void *buf, size_t len, int64_t offset)
Read up to len bytes from fd into buf, suspending the calling fiber until the operation completes rat...
The fiber facing IO API: blocking looking calls a fiber uses to do IO.
#define SERENE_RUNTIME_SHUTDOWN(engine)
Tear down what SERENE_RUNTIME_INIT brought up, in reverse order, the engine (reactor,...
#define SERENE_RUNTIME_INIT_WITH_SCHED(engine, sched, config)
SERENE_RUNTIME_INIT plus a sched variable bound to the engine's scheduler, which every run and fiber ...
srn_fiber_t * srn_fiber_current(void)
The fiber currently running on this os thread, or null when the calling thread is not a worker or the...
void srn_sched_run(srn_scheduler_t *sched, size_t nworkers)
Run the scheduler with nworkers os threads draining it, returning once the pool goes quiescent (every...
char name[SRN_FIBER_NAME_MAX]
Debug name, the caller's choice copied at creation, or the autogenerated f#<id> from the engine wide ...
The result of srn_fiber_accept.