1 /* the polite echo server. requires you to send a HELO, afterwards
2 mimics a traditional echo server */
4 #include "../rocksockserver.h"
5 #include "../../lib/include/sblist.h"
8 #pragma RcB2 CFLAGS "-std=c99"
18 typedef struct client
{
24 typedef struct server_state
{
29 struct client
*client_from_fd(sblist
*clients
, int fd
) {
31 sblist_iter(clients
, c
) {
32 if(c
->fd
== fd
) return c
;
37 static void disconnect_client(server
* s
, int fd
) {
39 sblist_iter_counter(s
->clients
, i
, c
) {
41 sblist_delete(s
->clients
, i
);
45 rocksockserver_disconnect_client(&s
->srv
, fd
);
48 static int on_cdisconnect (void* userdata
, int fd
) {
50 disconnect_client(s
, fd
);
54 static int on_cconnect (void* userdata
, struct sockaddr_storage
* clientaddr
, int fd
) {
56 struct client c
= {.fd
= fd
};
57 if(!sblist_add(s
->clients
, &c
)) {
58 disconnect_client(s
, fd
);
64 static void read_command(server
*s
, client
*c
, int fd
) {
66 if(c
->state
== cs_null
) {
67 if(5 != (nbytes
= recv(fd
, c
->msg
, 5, 0)) ||
68 memcmp(c
->msg
, "HELO\n", 5)) {
70 } else c
->state
= cs_said_hello
;
71 } else if (c
->state
== cs_idle
) {
72 nbytes
= recv(fd
, c
->msg
, sizeof(c
->msg
)-1, 0);
73 if (nbytes
== 0) on_cdisconnect(s
, fd
);
74 else if(nbytes
< 1) c
->state
= cs_error
;
82 static int on_cread (void* userdata
, int fd
, size_t dummy
) {
85 if(!(c
= client_from_fd(s
->clients
, fd
))) return -1;
86 read_command(s
, c
, fd
);
89 #define SL(X) X, sizeof(X)-1
90 static int on_cwantsdata (void* userdata
, int fd
) {
93 if(!(c
= client_from_fd(s
->clients
, fd
))) return -1;
96 send(fd
, SL("HELO. you may now say something.\n"), MSG_NOSIGNAL
);
102 send(fd
, SL("error: need to send HELO first\n"), MSG_NOSIGNAL
);
103 disconnect_client(s
, fd
);
106 send(fd
, c
->msg
, strlen(c
->msg
), MSG_NOSIGNAL
);
115 s
->clients
= sblist_new(sizeof(struct client
), 32);
116 const int port
= 9999;
117 const char* listenip
= "0.0.0.0";
118 if(rocksockserver_init(&s
->srv
, listenip
, port
, (void*) s
)) return -1;
119 if(rocksockserver_loop(&s
->srv
, NULL
, 0,
120 &on_cconnect
, &on_cread
,
121 &on_cwantsdata
, &on_cdisconnect
)) return -2;