-
Notifications
You must be signed in to change notification settings - Fork 141
/
raw-echo.c
117 lines (98 loc) · 4.28 KB
/
raw-echo.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* *****************************************************************************
This is a simple echo server example.
To try it out, compile using (avoids server state printout):
FIO_PRINT=0 NAME=echo make
Than run:
./tmp/echo
To connect to this server run telnet, netcat or the client example, using:
telnet localhost 3000
Or:
nc localhost 3000
This example uses the core facil.io library (fio.h) and the Command Line
Interface library (fio_cli.h).
***************************************************************************** */
#include <fio.h>
#include <fio_cli.h>
/* *****************************************************************************
Echo connection callbacks
***************************************************************************** */
// A callback to be called whenever data is available on the socket
static void echo_on_data(intptr_t uuid, fio_protocol_s *prt) {
// echo buffer
char buffer[1024] = {'E', 'c', 'h', 'o', ':', ' '};
ssize_t len;
// Read to the buffer, starting after the "Echo: "
while ((len = fio_read(uuid, buffer + 6, 1018)) > 0) {
fprintf(stderr, "Read: %.*s", (int)len, buffer + 6);
// Write back the message
fio_write(uuid, buffer, len + 6);
// Handle goodbye
if ((buffer[6] | 32) == 'b' && (buffer[7] | 32) == 'y' &&
(buffer[8] | 32) == 'e') {
fio_write(uuid, "Goodbye.\n", 9);
fio_close(uuid);
return;
}
}
(void)prt; // we can ignore the unused argument
}
// A callback called whenever a timeout is reach
static void echo_ping(intptr_t uuid, fio_protocol_s *prt) {
fio_write(uuid, "Server: Are you there?\n", 23);
(void)prt; // we can ignore the unused argument
}
// A callback called if the server is shutting down...
// ... while the connection is still open
static uint8_t echo_on_shutdown(intptr_t uuid, fio_protocol_s *prt) {
fio_write(uuid, "Echo server shutting down\nGoodbye.\n", 35);
return 0;
(void)prt; // we can ignore the unused argument
}
static void echo_on_close(intptr_t uuid, fio_protocol_s *proto) {
fprintf(stderr, "Connection %p closed.\n", (void *)proto);
free(proto);
(void)uuid;
}
/* *****************************************************************************
The main echo protocol creation callback
***************************************************************************** */
// A callback called for new connections
static void echo_on_open(intptr_t uuid, void *udata) {
// Protocol objects MUST be dynamically allocated when multi-threading.
fio_protocol_s *echo_proto = malloc(sizeof(*echo_proto));
*echo_proto = (fio_protocol_s){.on_data = echo_on_data,
.on_shutdown = echo_on_shutdown,
.on_close = echo_on_close,
.ping = echo_ping};
fprintf(stderr, "New Connection %p received from %s\n", (void *)echo_proto,
fio_peer_addr(uuid).data);
fio_attach(uuid, echo_proto);
fio_write2(uuid, .data.buffer = "Echo Service: Welcome\n", .length = 22,
.after.dealloc = FIO_DEALLOC_NOOP);
fio_timeout_set(uuid, 5);
(void)udata; // ignore this
}
/* *****************************************************************************
The main function (listens to the `echo` connections and handles CLI)
***************************************************************************** */
// The main function starts listening to echo connections
int main(int argc, char const *argv[]) {
/* Setup CLI arguments */
fio_cli_start(argc, argv, 0, 0, "this example accepts the following options:",
FIO_CLI_INT("-t -thread number of threads to run."),
FIO_CLI_INT("-w -workers number of workers to run."),
"-b, -address the address to bind to.",
FIO_CLI_INT("-p,-port the port to bind to."),
FIO_CLI_BOOL("-v -log enable logging."));
/* Setup default values */
fio_cli_set_default("-p", "3000");
fio_cli_set_default("-t", "1");
fio_cli_set_default("-w", "1");
/* Listen for connections */
if (fio_listen(.port = fio_cli_get("-p"), .on_open = echo_on_open) == -1) {
perror("No listening socket available on port 3000");
exit(-1);
}
/* Run the server and hang until a stop signal is received */
fio_start(.threads = fio_cli_get_i("-t"), .workers = fio_cli_get_i("-w"));
}