Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
12_http_server.c File Reference
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <serene/rt/fiber/io.h>
#include <serene/runtime.h>
Include dependency graph for 12_http_server.c:

Go to the source code of this file.

Data Structures

struct  server_args_t

Typedefs

typedef struct server_args_t server_args_t

Functions

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)
static void set_nonblock (int fd)
int main (void)

Typedef Documentation

◆ server_args_t

typedef struct server_args_t server_args_t

Function Documentation

◆ main()

int main ( void )

Definition at line 105 of file 12_http_server.c.

105 {
106 SERENE_RUNTIME_INIT_WITH_SCHED(engine, sched, nullptr);
107 srn_context_t *ctx = srn_context_make(engine);
108
109 int one = 1;
110 int sock = socket(AF_INET, SOCK_STREAM, 0);
111 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
112
113 int port = 8080;
114 struct sockaddr_in a = {
115 .sin_family = AF_INET,
116 .sin_addr = {INADDR_ANY},
117 .sin_port = htons(port),
118 };
119
120 if (sock < 0 || bind(sock, (struct sockaddr *)&a, sizeof(a)) != 0 || listen(sock, 128) != 0) {
121 perror("listener setup");
122 return 1;
123 }
124
125 set_nonblock(sock);
126 socklen_t al = sizeof(a);
127 if (getsockname(sock, (struct sockaddr *)&a, &al) != 0) {
128 perror("getsockname");
129 return 1;
130 }
131
132 printf("Running the webserver on 0.0.0.0:%d\n", port);
133 server_args_t s = {sock};
134 (void)srn_fiber_spawn(ctx, server, &s);
135
136 srn_sched_run(sched, 1);
137 close(sock);
138
141 return 0;
142}
static srn_fiber_result_t server(srn_context_t *ctx, void *arg)
Definition 09_tcp_echo.c:56
static void set_nonblock(int fd)
srn_context_t * srn_context_make(srn_engine_t *engine)
Make an empty context, by allocating a new memory block.
Definition context.c:39
int srn_context_release(srn_context_t *ctx)
Definition context.c:64
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,...
Definition fiber.c:247
#define SERENE_RUNTIME_SHUTDOWN(engine)
Tear down what SERENE_RUNTIME_INIT brought up, in reverse order, the engine (reactor,...
Definition runtime.h:58
#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 ...
Definition runtime.h:46
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...
Definition scheduler.c:843
Here is the call graph for this function:

◆ server()

srn_fiber_result_t server ( srn_context_t * ctx,
void * arg )
static

Definition at line 83 of file 12_http_server.c.

83 {
84 (void)ctx;
85 server_args_t *s = arg;
86
87 for (;;) {
89
90 if (HAS_ERROR(conn)) {
91 printf("server: accept failed: %s\n", conn.maybe_error->msg);
92 return nullptr;
93 }
94
95 (void)srn_fiber_spawn(ctx, srn_fiber_web_worker, (void *)(intptr_t)conn.fd);
96 }
97 return nullptr;
98}
static srn_fiber_result_t srn_fiber_web_worker(srn_context_t *ctx, void *arg)
#define HAS_ERROR(x)
True when x – a value carrying an ERROR_HEADER – has an error attached.
Definition errors.h:63
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...
Definition io.c:308
The result of srn_fiber_accept.
Definition io.h:86
Here is the call graph for this function:

◆ set_nonblock()

void set_nonblock ( int fd)
static

Definition at line 100 of file 12_http_server.c.

100 {
101 int fl = fcntl(fd, F_GETFL, 0);
102 (void)fcntl(fd, F_SETFL, fl | O_NONBLOCK);
103}
Here is the caller graph for this function:

◆ srn_fiber_web_worker()

srn_fiber_result_t srn_fiber_web_worker ( srn_context_t * ctx,
void * arg )
static

Definition at line 42 of file 12_http_server.c.

42 {
43 int client_fd = (int)(intptr_t)arg;
44 int rd_num = (rand() % (5 - 1 + 1)) + 1;
45
46 // Drain the request first. Closing a socket with unread bytes makes the
47 // kernel answer with RST instead of FIN and the client reports a reset.
48 char req[1024];
49 (void)srn_fiber_read(client_fd, req, sizeof(req), -1);
50
51 char body[256];
52 int body_len = snprintf(
53 body, sizeof(body),
54 "<!DOCTYPE html><html><head><title>12-http-server-example</title>"
55 "<body><h1>%d</h1></body></html>",
56 rd_num
57 );
58
59 // Content-Length tells the client where the body ends, so it does not
60 // depend on how the connection is torn down to finish the read.
61 char response[1024];
62 int len = snprintf(
63 response, sizeof(response),
64 "HTTP/1.1 200 OK\r\n"
65 "Content-Type: text/html; charset=UTF-8\r\n"
66 "Content-Length: %d\r\n"
67 "Connection: close\r\n\r\n"
68 "%s",
69 body_len, body
70 );
71
72 srn_fiber_sleep(rd_num);
73 auto result = srn_fiber_write(client_fd, response, (size_t)len, -1);
74 if (HAS_ERROR(result)) {
75 printf("Failed to write: %s\n", result.maybe_error->msg);
76 }
78 printf("[%s] Replied back to the client\n", self->name);
79 close(client_fd);
80 return nullptr;
81}
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...
Definition io.c:296
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...
Definition io.c:282
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...
Definition io.c:284
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...
Definition scheduler.c:1058
char name[SRN_FIBER_NAME_MAX]
Debug name, the caller's choice copied at creation, or the autogenerated f#<id> from the engine wide ...
Definition fiber.h:330
Here is the call graph for this function:
Here is the caller graph for this function: