diff --git a/.gitignore b/.gitignore index a4220f5..50d8acd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,23 @@ # Object files -*.o -*.ko +/*.o +/*.ko # Libraries -*.lib -*.a +/*.lib +/*.a # Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib +/*.dll +/*.so +/*.so.* +/*.dylib # Executables -*.exe -*.out -*.app - -build-* -sip_ua -udp_server -tcp_server - +/*.exe +/*.out +/*.app +/build-* +/sip_ua +/udp_server +/tcp_server +/websocket_server diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a1ad3d8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +language: c + +before_install: + - sudo apt-get -qq update + - sudo apt-get -y install libssl-dev + +install: + - git clone https://github.com/creytiv/re.git + - cd re && make && sudo make install && cd .. + - sudo ldconfig + - wget "https://github.com/alfredh/pytools/raw/master/ccheck.py" + +script: + - make EXTRA_CFLAGS=-Werror + - python2 ccheck.py diff --git a/Makefile b/Makefile index 4a76c0b..c61e366 100644 --- a/Makefile +++ b/Makefile @@ -5,11 +5,12 @@ # PROJECT := redemo -VERSION := 0.4.1 +VERSION := 0.6.0 DEMOS += sip_ua DEMOS += tcp_server DEMOS += udp_server +DEMOS += websocket_server LIBRE_MK := $(shell [ -f ../re/mk/re.mk ] && \ diff --git a/README.md b/README.md index 5b2fb53..8bd3232 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,5 @@ redemo ====== Demo example applications using libre + +[![Build Status](https://travis-ci.org/creytiv/redemo.svg?branch=master)](https://travis-ci.org/creytiv/redemo) diff --git a/src/sip_ua/sip_ua.c b/src/sip_ua/sip_ua.c index a7daa2b..185b472 100644 --- a/src/sip_ua/sip_ua.c +++ b/src/sip_ua/sip_ua.c @@ -8,8 +8,8 @@ * $ ./sip_ua * * - * To test otbound calls, invoke with a SIP URI argument. - * sip_will will invite provided URI: + * To test outbound calls, invoke with a SIP URI argument. + * sip_ua will invite provided URI: * * $ ./sip_ua sip:echo@creytiv.com * @@ -269,7 +269,7 @@ static void exit_handler(void *arg) } -/* called upon reception of SIGINT, SIGALRM or SIGTERM */ +/* called upon reception of SIGINT, SIGALRM or SIGTERM */ static void signal_handler(int sig) { re_printf("terminating on signal %d...\n", sig); @@ -413,7 +413,8 @@ int main(int argc, char *argv[]) } else { - err = sipreg_register(®, sip, registrar, uri, uri, 60, name, + err = sipreg_register(®, sip, registrar, uri, + NULL, uri, 60, name, NULL, 0, 0, auth_handler, NULL, false, register_handler, NULL, NULL, NULL); if (err) { @@ -436,7 +437,7 @@ int main(int argc, char *argv[]) mem_deref(sip); mem_deref(dnsc); - /* free librar state */ + /* free libre state */ libre_close(); /* check for memory leaks */ diff --git a/src/tcp_server/tcp_server.c b/src/tcp_server/tcp_server.c index 1876209..362136c 100644 --- a/src/tcp_server/tcp_server.c +++ b/src/tcp_server/tcp_server.c @@ -136,7 +136,7 @@ int main(void) (void)sa_set_str(&laddr, "0.0.0.0", 3456); - /* Create listening UDP socket, IP address 0.0.0.0, TCP port 3456 */ + /* Create listening TCP socket, IP address 0.0.0.0, TCP port 3456 */ err = tcp_listen(&ts, &laddr, connect_handler, NULL); if (err) { re_fprintf(stderr, "tcp listen error: %s\n", strerror(err)); diff --git a/src/websocket_server/demo.mk b/src/websocket_server/demo.mk new file mode 100644 index 0000000..081a6f2 --- /dev/null +++ b/src/websocket_server/demo.mk @@ -0,0 +1,11 @@ +# +# demo.mk +# +# Copyright (C) 2011 Creytiv.com +# + +DEMO := websocket_server +$(DEMO)_SRCS += websocket_server.c +$(DEMO)_LFLAGS += + +include mk/dmo.mk diff --git a/src/websocket_server/websocket_server.c b/src/websocket_server/websocket_server.c new file mode 100644 index 0000000..1c5cec3 --- /dev/null +++ b/src/websocket_server/websocket_server.c @@ -0,0 +1,171 @@ +/** + * @file websocket_server.c Websocket Server Demo + * + * The demo can for instance be tested by pasting this into + * a web browser javascript console: + * var ws = new WebSocket('ws://localhost:3456'); + * ws.addEventListener('open', () => ws.send('hello')); + * ws.addEventListener('close', (e) => console.log('close', e)); + * ws.addEventListener('message', (e) => console.log('msg', e)); + * + * Copyright (C) 2018 Creytiv.com + */ + +#include + + +struct websocket { + struct le le; /* list entry */ + struct websock_conn *conn; /* Websocket connection */ +}; + +static struct websock *server; + +/* Linked list of active Websocket connections */ +static struct list connl; + +/* called upon reception of SIGINT, SIGALRM or SIGTERM */ +static void signal_handler(int sig) +{ + re_printf("terminating on signal %d...\n", sig); + + /* destroy active Websocket connections */ + list_flush(&connl); + + websock_shutdown(server); +} + + +static void websock_shutdown_handler(void *arg) +{ + (void)arg; + re_printf("websocket server shutting down\n"); + + /* stop libre main loop */ + re_cancel(); +} + + +/* destructor called when reference count on conn reach zero */ +static void destructor(void *arg) +{ + struct websocket *ws = arg; + + /* remove this connection entry from the list */ + list_unlink(&ws->le); + + /* clean up local Websocket connection state */ + mem_deref(ws->conn); +} + + +/* called when a message is received from the other side */ +static void srv_websock_recv_handler(const struct websock_hdr *hdr, + struct mbuf *mb, void *arg) +{ + struct websocket *ws = arg; + int err; + + err = websock_send(ws->conn, hdr->opcode, "%b", + mbuf_buf(mb), mbuf_get_left(mb)); + if (err) + re_fprintf(stderr, "ws send error: %m\n", err); +} + + +/* called when the websocket is closed by the other side */ +static void srv_websock_close_handler(int err, void *arg) +{ + struct websocket *ws = arg; + + re_printf("ws close %m\n", err); + mem_deref(ws); +} + + +/* HTTP request handler */ +static void http_req_handler(struct http_conn *conn, + const struct http_msg *msg, void *arg) +{ + struct websocket *ws; + int err; + + /* allocate connection state */ + ws = mem_zalloc(sizeof(*ws), destructor); + if (!ws) { + err = ENOMEM; + re_fprintf(stderr, "http req handler alloc error: %m\n", err); + goto out; + } + + err = websock_accept(&ws->conn, server, conn, msg, + 0, srv_websock_recv_handler, + srv_websock_close_handler, ws); + if (err) { + re_fprintf(stderr, "websocket accept error: %m\n", err); + goto out; + } + + /* append connection to connection list */ + list_append(&connl, &ws->le, ws); + out: + if (err) { + http_reply(conn, 500, "Server Error", NULL); + /* destroy state */ + mem_deref(ws); + } +} + + +int main(void) +{ + struct sa laddr; + struct http_sock *httpsock = NULL; + int err; /* errno return values */ + + /* enable coredumps to aid debugging */ + (void)sys_coredump_set(true); + + /* initialize libre state */ + err = libre_init(); + if (err) { + re_fprintf(stderr, "re init failed: %m\n", err); + goto out; + } + + (void)sa_set_str(&laddr, "0.0.0.0", 3456); + + /* Create listening HTTP server, IP address 0.0.0.0, TCP port 3456 */ + err = http_listen(&httpsock, &laddr, http_req_handler, NULL); + if (err) { + re_fprintf(stderr, "http listen error: %m\n", err); + goto out; + } + + err = websock_alloc(&server, websock_shutdown_handler, NULL); + if (err) { + re_fprintf(stderr, "websocket alloc error: %m\n", err); + goto out; + } + + re_printf("listening on WS socket: %J\n", &laddr); + + /* main loop */ + err = re_main(signal_handler); + + out: + /* free HTTP socket */ + httpsock = mem_deref(httpsock); + + /* free Websocket server */ + server = mem_deref(server); + + /* free library state */ + libre_close(); + + /* check for memory leaks */ + tmr_debug(); + mem_debug(); + + return err; +}