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

Go to the source code of this file.

Data Structures

struct  server_args_t
struct  client_args_t

Functions

static void set_nonblock (int fd)
static srn_fiber_result_t server (srn_context_t *ctx, void *arg)
static srn_fiber_result_t client (srn_context_t *ctx, void *arg)
int main (void)

Function Documentation

◆ client()

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

Definition at line 77 of file 09_tcp_echo.c.

77 {
78 (void)ctx;
79 client_args_t *c = arg;
80 int fd = socket(AF_INET, SOCK_STREAM, 0);
81 if (fd < 0) {
82 perror("socket");
83 return nullptr;
84 }
85 set_nonblock(fd);
86
87 struct sockaddr_in to = {.sin_family = AF_INET, .sin_port = c->port};
88 to.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
89
90 srn_error_t *err = srn_fiber_connect(fd, (struct sockaddr *)&to, sizeof(to));
91 if (err != nullptr) {
92 printf("client: connect failed: %s\n", err->msg);
93 close(fd);
94 return nullptr;
95 }
96
97 const char *msg = "ping";
98 (void)srn_fiber_write(fd, msg, strlen(msg), -1);
99
100 char buf[64] = {0};
101 srn_io_size_result_t r = srn_fiber_read(fd, buf, sizeof(buf) - 1, -1);
102 if (!HAS_ERROR(r)) {
103 buf[r.count] = '\0';
104 }
105 printf("client: sent \"%s\", got back \"%s\"\n", msg, buf);
106 close(fd);
107 return nullptr;
108}
static void set_nonblock(int fd)
Definition 09_tcp_echo.c:51
#define HAS_ERROR(x)
True when x – a value carrying an ERROR_HEADER – has an error attached.
Definition errors.h:63
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_connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
Connect the socket fd to addr/addrlen, suspending the calling fiber until the connection completes ra...
Definition io.c:330
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
uint16_t port
Definition 09_tcp_echo.c:48
A runtime error, a tag classifying the failure and a human-readable message.
Definition errors.h:125
char * msg
Definition errors.h:127
The result of a byte transfer op (read/write/sendto/recvmsg/sendmsg).
Definition io.h:76
size_t count
Definition io.h:78
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( void )

Definition at line 110 of file 09_tcp_echo.c.

110 {
111 SERENE_RUNTIME_INIT_WITH_SCHED(engine, sched, nullptr);
112 srn_context_t *ctx = srn_context_make(engine);
113
114 int lst = socket(AF_INET, SOCK_STREAM, 0);
115 struct sockaddr_in a = {.sin_family = AF_INET};
116 a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
117 if (lst < 0 || bind(lst, (struct sockaddr *)&a, sizeof(a)) != 0 || listen(lst, 4) != 0) {
118 perror("listener setup");
119 return 1;
120 }
121 set_nonblock(lst);
122 socklen_t al = sizeof(a);
123 if (getsockname(lst, (struct sockaddr *)&a, &al) != 0) {
124 perror("getsockname");
125 return 1;
126 }
127
128 server_args_t s = {lst};
129 client_args_t c = {a.sin_port};
130 (void)srn_fiber_spawn(ctx, server, &s);
131 (void)srn_fiber_spawn(ctx, client, &c);
132
133 srn_sched_run(sched, 1);
134 close(lst);
135
138 return 0;
139}
static srn_fiber_result_t client(srn_context_t *ctx, void *arg)
Definition 09_tcp_echo.c:77
static srn_fiber_result_t server(srn_context_t *ctx, void *arg)
Definition 09_tcp_echo.c:56
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 56 of file 09_tcp_echo.c.

56 {
57 (void)ctx;
58 server_args_t *s = arg;
60 if (HAS_ERROR(a)) {
61 printf("server: accept failed: %s\n", a.maybe_error->msg);
62 return nullptr;
63 }
64 int conn = a.fd;
65 char buf[64] = {0};
66 srn_io_size_result_t r = srn_fiber_read(conn, buf, sizeof(buf), -1);
67 if (HAS_ERROR(r)) {
68 printf("server: read failed: %s\n", r.maybe_error->msg);
69 } else {
70 printf("server: got %zu bytes, echoing them back\n", r.count);
71 (void)srn_fiber_write(conn, buf, r.count, -1);
72 }
73 close(conn);
74 return nullptr;
75}
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:
Here is the caller graph for this function:

◆ set_nonblock()

void set_nonblock ( int fd)
static

Definition at line 51 of file 09_tcp_echo.c.

51 {
52 int fl = fcntl(fd, F_GETFL, 0);
53 (void)fcntl(fd, F_SETFL, fl | O_NONBLOCK);
54}
Here is the caller graph for this function: