From d7ee97f18cad16aa3c4e33fab69853632658ca45 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Mon, 31 Oct 2016 15:20:12 +0100 Subject: [PATCH 01/36] Make it possible to create a DTLS socket without having an UDP socket underneath. Add `dtls_send_h` and `dtls_mtu_h` for DTLS in UDP socketless mode Add `dtls_socketless` and `dtls_receive` function Add `sendh` and `mtuh` fields to `struct dtls_socket` --- include/re_tls.h | 7 ++++ src/tls/openssl/tls_udp.c | 83 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/include/re_tls.h b/include/re_tls.h index aa45f603..538bdb86 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -66,6 +66,9 @@ int tls_start_tcp(struct tls_conn **ptc, struct tls *tls, /* UDP (DTLS) */ typedef void (dtls_conn_h)(const struct sa *peer, void *arg); +typedef int (dtls_send_h)(struct tls_conn *tc, const struct sa *dst, + struct mbuf *mb, void *arg); +typedef size_t (dtls_mtu_h)(struct tls_conn *tc, void *arg); typedef void (dtls_estab_h)(void *arg); typedef void (dtls_recv_h)(struct mbuf *mb, void *arg); typedef void (dtls_close_h)(int err, void *arg); @@ -75,6 +78,9 @@ struct dtls_sock; int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, struct udp_sock *us, uint32_t htsize, int layer, dtls_conn_h *connh, void *arg); +int dtls_socketless(struct dtls_sock **sockp, uint32_t htsize, + dtls_conn_h *connh, dtls_send_h *sendh, dtls_mtu_h *mtuh, + void *arg); struct udp_sock *dtls_udp_sock(struct dtls_sock *sock); void dtls_set_mtu(struct dtls_sock *sock, size_t mtu); int dtls_connect(struct tls_conn **ptc, struct tls *tls, @@ -86,6 +92,7 @@ int dtls_accept(struct tls_conn **ptc, struct tls *tls, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); int dtls_send(struct tls_conn *tc, struct mbuf *mb); +void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb); void dtls_set_handlers(struct tls_conn *tc, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); const struct sa *dtls_peer(const struct tls_conn *tc); diff --git a/src/tls/openssl/tls_udp.c b/src/tls/openssl/tls_udp.c index e04cd873..449c1226 100644 --- a/src/tls/openssl/tls_udp.c +++ b/src/tls/openssl/tls_udp.c @@ -39,6 +39,8 @@ struct dtls_sock { struct hash *ht; struct mbuf *mb; dtls_conn_h *connh; + dtls_send_h *sendh; + dtls_mtu_h *mtuh; void *arg; size_t mtu; }; @@ -117,7 +119,7 @@ static int bio_write(BIO *b, const char *buf, int len) (void)mbuf_write_mem(mb, (void *)buf, len); mb->pos = SPACE; - err = udp_send_helper(tc->sock->us, &tc->peer, mb, tc->sock->uh); + err = tc->sock->sendh(tc, &tc->peer, mb, tc->arg); mem_deref(mb); @@ -143,7 +145,17 @@ static long bio_ctrl(BIO *b, int cmd, long num, void *ptr) #if defined (BIO_CTRL_DGRAM_QUERY_MTU) case BIO_CTRL_DGRAM_QUERY_MTU: - return tc ? tc->sock->mtu : MTU_DEFAULT; + if (tc) { + if (tc->sock->mtuh) { + return tc->sock->mtuh(tc, tc->arg); + } + else { + return tc->sock->mtu; + } + } + else { + return MTU_DEFAULT; + } #endif #if defined (BIO_CTRL_DGRAM_GET_FALLBACK_MTU) @@ -710,6 +722,13 @@ static struct tls_conn *conn_lookup(struct dtls_sock *sock, } +static int send_handler(struct tls_conn *tc, const struct sa *dst, + struct mbuf *mb, void *arg) { + (void)arg; + return udp_send_helper(tc->sock->us, dst, mb, tc->sock->uh); +} + + static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct dtls_sock *sock = arg; @@ -742,6 +761,18 @@ static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) } +/** + * Feed data to a DTLS socket + * + * @param sock DTLS socket + * @param src Source address + * @param mb Buffer to receive + */ +void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb) { + recv_handler(src, mb, sock); +} + + /** * Create DTLS Socket * @@ -789,6 +820,54 @@ int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, sock->mtu = MTU_DEFAULT; sock->connh = connh; + sock->sendh = send_handler; + sock->arg = arg; + + out: + if (err) + mem_deref(sock); + else + *sockp = sock; + + return err; +} + + +/** + * Create a DTLS Socket without using an UDP socket underneath + * + * @param sockp Pointer to returned DTLS Socket + * @param htsize Connection hash table size. Set to 0 if one DTLS session shall + * be used for all peers. + * @param connh Connect handler + * @param sendh Send handler + * @param mtuh MTU handler + * @param arg Handler argument + * + * @return 0 if success, otherwise errorcode + */ +int dtls_socketless(struct dtls_sock **sockp, uint32_t htsize, + dtls_conn_h *connh, dtls_send_h *sendh, dtls_mtu_h *mtuh, + void *arg) +{ + struct dtls_sock *sock; + int err; + + if (!sockp || !sendh) + return EINVAL; + + sock = mem_zalloc(sizeof(*sock), sock_destructor); + if (!sock) + return ENOMEM; + + err = hash_alloc(&sock->ht, hash_valid_size(htsize)); + if (err) + goto out; + + sock->mtu = MTU_DEFAULT; + sock->connh = connh; + sock->sendh = sendh; + sock->mtuh = mtuh; sock->arg = arg; out: From b3beb212eaf503522351287e1f82ccc0e6415826 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 1 Mar 2017 01:41:59 +0100 Subject: [PATCH 02/36] Raise FD_EXCEPT on EPOLLHUP (fixes closed pipes) --- src/main/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/main.c b/src/main/main.c index 3c25ffed..60f29a5f 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -790,6 +790,8 @@ static int fd_poll(struct re *re) flags |= FD_WRITE; if (re->events[i].events & EPOLLERR) flags |= FD_EXCEPT; + if (re->events[i].events & EPOLLHUP) + flags |= FD_EXCEPT; if (!flags) { DEBUG_WARNING("epoll: no flags fd=%d\n", fd); From f05afb5bed0121947e04cdbde5ba5fa67919ce34 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 21 Oct 2016 01:02:28 +0200 Subject: [PATCH 03/36] Add the possibility to set Diffie-Hellman parameters Add `tls_set_dh_params_pem` and `tls_set_dh_params_der` function --- include/re_tls.h | 2 + src/tls/openssl/tls.c | 153 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) diff --git a/include/re_tls.h b/include/re_tls.h index aa45f603..7907f6ec 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -54,6 +54,8 @@ int tls_srtp_keyinfo(const struct tls_conn *tc, enum srtp_suite *suite, uint8_t *srv_key, size_t srv_key_size); const char *tls_cipher_name(const struct tls_conn *tc); int tls_set_ciphers(struct tls *tls, const char *cipherv[], size_t count); +int tls_set_dh_params_pem(struct tls *tls, const char *pem, size_t len); +int tls_set_dh_params_der(struct tls *tls, const uint8_t *der, size_t len); int tls_set_servername(struct tls_conn *tc, const char *servername); diff --git a/src/tls/openssl/tls.c b/src/tls/openssl/tls.c index c82d9375..fabf3066 100644 --- a/src/tls/openssl/tls.c +++ b/src/tls/openssl/tls.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -853,6 +855,157 @@ int tls_set_ciphers(struct tls *tls, const char *cipherv[], size_t count) } +static int set_dh_params(struct tls *tls, DH *dh) +{ + int codes, r; +#if OPENSSL_VERSION_NUMBER < 0x1000200fL + EC_KEY *ec_key; +#endif + + if (!DH_check(dh, &codes)) + return ENOMEM; + if (codes) { +#if defined(DH_CHECK_P_NOT_PRIME) + if (codes & DH_CHECK_P_NOT_PRIME) + DEBUG_WARNING("set_dh_params: p is not prime\n"); +#endif +#if defined(DH_CHECK_P_NOT_SAFE_PRIME) + if (codes & DH_CHECK_P_NOT_SAFE_PRIME) + DEBUG_WARNING("set_dh_params: p is not safe prime\n"); +#endif +#if defined(DH_UNABLE_TO_CHECK_GENERATOR) + if (codes & DH_UNABLE_TO_CHECK_GENERATOR) + DEBUG_WARNING("set_dh_params: generator g " + "cannot be checked\n"); +#endif +#if defined(DH_NOT_SUITABLE_GENERATOR) + if (codes & DH_NOT_SUITABLE_GENERATOR) + DEBUG_WARNING("set_dh_params: generator g " + "is not suitable\n"); +#endif +#if defined(DH_CHECK_Q_NOT_PRIME) + if (codes & DH_CHECK_Q_NOT_PRIME) + DEBUG_WARNING("set_dh_params: q is not prime\n"); +#endif +#if defined(DH_CHECK_INVALID_Q_VALUE) + if (codes & DH_CHECK_INVALID_Q_VALUE) + DEBUG_WARNING("set_dh_params: q is invalid\n"); +#endif +#if defined(DH_CHECK_INVALID_J_VALUE) + if (codes & DH_CHECK_INVALID_J_VALUE) + DEBUG_WARNING("set_dh_params: j is invalid\n"); +#endif + return EINVAL; + } + + if (!SSL_CTX_set_tmp_dh(tls->ctx, dh)) { + DEBUG_WARNING("set_dh_params: set_tmp_dh failed\n"); + return ENOMEM; + } + +#if OPENSSL_VERSION_NUMBER >= 0x1000200fL + r = SSL_CTX_set_ecdh_auto(tls->ctx, 1); + if (!r) { + DEBUG_WARNING("set_dh_params: set_ecdh_auto failed\n"); + return ENOMEM; + } +#else + ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (!ec_key) + return ENOMEM; + r = SSL_CTX_set_tmp_ecdh(tls->ctx, ec_key); + EC_KEY_free(ec_key); + if (!r) { + DEBUG_WARNING("set_dh_params: set_tmp_ecdh failed\n"); + return ENOMEM; + } +#endif + + return 0; +} + + +/** + * Set Diffie-Hellman parameters on a TLS context + * + * @param tls TLS Context + * @param pem Diffie-Hellman parameters in PEM format + * @param len Length of PEM string + * + * @return 0 if success, otherwise errorcode + */ +int tls_set_dh_params_pem(struct tls *tls, const char *pem, size_t len) +{ + BIO *bio = NULL; + DH *dh = NULL; + int err = ENOMEM; + + if (!tls || !pem || !len) + return EINVAL; + + bio = BIO_new_mem_buf((char *)pem, (int)len); + if (!bio) + goto out; + + dh = PEM_read_bio_DHparams(bio, NULL, 0, NULL); + if (!dh) + goto out; + + err = set_dh_params(tls, dh); + if (err) + goto out; + + err = 0; + + out: + if (dh) + DH_free(dh); + if (bio) + BIO_free(bio); + if (err) + ERR_clear_error(); + + return err; +} + + +/** + * Set Diffie-Hellman parameters on a TLS context + * + * @param tls TLS Context + * @param der Diffie-Hellman parameters in DER format + * @param len Length of DER bytes + * + * @return 0 if success, otherwise errorcode + */ +int tls_set_dh_params_der(struct tls *tls, const uint8_t *der, size_t len) +{ + DH *dh = NULL; + int err = ENOMEM; + + if (!tls || !der || !len) + return EINVAL; + + dh = d2i_DHparams(NULL, &der, len); + if (!dh) + goto out; + + err = set_dh_params(tls, dh); + if (err) + goto out; + + err = 0; + + out: + if (dh) + DH_free(dh); + if (err) + ERR_clear_error(); + + return err; +} + + /** * Set the server name on a TLS Connection, using TLS SNI extension. * From ddc1ab1c9247d7f0f15315a052143435cb4ad0fa Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 22 Mar 2017 16:25:01 +0100 Subject: [PATCH 04/36] Add Libs.private to pkg-config file Allow users to specify `PREFIX` in Makefile Allow users to specify the OpenSSL sysroot as `OPENSSL_SYSROOT` in Makefile --- Makefile | 3 +++ mk/re.mk | 15 +++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 9f468d36..4ea0f3bc 100644 --- a/Makefile +++ b/Makefile @@ -34,11 +34,13 @@ MODULES += odict MODULES += json INSTALL := install +ifndef PREFIX ifeq ($(DESTDIR),) PREFIX := /usr/local else PREFIX := /usr endif +endif ifeq ($(LIBDIR),) LIBDIR := $(PREFIX)/lib endif @@ -85,6 +87,7 @@ libre.pc: @echo 'Version: '$(VERSION) >> libre.pc @echo 'URL: http://creytiv.com/re.html' >> libre.pc @echo 'Libs: -L$${libdir} -lre' >> libre.pc + @echo 'Libs.private: -L$${libdir} -lre ${LIBS}' >> libre.pc @echo 'Cflags: -I$${includedir}' >> libre.pc $(BUILD)/%.o: src/%.c $(BUILD) Makefile $(MK) $(MODMKS) diff --git a/mk/re.mk b/mk/re.mk index 3ba29a0e..e15e052c 100644 --- a/mk/re.mk +++ b/mk/re.mk @@ -459,8 +459,11 @@ endif # External libraries section # -USE_OPENSSL := $(shell [ -f $(SYSROOT)/include/openssl/ssl.h ] || \ - [ -f $(SYSROOT)/local/include/openssl/ssl.h ] || \ +ifeq ($(OPENSSL_SYSROOT),) +OPENSSL_SYSROOT := $(SYSROOT) +endif +USE_OPENSSL := $(shell [ -f $(OPENSSL_SYSROOT)/include/openssl/ssl.h ] || \ + [ -f $(OPENSSL_SYSROOT)/local/include/openssl/ssl.h ] || \ [ -f $(SYSROOT_ALT)/include/openssl/ssl.h ] && echo "yes") ifneq ($(USE_OPENSSL),) @@ -468,12 +471,12 @@ CFLAGS += -DUSE_OPENSSL -DUSE_TLS LIBS += -lssl -lcrypto USE_TLS := yes -USE_OPENSSL_DTLS := $(shell [ -f $(SYSROOT)/include/openssl/dtls1.h ] || \ - [ -f $(SYSROOT)/local/include/openssl/dtls1.h ] || \ +USE_OPENSSL_DTLS := $(shell [ -f $(OPENSSL_SYSROOT)/include/openssl/dtls1.h ] || \ + [ -f $(OPENSSL_SYSROOT)/local/include/openssl/dtls1.h ] || \ [ -f $(SYSROOT_ALT)/include/openssl/dtls1.h ] && echo "yes") -USE_OPENSSL_SRTP := $(shell [ -f $(SYSROOT)/include/openssl/srtp.h ] || \ - [ -f $(SYSROOT)/local/include/openssl/srtp.h ] || \ +USE_OPENSSL_SRTP := $(shell [ -f $(OPENSSL_SYSROOT)/include/openssl/srtp.h ] || \ + [ -f $(OPENSSL_SYSROOT)/local/include/openssl/srtp.h ] || \ [ -f $(SYSROOT_ALT)/include/openssl/srtp.h ] && echo "yes") ifneq ($(USE_OPENSSL_DTLS),) From 69da9f16f314fc7e8dab9821bf257182daafef97 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 22 Mar 2017 17:20:03 +0100 Subject: [PATCH 05/36] Add install-static option to Makefile --- Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile b/Makefile index 4ea0f3bc..86680784 100644 --- a/Makefile +++ b/Makefile @@ -115,6 +115,15 @@ install: $(SHARED) $(STATIC) libre.pc $(INSTALL) -m 0644 libre.pc $(DESTDIR)$(LIBDIR)/pkgconfig $(INSTALL) -m 0644 $(MK) $(DESTDIR)$(MKDIR) +install-static: $(STATIC) libre.pc + @mkdir -p $(DESTDIR)$(LIBDIR) $(DESTDIR)$(LIBDIR)/pkgconfig \ + $(DESTDIR)$(INCDIR) $(DESTDIR)$(MKDIR) + $(INSTALL) -m 0644 $(shell find include -name "*.h") \ + $(DESTDIR)$(INCDIR) + $(INSTALL) -m 0755 $(STATIC) $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 0644 libre.pc $(DESTDIR)$(LIBDIR)/pkgconfig + $(INSTALL) -m 0644 $(MK) $(DESTDIR)$(MKDIR) + uninstall: @rm -rf $(DESTDIR)$(INCDIR) @rm -rf $(DESTDIR)$(MKDIR) From 24ac34c83df1fbfdf93c417357308e7a68e5a87f Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 22 Mar 2017 17:41:12 +0100 Subject: [PATCH 06/36] Print OpenSSL sysroot on make info --- mk/re.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/mk/re.mk b/mk/re.mk index e15e052c..02271ec1 100644 --- a/mk/re.mk +++ b/mk/re.mk @@ -693,6 +693,7 @@ info: @echo " USE_OPENSSL: $(USE_OPENSSL)" @echo " USE_OPENSSL_AES: $(USE_OPENSSL_AES)" @echo " USE_OPENSSL_HMAC: $(USE_OPENSSL_HMAC)" + @echo " OPENSSL_SYSROOT: $(OPENSSL_SYSROOT)" @echo " USE_TLS: $(USE_TLS)" @echo " USE_DTLS: $(USE_DTLS)" @echo " USE_DTLS_SRTP: $(USE_DTLS_SRTP)" From 0071283e0e8041fbdc5ce8153befbb33bed244d2 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 22 Mar 2017 19:26:27 +0100 Subject: [PATCH 07/36] Fix add include and libs directory when using `OPENSSL_SYSROOT` --- mk/re.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mk/re.mk b/mk/re.mk index 02271ec1..c0ef6720 100644 --- a/mk/re.mk +++ b/mk/re.mk @@ -60,6 +60,10 @@ ifeq ($(SYSROOT_ALT),) SYSROOT_ALT := $(shell [ -d /opt/local/include ] && echo "/opt/local") endif +ifneq ($(OPENSSL_SYSROOT),) +CFLAGS += -I$(OPENSSL_SYSROOT)/include +LFLAGS += -L$(OPENSSL_SYSROOT)/lib +endif ifneq ($(SYSROOT_ALT),) CFLAGS += -I$(SYSROOT_ALT)/include LFLAGS += -L$(SYSROOT_ALT)/lib From 29b5a2b75627c9fbfb06bb452a7fa67d103afb9d Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 22 Mar 2017 19:40:57 +0100 Subject: [PATCH 08/36] Remove `OPENSSL_SYSROOT` (`SYSROOT_ALT` should be sufficient) --- mk/re.mk | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/mk/re.mk b/mk/re.mk index c0ef6720..3ba29a0e 100644 --- a/mk/re.mk +++ b/mk/re.mk @@ -60,10 +60,6 @@ ifeq ($(SYSROOT_ALT),) SYSROOT_ALT := $(shell [ -d /opt/local/include ] && echo "/opt/local") endif -ifneq ($(OPENSSL_SYSROOT),) -CFLAGS += -I$(OPENSSL_SYSROOT)/include -LFLAGS += -L$(OPENSSL_SYSROOT)/lib -endif ifneq ($(SYSROOT_ALT),) CFLAGS += -I$(SYSROOT_ALT)/include LFLAGS += -L$(SYSROOT_ALT)/lib @@ -463,11 +459,8 @@ endif # External libraries section # -ifeq ($(OPENSSL_SYSROOT),) -OPENSSL_SYSROOT := $(SYSROOT) -endif -USE_OPENSSL := $(shell [ -f $(OPENSSL_SYSROOT)/include/openssl/ssl.h ] || \ - [ -f $(OPENSSL_SYSROOT)/local/include/openssl/ssl.h ] || \ +USE_OPENSSL := $(shell [ -f $(SYSROOT)/include/openssl/ssl.h ] || \ + [ -f $(SYSROOT)/local/include/openssl/ssl.h ] || \ [ -f $(SYSROOT_ALT)/include/openssl/ssl.h ] && echo "yes") ifneq ($(USE_OPENSSL),) @@ -475,12 +468,12 @@ CFLAGS += -DUSE_OPENSSL -DUSE_TLS LIBS += -lssl -lcrypto USE_TLS := yes -USE_OPENSSL_DTLS := $(shell [ -f $(OPENSSL_SYSROOT)/include/openssl/dtls1.h ] || \ - [ -f $(OPENSSL_SYSROOT)/local/include/openssl/dtls1.h ] || \ +USE_OPENSSL_DTLS := $(shell [ -f $(SYSROOT)/include/openssl/dtls1.h ] || \ + [ -f $(SYSROOT)/local/include/openssl/dtls1.h ] || \ [ -f $(SYSROOT_ALT)/include/openssl/dtls1.h ] && echo "yes") -USE_OPENSSL_SRTP := $(shell [ -f $(OPENSSL_SYSROOT)/include/openssl/srtp.h ] || \ - [ -f $(OPENSSL_SYSROOT)/local/include/openssl/srtp.h ] || \ +USE_OPENSSL_SRTP := $(shell [ -f $(SYSROOT)/include/openssl/srtp.h ] || \ + [ -f $(SYSROOT)/local/include/openssl/srtp.h ] || \ [ -f $(SYSROOT_ALT)/include/openssl/srtp.h ] && echo "yes") ifneq ($(USE_OPENSSL_DTLS),) @@ -697,7 +690,6 @@ info: @echo " USE_OPENSSL: $(USE_OPENSSL)" @echo " USE_OPENSSL_AES: $(USE_OPENSSL_AES)" @echo " USE_OPENSSL_HMAC: $(USE_OPENSSL_HMAC)" - @echo " OPENSSL_SYSROOT: $(OPENSSL_SYSROOT)" @echo " USE_TLS: $(USE_TLS)" @echo " USE_DTLS: $(USE_DTLS)" @echo " USE_DTLS_SRTP: $(USE_DTLS_SRTP)" From 6abcc92ed2207a310a577f0190e5f482af062401 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 22 Mar 2017 19:51:42 +0100 Subject: [PATCH 09/36] Explicitly use `long` as value for `SSL_CTX_set_ecdh_auto` call --- src/tls/openssl/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tls/openssl/tls.c b/src/tls/openssl/tls.c index fabf3066..380e95bd 100644 --- a/src/tls/openssl/tls.c +++ b/src/tls/openssl/tls.c @@ -904,7 +904,7 @@ static int set_dh_params(struct tls *tls, DH *dh) } #if OPENSSL_VERSION_NUMBER >= 0x1000200fL - r = SSL_CTX_set_ecdh_auto(tls->ctx, 1); + r = SSL_CTX_set_ecdh_auto(tls->ctx, (long) 1); if (!r) { DEBUG_WARNING("set_dh_params: set_ecdh_auto failed\n"); return ENOMEM; From 3762eb8d08252a56691b8ba35e18985f4b76801f Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Sun, 26 Mar 2017 13:04:01 +0200 Subject: [PATCH 10/36] Fix use `long` for `SSL_CTX_set_ecdh_auto` and `SSL_CTX_set_tmp_ecdh` return values --- src/tls/openssl/tls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tls/openssl/tls.c b/src/tls/openssl/tls.c index 380e95bd..3f7e6826 100644 --- a/src/tls/openssl/tls.c +++ b/src/tls/openssl/tls.c @@ -857,7 +857,8 @@ int tls_set_ciphers(struct tls *tls, const char *cipherv[], size_t count) static int set_dh_params(struct tls *tls, DH *dh) { - int codes, r; + int codes; + long r; #if OPENSSL_VERSION_NUMBER < 0x1000200fL EC_KEY *ec_key; #endif From ecc1a62f5adb49a7dbb50944e9d3065262fc54e9 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Mon, 27 Mar 2017 22:01:07 +0200 Subject: [PATCH 11/36] Handle %h prefixed (short) types in formatter functions --- src/fmt/print.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/fmt/print.c b/src/fmt/print.c index 50872ded..dd1a018d 100644 --- a/src/fmt/print.c +++ b/src/fmt/print.c @@ -299,6 +299,11 @@ int re_vhprintf(const char *fmt, va_list ap, re_vprintf_h *vph, void *arg) } break; + case 'h': + lenmod = LENMOD_NONE; + fm = true; + break; + case 'H': ph = va_arg(ap, re_printf_h *); ph_arg = va_arg(ap, void *); From 5bedf3b2c42c16079d3e9578b027ae738652df0e Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Thu, 6 Apr 2017 14:32:10 +0200 Subject: [PATCH 12/36] Allow 'c='-line in SPD media to be explicitly set to unspecified --- src/sdp/media.c | 1 + src/sdp/msg.c | 2 +- src/sdp/sdp.h | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/sdp/media.c b/src/sdp/media.c index 07ce3a27..d16d3aba 100644 --- a/src/sdp/media.c +++ b/src/sdp/media.c @@ -446,6 +446,7 @@ void sdp_media_set_laddr(struct sdp_media *m, const struct sa *laddr) if (!m || !laddr) return; + m->flags |= MEDIA_LADDR_SET; m->laddr = *laddr; } diff --git a/src/sdp/msg.c b/src/sdp/msg.c index c1a8bbce..58834c9f 100644 --- a/src/sdp/msg.c +++ b/src/sdp/msg.c @@ -398,7 +398,7 @@ static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer) err |= mbuf_write_str(mb, "\r\n"); - if (sa_isset(&m->laddr, SA_ADDR)) { + if (m->flags & MEDIA_LADDR_SET) { const int ipver = sa_af(&m->laddr) == AF_INET ? 4 : 6; err |= mbuf_printf(mb, "c=IN IP%d %j\r\n", ipver, &m->laddr); } diff --git a/src/sdp/sdp.h b/src/sdp/sdp.h index f0588d1f..d4462ab8 100644 --- a/src/sdp/sdp.h +++ b/src/sdp/sdp.h @@ -10,6 +10,10 @@ enum { RTP_DYNPT_END = 127, }; +enum { + MEDIA_LADDR_SET = 1<<0, +}; + struct sdp_session { struct list lmedial; @@ -27,6 +31,7 @@ struct sdp_session { struct sdp_media { struct le le; + uint8_t flags; struct list lfmtl; struct list rfmtl; struct list lattrl; From 8aca84a343ed571e06b8ef547ca0d64ad159505c Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 7 Apr 2017 18:59:58 +0200 Subject: [PATCH 13/36] Allow to exclude direction attribute --- include/re_sdp.h | 1 + src/sdp/media.c | 19 +++++++++++++++++++ src/sdp/msg.c | 6 ++++-- src/sdp/sdp.h | 1 + 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/re_sdp.h b/include/re_sdp.h index f34bab5d..457cb4d9 100644 --- a/include/re_sdp.h +++ b/include/re_sdp.h @@ -99,6 +99,7 @@ void sdp_media_set_lbandwidth(struct sdp_media *m, enum sdp_bandwidth type, void sdp_media_set_lport_rtcp(struct sdp_media *m, uint16_t port); void sdp_media_set_laddr_rtcp(struct sdp_media *m, const struct sa *laddr); void sdp_media_set_ldir(struct sdp_media *m, enum sdp_dir dir); +void sdp_media_ldir_exclude(struct sdp_media *m, bool exclude); int sdp_media_set_lattr(struct sdp_media *m, bool replace, const char *name, const char *value, ...); void sdp_media_del_lattr(struct sdp_media *m, const char *name); diff --git a/src/sdp/media.c b/src/sdp/media.c index d16d3aba..05e769c9 100644 --- a/src/sdp/media.c +++ b/src/sdp/media.c @@ -513,6 +513,25 @@ void sdp_media_set_ldir(struct sdp_media *m, enum sdp_dir dir) } +/** + * Set whether the local direction flag of an SDP media line should be excluded + * when encoding. Defaults to false. + * + * @param m SDP Media line + * @param exclude Exclude direction flag + */ +void sdp_media_ldir_exclude(struct sdp_media *m, bool exclude) +{ + if (!m) + return; + + if (exclude) + m->flags |= MEDIA_LDIR_EXCLUDE; + else + m->flags &= ~MEDIA_LDIR_EXCLUDE; +} + + /** * Set a local attribute of an SDP Media line * diff --git a/src/sdp/msg.c b/src/sdp/msg.c index 58834c9f..82b89055 100644 --- a/src/sdp/msg.c +++ b/src/sdp/msg.c @@ -443,8 +443,10 @@ static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer) err |= mbuf_printf(mb, "a=rtcp:%u\r\n", sa_port(&m->laddr_rtcp)); - err |= mbuf_printf(mb, "a=%s\r\n", - sdp_dir_name(offer ? m->ldir : m->ldir & m->rdir)); + if (!(m->flags & MEDIA_LDIR_EXCLUDE)) + err |= mbuf_printf(mb, "a=%s\r\n", + sdp_dir_name(offer ? m->ldir : + m->ldir & m->rdir)); for (le = m->lattrl.head; le; le = le->next) err |= mbuf_printf(mb, "%H", sdp_attr_print, le->data); diff --git a/src/sdp/sdp.h b/src/sdp/sdp.h index d4462ab8..604082a5 100644 --- a/src/sdp/sdp.h +++ b/src/sdp/sdp.h @@ -12,6 +12,7 @@ enum { enum { MEDIA_LADDR_SET = 1<<0, + MEDIA_LDIR_EXCLUDE = 1<<1, }; From 35f6d0bfc5ed9a908e20ccf8ba32c757bf5954f4 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Tue, 11 Apr 2017 13:31:45 +0200 Subject: [PATCH 14/36] Less code duplication --- Makefile | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 86680784..17898b27 100644 --- a/Makefile +++ b/Makefile @@ -105,16 +105,6 @@ clean: @rm -rf $(SHARED) $(STATIC) libre.pc test.d test.o test $(BUILD) -install: $(SHARED) $(STATIC) libre.pc - @mkdir -p $(DESTDIR)$(LIBDIR) $(DESTDIR)$(LIBDIR)/pkgconfig \ - $(DESTDIR)$(INCDIR) $(DESTDIR)$(MKDIR) - $(INSTALL) -m 0644 $(shell find include -name "*.h") \ - $(DESTDIR)$(INCDIR) - $(INSTALL) -m 0755 $(SHARED) $(DESTDIR)$(LIBDIR) - $(INSTALL) -m 0755 $(STATIC) $(DESTDIR)$(LIBDIR) - $(INSTALL) -m 0644 libre.pc $(DESTDIR)$(LIBDIR)/pkgconfig - $(INSTALL) -m 0644 $(MK) $(DESTDIR)$(MKDIR) - install-static: $(STATIC) libre.pc @mkdir -p $(DESTDIR)$(LIBDIR) $(DESTDIR)$(LIBDIR)/pkgconfig \ $(DESTDIR)$(INCDIR) $(DESTDIR)$(MKDIR) @@ -124,6 +114,9 @@ install-static: $(STATIC) libre.pc $(INSTALL) -m 0644 libre.pc $(DESTDIR)$(LIBDIR)/pkgconfig $(INSTALL) -m 0644 $(MK) $(DESTDIR)$(MKDIR) +install: install-static $(SHARED) libre.pc + $(INSTALL) -m 0755 $(SHARED) $(DESTDIR)$(LIBDIR) + uninstall: @rm -rf $(DESTDIR)$(INCDIR) @rm -rf $(DESTDIR)$(MKDIR) From c12309ad6ed5fe0775201df941e2f00c34100ecd Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 28 Apr 2017 13:40:45 +0200 Subject: [PATCH 15/36] Use `PREFIX ?= ...` instead of `ifndef` --- Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 17898b27..4deaf70b 100644 --- a/Makefile +++ b/Makefile @@ -34,12 +34,10 @@ MODULES += odict MODULES += json INSTALL := install -ifndef PREFIX ifeq ($(DESTDIR),) -PREFIX := /usr/local +PREFIX ?= /usr/local else -PREFIX := /usr -endif +PREFIX ?= /usr endif ifeq ($(LIBDIR),) LIBDIR := $(PREFIX)/lib From 3844e14f29e45540b0bb0357a38580936b255143 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Tue, 11 Apr 2017 13:31:45 +0200 Subject: [PATCH 16/36] Less code duplication --- Makefile | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 86680784..17898b27 100644 --- a/Makefile +++ b/Makefile @@ -105,16 +105,6 @@ clean: @rm -rf $(SHARED) $(STATIC) libre.pc test.d test.o test $(BUILD) -install: $(SHARED) $(STATIC) libre.pc - @mkdir -p $(DESTDIR)$(LIBDIR) $(DESTDIR)$(LIBDIR)/pkgconfig \ - $(DESTDIR)$(INCDIR) $(DESTDIR)$(MKDIR) - $(INSTALL) -m 0644 $(shell find include -name "*.h") \ - $(DESTDIR)$(INCDIR) - $(INSTALL) -m 0755 $(SHARED) $(DESTDIR)$(LIBDIR) - $(INSTALL) -m 0755 $(STATIC) $(DESTDIR)$(LIBDIR) - $(INSTALL) -m 0644 libre.pc $(DESTDIR)$(LIBDIR)/pkgconfig - $(INSTALL) -m 0644 $(MK) $(DESTDIR)$(MKDIR) - install-static: $(STATIC) libre.pc @mkdir -p $(DESTDIR)$(LIBDIR) $(DESTDIR)$(LIBDIR)/pkgconfig \ $(DESTDIR)$(INCDIR) $(DESTDIR)$(MKDIR) @@ -124,6 +114,9 @@ install-static: $(STATIC) libre.pc $(INSTALL) -m 0644 libre.pc $(DESTDIR)$(LIBDIR)/pkgconfig $(INSTALL) -m 0644 $(MK) $(DESTDIR)$(MKDIR) +install: install-static $(SHARED) libre.pc + $(INSTALL) -m 0755 $(SHARED) $(DESTDIR)$(LIBDIR) + uninstall: @rm -rf $(DESTDIR)$(INCDIR) @rm -rf $(DESTDIR)$(MKDIR) From 728577bbaa21d407cfa429f0f7cc342a32c81095 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 28 Apr 2017 13:40:45 +0200 Subject: [PATCH 17/36] Use `PREFIX ?= ...` instead of `ifndef` --- Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 17898b27..4deaf70b 100644 --- a/Makefile +++ b/Makefile @@ -34,12 +34,10 @@ MODULES += odict MODULES += json INSTALL := install -ifndef PREFIX ifeq ($(DESTDIR),) -PREFIX := /usr/local +PREFIX ?= /usr/local else -PREFIX := /usr -endif +PREFIX ?= /usr endif ifeq ($(LIBDIR),) LIBDIR := $(PREFIX)/lib From 93b3fa3d9beaa5cdde391d84fcb1501cf114c918 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 28 Apr 2017 14:04:35 +0200 Subject: [PATCH 18/36] Remove `install-static` target --- Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 4deaf70b..65cf499b 100644 --- a/Makefile +++ b/Makefile @@ -103,18 +103,16 @@ clean: @rm -rf $(SHARED) $(STATIC) libre.pc test.d test.o test $(BUILD) -install-static: $(STATIC) libre.pc +install: $(SHARED) $(STATIC) libre.pc @mkdir -p $(DESTDIR)$(LIBDIR) $(DESTDIR)$(LIBDIR)/pkgconfig \ $(DESTDIR)$(INCDIR) $(DESTDIR)$(MKDIR) $(INSTALL) -m 0644 $(shell find include -name "*.h") \ $(DESTDIR)$(INCDIR) + $(INSTALL) -m 0755 $(SHARED) $(DESTDIR)$(LIBDIR) $(INSTALL) -m 0755 $(STATIC) $(DESTDIR)$(LIBDIR) $(INSTALL) -m 0644 libre.pc $(DESTDIR)$(LIBDIR)/pkgconfig $(INSTALL) -m 0644 $(MK) $(DESTDIR)$(MKDIR) -install: install-static $(SHARED) libre.pc - $(INSTALL) -m 0755 $(SHARED) $(DESTDIR)$(LIBDIR) - uninstall: @rm -rf $(DESTDIR)$(INCDIR) @rm -rf $(DESTDIR)$(MKDIR) From 1c365017ae1010de84defee01e5957bdfecbb8f5 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 1 Mar 2017 01:41:59 +0100 Subject: [PATCH 19/36] Raise FD_EXCEPT on EPOLLHUP (fixes closed pipes) --- src/main/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/main.c b/src/main/main.c index 762b0b4f..3453ebd3 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -786,6 +786,8 @@ static int fd_poll(struct re *re) flags |= FD_WRITE; if (re->events[i].events & EPOLLERR) flags |= FD_EXCEPT; + if (re->events[i].events & EPOLLHUP) + flags |= FD_EXCEPT; if (!flags) { DEBUG_WARNING("epoll: no flags fd=%d\n", fd); From 57ca16a93d32906ba33cb4db99b2123bb9251869 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Mon, 31 Oct 2016 15:20:12 +0100 Subject: [PATCH 20/36] Make it possible to create a DTLS socket without having an UDP socket underneath. Add `dtls_send_h` and `dtls_mtu_h` for DTLS in UDP socketless mode Add `dtls_socketless` and `dtls_receive` function Add `sendh` and `mtuh` fields to `struct dtls_socket` --- include/re_tls.h | 7 ++++ src/tls/openssl/tls_udp.c | 83 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/include/re_tls.h b/include/re_tls.h index aa45f603..538bdb86 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -66,6 +66,9 @@ int tls_start_tcp(struct tls_conn **ptc, struct tls *tls, /* UDP (DTLS) */ typedef void (dtls_conn_h)(const struct sa *peer, void *arg); +typedef int (dtls_send_h)(struct tls_conn *tc, const struct sa *dst, + struct mbuf *mb, void *arg); +typedef size_t (dtls_mtu_h)(struct tls_conn *tc, void *arg); typedef void (dtls_estab_h)(void *arg); typedef void (dtls_recv_h)(struct mbuf *mb, void *arg); typedef void (dtls_close_h)(int err, void *arg); @@ -75,6 +78,9 @@ struct dtls_sock; int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, struct udp_sock *us, uint32_t htsize, int layer, dtls_conn_h *connh, void *arg); +int dtls_socketless(struct dtls_sock **sockp, uint32_t htsize, + dtls_conn_h *connh, dtls_send_h *sendh, dtls_mtu_h *mtuh, + void *arg); struct udp_sock *dtls_udp_sock(struct dtls_sock *sock); void dtls_set_mtu(struct dtls_sock *sock, size_t mtu); int dtls_connect(struct tls_conn **ptc, struct tls *tls, @@ -86,6 +92,7 @@ int dtls_accept(struct tls_conn **ptc, struct tls *tls, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); int dtls_send(struct tls_conn *tc, struct mbuf *mb); +void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb); void dtls_set_handlers(struct tls_conn *tc, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); const struct sa *dtls_peer(const struct tls_conn *tc); diff --git a/src/tls/openssl/tls_udp.c b/src/tls/openssl/tls_udp.c index e04cd873..449c1226 100644 --- a/src/tls/openssl/tls_udp.c +++ b/src/tls/openssl/tls_udp.c @@ -39,6 +39,8 @@ struct dtls_sock { struct hash *ht; struct mbuf *mb; dtls_conn_h *connh; + dtls_send_h *sendh; + dtls_mtu_h *mtuh; void *arg; size_t mtu; }; @@ -117,7 +119,7 @@ static int bio_write(BIO *b, const char *buf, int len) (void)mbuf_write_mem(mb, (void *)buf, len); mb->pos = SPACE; - err = udp_send_helper(tc->sock->us, &tc->peer, mb, tc->sock->uh); + err = tc->sock->sendh(tc, &tc->peer, mb, tc->arg); mem_deref(mb); @@ -143,7 +145,17 @@ static long bio_ctrl(BIO *b, int cmd, long num, void *ptr) #if defined (BIO_CTRL_DGRAM_QUERY_MTU) case BIO_CTRL_DGRAM_QUERY_MTU: - return tc ? tc->sock->mtu : MTU_DEFAULT; + if (tc) { + if (tc->sock->mtuh) { + return tc->sock->mtuh(tc, tc->arg); + } + else { + return tc->sock->mtu; + } + } + else { + return MTU_DEFAULT; + } #endif #if defined (BIO_CTRL_DGRAM_GET_FALLBACK_MTU) @@ -710,6 +722,13 @@ static struct tls_conn *conn_lookup(struct dtls_sock *sock, } +static int send_handler(struct tls_conn *tc, const struct sa *dst, + struct mbuf *mb, void *arg) { + (void)arg; + return udp_send_helper(tc->sock->us, dst, mb, tc->sock->uh); +} + + static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct dtls_sock *sock = arg; @@ -742,6 +761,18 @@ static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) } +/** + * Feed data to a DTLS socket + * + * @param sock DTLS socket + * @param src Source address + * @param mb Buffer to receive + */ +void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb) { + recv_handler(src, mb, sock); +} + + /** * Create DTLS Socket * @@ -789,6 +820,54 @@ int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, sock->mtu = MTU_DEFAULT; sock->connh = connh; + sock->sendh = send_handler; + sock->arg = arg; + + out: + if (err) + mem_deref(sock); + else + *sockp = sock; + + return err; +} + + +/** + * Create a DTLS Socket without using an UDP socket underneath + * + * @param sockp Pointer to returned DTLS Socket + * @param htsize Connection hash table size. Set to 0 if one DTLS session shall + * be used for all peers. + * @param connh Connect handler + * @param sendh Send handler + * @param mtuh MTU handler + * @param arg Handler argument + * + * @return 0 if success, otherwise errorcode + */ +int dtls_socketless(struct dtls_sock **sockp, uint32_t htsize, + dtls_conn_h *connh, dtls_send_h *sendh, dtls_mtu_h *mtuh, + void *arg) +{ + struct dtls_sock *sock; + int err; + + if (!sockp || !sendh) + return EINVAL; + + sock = mem_zalloc(sizeof(*sock), sock_destructor); + if (!sock) + return ENOMEM; + + err = hash_alloc(&sock->ht, hash_valid_size(htsize)); + if (err) + goto out; + + sock->mtu = MTU_DEFAULT; + sock->connh = connh; + sock->sendh = sendh; + sock->mtuh = mtuh; sock->arg = arg; out: From e2c464edbd4b9ea7f396277cbe90e9ca2f14af7e Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Thu, 6 Apr 2017 14:32:10 +0200 Subject: [PATCH 21/36] Allow 'c='-line in SPD media to be explicitly set to unspecified --- src/sdp/media.c | 1 + src/sdp/msg.c | 2 +- src/sdp/sdp.h | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/sdp/media.c b/src/sdp/media.c index 07ce3a27..d16d3aba 100644 --- a/src/sdp/media.c +++ b/src/sdp/media.c @@ -446,6 +446,7 @@ void sdp_media_set_laddr(struct sdp_media *m, const struct sa *laddr) if (!m || !laddr) return; + m->flags |= MEDIA_LADDR_SET; m->laddr = *laddr; } diff --git a/src/sdp/msg.c b/src/sdp/msg.c index c1a8bbce..58834c9f 100644 --- a/src/sdp/msg.c +++ b/src/sdp/msg.c @@ -398,7 +398,7 @@ static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer) err |= mbuf_write_str(mb, "\r\n"); - if (sa_isset(&m->laddr, SA_ADDR)) { + if (m->flags & MEDIA_LADDR_SET) { const int ipver = sa_af(&m->laddr) == AF_INET ? 4 : 6; err |= mbuf_printf(mb, "c=IN IP%d %j\r\n", ipver, &m->laddr); } diff --git a/src/sdp/sdp.h b/src/sdp/sdp.h index f0588d1f..d4462ab8 100644 --- a/src/sdp/sdp.h +++ b/src/sdp/sdp.h @@ -10,6 +10,10 @@ enum { RTP_DYNPT_END = 127, }; +enum { + MEDIA_LADDR_SET = 1<<0, +}; + struct sdp_session { struct list lmedial; @@ -27,6 +31,7 @@ struct sdp_session { struct sdp_media { struct le le; + uint8_t flags; struct list lfmtl; struct list rfmtl; struct list lattrl; From 625c78750ac8dfcd8b16539ca7b10d735f4affdd Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Thu, 6 Apr 2017 14:32:10 +0200 Subject: [PATCH 22/36] Allow 'c='-line in SPD media to be explicitly set to unspecified --- src/sdp/media.c | 1 + src/sdp/msg.c | 2 +- src/sdp/sdp.h | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/sdp/media.c b/src/sdp/media.c index 07ce3a27..d16d3aba 100644 --- a/src/sdp/media.c +++ b/src/sdp/media.c @@ -446,6 +446,7 @@ void sdp_media_set_laddr(struct sdp_media *m, const struct sa *laddr) if (!m || !laddr) return; + m->flags |= MEDIA_LADDR_SET; m->laddr = *laddr; } diff --git a/src/sdp/msg.c b/src/sdp/msg.c index c1a8bbce..58834c9f 100644 --- a/src/sdp/msg.c +++ b/src/sdp/msg.c @@ -398,7 +398,7 @@ static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer) err |= mbuf_write_str(mb, "\r\n"); - if (sa_isset(&m->laddr, SA_ADDR)) { + if (m->flags & MEDIA_LADDR_SET) { const int ipver = sa_af(&m->laddr) == AF_INET ? 4 : 6; err |= mbuf_printf(mb, "c=IN IP%d %j\r\n", ipver, &m->laddr); } diff --git a/src/sdp/sdp.h b/src/sdp/sdp.h index f0588d1f..d4462ab8 100644 --- a/src/sdp/sdp.h +++ b/src/sdp/sdp.h @@ -10,6 +10,10 @@ enum { RTP_DYNPT_END = 127, }; +enum { + MEDIA_LADDR_SET = 1<<0, +}; + struct sdp_session { struct list lmedial; @@ -27,6 +31,7 @@ struct sdp_session { struct sdp_media { struct le le; + uint8_t flags; struct list lfmtl; struct list rfmtl; struct list lattrl; From 0616c5ed56f238d28b88f804d6d3d01f569ab7aa Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 7 Apr 2017 18:59:58 +0200 Subject: [PATCH 23/36] Allow to exclude direction attribute --- include/re_sdp.h | 1 + src/sdp/media.c | 19 +++++++++++++++++++ src/sdp/msg.c | 6 ++++-- src/sdp/sdp.h | 1 + 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/re_sdp.h b/include/re_sdp.h index f34bab5d..457cb4d9 100644 --- a/include/re_sdp.h +++ b/include/re_sdp.h @@ -99,6 +99,7 @@ void sdp_media_set_lbandwidth(struct sdp_media *m, enum sdp_bandwidth type, void sdp_media_set_lport_rtcp(struct sdp_media *m, uint16_t port); void sdp_media_set_laddr_rtcp(struct sdp_media *m, const struct sa *laddr); void sdp_media_set_ldir(struct sdp_media *m, enum sdp_dir dir); +void sdp_media_ldir_exclude(struct sdp_media *m, bool exclude); int sdp_media_set_lattr(struct sdp_media *m, bool replace, const char *name, const char *value, ...); void sdp_media_del_lattr(struct sdp_media *m, const char *name); diff --git a/src/sdp/media.c b/src/sdp/media.c index d16d3aba..05e769c9 100644 --- a/src/sdp/media.c +++ b/src/sdp/media.c @@ -513,6 +513,25 @@ void sdp_media_set_ldir(struct sdp_media *m, enum sdp_dir dir) } +/** + * Set whether the local direction flag of an SDP media line should be excluded + * when encoding. Defaults to false. + * + * @param m SDP Media line + * @param exclude Exclude direction flag + */ +void sdp_media_ldir_exclude(struct sdp_media *m, bool exclude) +{ + if (!m) + return; + + if (exclude) + m->flags |= MEDIA_LDIR_EXCLUDE; + else + m->flags &= ~MEDIA_LDIR_EXCLUDE; +} + + /** * Set a local attribute of an SDP Media line * diff --git a/src/sdp/msg.c b/src/sdp/msg.c index 58834c9f..82b89055 100644 --- a/src/sdp/msg.c +++ b/src/sdp/msg.c @@ -443,8 +443,10 @@ static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer) err |= mbuf_printf(mb, "a=rtcp:%u\r\n", sa_port(&m->laddr_rtcp)); - err |= mbuf_printf(mb, "a=%s\r\n", - sdp_dir_name(offer ? m->ldir : m->ldir & m->rdir)); + if (!(m->flags & MEDIA_LDIR_EXCLUDE)) + err |= mbuf_printf(mb, "a=%s\r\n", + sdp_dir_name(offer ? m->ldir : + m->ldir & m->rdir)); for (le = m->lattrl.head; le; le = le->next) err |= mbuf_printf(mb, "%H", sdp_attr_print, le->data); diff --git a/src/sdp/sdp.h b/src/sdp/sdp.h index d4462ab8..604082a5 100644 --- a/src/sdp/sdp.h +++ b/src/sdp/sdp.h @@ -12,6 +12,7 @@ enum { enum { MEDIA_LADDR_SET = 1<<0, + MEDIA_LDIR_EXCLUDE = 1<<1, }; From 244e02fbecaf93320ce5ce268384854c7245a8c7 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 28 Jul 2017 14:41:15 +0200 Subject: [PATCH 24/36] Return whether the packet has been handled in `dtls_receive`. --- include/re_tls.h | 2 +- src/tls/openssl/tls_udp.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/re_tls.h b/include/re_tls.h index 538bdb86..518c74b3 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -92,7 +92,7 @@ int dtls_accept(struct tls_conn **ptc, struct tls *tls, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); int dtls_send(struct tls_conn *tc, struct mbuf *mb); -void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb); +bool dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb); void dtls_set_handlers(struct tls_conn *tc, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); const struct sa *dtls_peer(const struct tls_conn *tc); diff --git a/src/tls/openssl/tls_udp.c b/src/tls/openssl/tls_udp.c index 449c1226..9a5f9f78 100644 --- a/src/tls/openssl/tls_udp.c +++ b/src/tls/openssl/tls_udp.c @@ -767,9 +767,11 @@ static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) * @param sock DTLS socket * @param src Source address * @param mb Buffer to receive + * + * @return whether the packet has been handled. */ -void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb) { - recv_handler(src, mb, sock); +bool dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb) { + return recv_handler(src, mb, sock); } From 3a6d31425a335a3b8c516d953d9612a0b0fce979 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 28 Jul 2017 16:18:07 +0200 Subject: [PATCH 25/36] Make headroom of an outgoing DTLS packet configurable Add functions `dtls_headroom` and `dtls_set_headroom`. --- include/re_tls.h | 2 ++ src/tls/openssl/tls_udp.c | 48 +++++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/include/re_tls.h b/include/re_tls.h index aa45f603..e6ff1b9d 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -77,6 +77,8 @@ int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, dtls_conn_h *connh, void *arg); struct udp_sock *dtls_udp_sock(struct dtls_sock *sock); void dtls_set_mtu(struct dtls_sock *sock, size_t mtu); +size_t dtls_headroom(struct dtls_sock *sock); +void dtls_set_headroom(struct dtls_sock *sock, size_t headroom); int dtls_connect(struct tls_conn **ptc, struct tls *tls, struct dtls_sock *sock, const struct sa *peer, dtls_estab_h *estabh, dtls_recv_h *recvh, diff --git a/src/tls/openssl/tls_udp.c b/src/tls/openssl/tls_udp.c index e04cd873..abcaf56e 100644 --- a/src/tls/openssl/tls_udp.c +++ b/src/tls/openssl/tls_udp.c @@ -27,8 +27,9 @@ enum { - MTU_DEFAULT = 1400, - MTU_FALLBACK = 548, + MTU_DEFAULT = 1400, + MTU_FALLBACK = 548, + HEADROOM_DEFAULT = 4, }; @@ -41,6 +42,7 @@ struct dtls_sock { dtls_conn_h *connh; void *arg; size_t mtu; + size_t headroom; }; @@ -106,16 +108,15 @@ static int bio_write(BIO *b, const char *buf, int len) struct tls_conn *tc = b->ptr; #endif struct mbuf *mb; - enum {SPACE = 4}; int err; - mb = mbuf_alloc(SPACE + len); + mb = mbuf_alloc(tc->sock->headroom + len); if (!mb) return -1; - mb->pos = SPACE; + mb->pos = tc->sock->headroom; (void)mbuf_write_mem(mb, (void *)buf, len); - mb->pos = SPACE; + mb->pos = tc->sock->headroom; err = udp_send_helper(tc->sock->us, &tc->peer, mb, tc->sock->uh); @@ -787,9 +788,10 @@ int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, if (err) goto out; - sock->mtu = MTU_DEFAULT; - sock->connh = connh; - sock->arg = arg; + sock->mtu = MTU_DEFAULT; + sock->headroom = HEADROOM_DEFAULT; + sock->connh = connh; + sock->arg = arg; out: if (err) @@ -829,6 +831,34 @@ void dtls_set_mtu(struct dtls_sock *sock, size_t mtu) } +/* + * Get headroom of a DTLS Socket + * + * @param sock DTLS Socket + * + * @return Headroom value. + */ +size_t dtls_headroom(struct dtls_sock *sock) +{ + return sock ? sock->headroom : 0; +} + + +/** + * Set headroom on a DTLS Socket + * + * @param sock DTLS Socket + * @param headroom Headroom value + */ +void dtls_set_headroom(struct dtls_sock *sock, size_t headroom) +{ + if (!sock) + return; + + sock->headroom = headroom; +} + + #ifdef TLS_BIO_OPAQUE BIO_METHOD *tls_method_udp(void) { From fcb10a0f1d87741910adb52026495511ca16c0e5 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Mon, 31 Oct 2016 15:20:12 +0100 Subject: [PATCH 26/36] Make it possible to create a DTLS socket without having an UDP socket underneath. Add `dtls_send_h` and `dtls_mtu_h` for DTLS in UDP socketless mode Add `dtls_socketless` and `dtls_receive` function Add `sendh` and `mtuh` fields to `struct dtls_socket` --- include/re_tls.h | 7 ++++ src/tls/openssl/tls_udp.c | 83 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/include/re_tls.h b/include/re_tls.h index 050e0495..e97a7590 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -66,6 +66,9 @@ int tls_start_tcp(struct tls_conn **ptc, struct tls *tls, /* UDP (DTLS) */ typedef void (dtls_conn_h)(const struct sa *peer, void *arg); +typedef int (dtls_send_h)(struct tls_conn *tc, const struct sa *dst, + struct mbuf *mb, void *arg); +typedef size_t (dtls_mtu_h)(struct tls_conn *tc, void *arg); typedef void (dtls_estab_h)(void *arg); typedef void (dtls_recv_h)(struct mbuf *mb, void *arg); typedef void (dtls_close_h)(int err, void *arg); @@ -75,6 +78,9 @@ struct dtls_sock; int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, struct udp_sock *us, uint32_t htsize, int layer, dtls_conn_h *connh, void *arg); +int dtls_socketless(struct dtls_sock **sockp, uint32_t htsize, + dtls_conn_h *connh, dtls_send_h *sendh, dtls_mtu_h *mtuh, + void *arg); struct udp_sock *dtls_udp_sock(struct dtls_sock *sock); void dtls_set_mtu(struct dtls_sock *sock, size_t mtu); int dtls_connect(struct tls_conn **ptc, struct tls *tls, @@ -86,6 +92,7 @@ int dtls_accept(struct tls_conn **ptc, struct tls *tls, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); int dtls_send(struct tls_conn *tc, struct mbuf *mb); +void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb); void dtls_set_handlers(struct tls_conn *tc, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); const struct sa *dtls_peer(const struct tls_conn *tc); diff --git a/src/tls/openssl/tls_udp.c b/src/tls/openssl/tls_udp.c index 4ec81a30..368a4203 100644 --- a/src/tls/openssl/tls_udp.c +++ b/src/tls/openssl/tls_udp.c @@ -39,6 +39,8 @@ struct dtls_sock { struct hash *ht; struct mbuf *mb; dtls_conn_h *connh; + dtls_send_h *sendh; + dtls_mtu_h *mtuh; void *arg; size_t mtu; }; @@ -120,7 +122,7 @@ static int bio_write(BIO *b, const char *buf, int len) (void)mbuf_write_mem(mb, (void *)buf, len); mb->pos = SPACE; - err = udp_send_helper(tc->sock->us, &tc->peer, mb, tc->sock->uh); + err = tc->sock->sendh(tc, &tc->peer, mb, tc->arg); mem_deref(mb); @@ -146,7 +148,17 @@ static long bio_ctrl(BIO *b, int cmd, long num, void *ptr) #if defined (BIO_CTRL_DGRAM_QUERY_MTU) case BIO_CTRL_DGRAM_QUERY_MTU: - return tc ? tc->sock->mtu : MTU_DEFAULT; + if (tc) { + if (tc->sock->mtuh) { + return tc->sock->mtuh(tc, tc->arg); + } + else { + return tc->sock->mtu; + } + } + else { + return MTU_DEFAULT; + } #endif #if defined (BIO_CTRL_DGRAM_GET_FALLBACK_MTU) @@ -750,6 +762,13 @@ static struct tls_conn *conn_lookup(struct dtls_sock *sock, } +static int send_handler(struct tls_conn *tc, const struct sa *dst, + struct mbuf *mb, void *arg) { + (void)arg; + return udp_send_helper(tc->sock->us, dst, mb, tc->sock->uh); +} + + static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct dtls_sock *sock = arg; @@ -782,6 +801,18 @@ static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) } +/** + * Feed data to a DTLS socket + * + * @param sock DTLS socket + * @param src Source address + * @param mb Buffer to receive + */ +void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb) { + recv_handler(src, mb, sock); +} + + /** * Create DTLS Socket * @@ -829,6 +860,54 @@ int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, sock->mtu = MTU_DEFAULT; sock->connh = connh; + sock->sendh = send_handler; + sock->arg = arg; + + out: + if (err) + mem_deref(sock); + else + *sockp = sock; + + return err; +} + + +/** + * Create a DTLS Socket without using an UDP socket underneath + * + * @param sockp Pointer to returned DTLS Socket + * @param htsize Connection hash table size. Set to 0 if one DTLS session shall + * be used for all peers. + * @param connh Connect handler + * @param sendh Send handler + * @param mtuh MTU handler + * @param arg Handler argument + * + * @return 0 if success, otherwise errorcode + */ +int dtls_socketless(struct dtls_sock **sockp, uint32_t htsize, + dtls_conn_h *connh, dtls_send_h *sendh, dtls_mtu_h *mtuh, + void *arg) +{ + struct dtls_sock *sock; + int err; + + if (!sockp || !sendh) + return EINVAL; + + sock = mem_zalloc(sizeof(*sock), sock_destructor); + if (!sock) + return ENOMEM; + + err = hash_alloc(&sock->ht, hash_valid_size(htsize)); + if (err) + goto out; + + sock->mtu = MTU_DEFAULT; + sock->connh = connh; + sock->sendh = sendh; + sock->mtuh = mtuh; sock->arg = arg; out: From 53ee9fab4754cf6a02b7afd4983eb22331db4fe1 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 28 Jul 2017 14:41:15 +0200 Subject: [PATCH 27/36] Return whether the packet has been handled in `dtls_receive`. --- include/re_tls.h | 2 +- src/tls/openssl/tls_udp.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/re_tls.h b/include/re_tls.h index e97a7590..3659ee9a 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -92,7 +92,7 @@ int dtls_accept(struct tls_conn **ptc, struct tls *tls, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); int dtls_send(struct tls_conn *tc, struct mbuf *mb); -void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb); +bool dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb); void dtls_set_handlers(struct tls_conn *tc, dtls_estab_h *estabh, dtls_recv_h *recvh, dtls_close_h *closeh, void *arg); const struct sa *dtls_peer(const struct tls_conn *tc); diff --git a/src/tls/openssl/tls_udp.c b/src/tls/openssl/tls_udp.c index 368a4203..de203aee 100644 --- a/src/tls/openssl/tls_udp.c +++ b/src/tls/openssl/tls_udp.c @@ -807,9 +807,11 @@ static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) * @param sock DTLS socket * @param src Source address * @param mb Buffer to receive + * + * @return whether the packet has been handled. */ -void dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb) { - recv_handler(src, mb, sock); +bool dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb) { + return recv_handler(src, mb, sock); } From 97f455c176632073de5e4cf146d538eeced0f766 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 28 Jul 2017 16:18:07 +0200 Subject: [PATCH 28/36] Make headroom of an outgoing DTLS packet configurable Add functions `dtls_headroom` and `dtls_set_headroom`. --- include/re_tls.h | 2 ++ src/tls/openssl/tls_udp.c | 48 +++++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/include/re_tls.h b/include/re_tls.h index 050e0495..00c3493a 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -77,6 +77,8 @@ int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, dtls_conn_h *connh, void *arg); struct udp_sock *dtls_udp_sock(struct dtls_sock *sock); void dtls_set_mtu(struct dtls_sock *sock, size_t mtu); +size_t dtls_headroom(struct dtls_sock *sock); +void dtls_set_headroom(struct dtls_sock *sock, size_t headroom); int dtls_connect(struct tls_conn **ptc, struct tls *tls, struct dtls_sock *sock, const struct sa *peer, dtls_estab_h *estabh, dtls_recv_h *recvh, diff --git a/src/tls/openssl/tls_udp.c b/src/tls/openssl/tls_udp.c index 4ec81a30..e53f973a 100644 --- a/src/tls/openssl/tls_udp.c +++ b/src/tls/openssl/tls_udp.c @@ -27,8 +27,9 @@ enum { - MTU_DEFAULT = 1400, - MTU_FALLBACK = 548, + MTU_DEFAULT = 1400, + MTU_FALLBACK = 548, + HEADROOM_DEFAULT = 4, }; @@ -41,6 +42,7 @@ struct dtls_sock { dtls_conn_h *connh; void *arg; size_t mtu; + size_t headroom; }; @@ -109,16 +111,15 @@ static int bio_write(BIO *b, const char *buf, int len) struct tls_conn *tc = b->ptr; #endif struct mbuf *mb; - enum {SPACE = 4}; int err; - mb = mbuf_alloc(SPACE + len); + mb = mbuf_alloc(tc->sock->headroom + len); if (!mb) return -1; - mb->pos = SPACE; + mb->pos = tc->sock->headroom; (void)mbuf_write_mem(mb, (void *)buf, len); - mb->pos = SPACE; + mb->pos = tc->sock->headroom; err = udp_send_helper(tc->sock->us, &tc->peer, mb, tc->sock->uh); @@ -827,9 +828,10 @@ int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr, if (err) goto out; - sock->mtu = MTU_DEFAULT; - sock->connh = connh; - sock->arg = arg; + sock->mtu = MTU_DEFAULT; + sock->headroom = HEADROOM_DEFAULT; + sock->connh = connh; + sock->arg = arg; out: if (err) @@ -869,6 +871,34 @@ void dtls_set_mtu(struct dtls_sock *sock, size_t mtu) } +/* + * Get headroom of a DTLS Socket + * + * @param sock DTLS Socket + * + * @return Headroom value. + */ +size_t dtls_headroom(struct dtls_sock *sock) +{ + return sock ? sock->headroom : 0; +} + + +/** + * Set headroom on a DTLS Socket + * + * @param sock DTLS Socket + * @param headroom Headroom value + */ +void dtls_set_headroom(struct dtls_sock *sock, size_t headroom) +{ + if (!sock) + return; + + sock->headroom = headroom; +} + + void dtls_recv_packet(struct dtls_sock *sock, const struct sa *src, struct mbuf *mb) { From 9db018131986f6cfc82e5d789b74ed8079b392f9 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 1 Mar 2017 01:41:59 +0100 Subject: [PATCH 29/36] Raise FD_EXCEPT on EPOLLHUP (fixes closed pipes) --- src/main/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/main.c b/src/main/main.c index 762b0b4f..3453ebd3 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -786,6 +786,8 @@ static int fd_poll(struct re *re) flags |= FD_WRITE; if (re->events[i].events & EPOLLERR) flags |= FD_EXCEPT; + if (re->events[i].events & EPOLLHUP) + flags |= FD_EXCEPT; if (!flags) { DEBUG_WARNING("epoll: no flags fd=%d\n", fd); From 631c8802b4801fbd442b7c5612f0736075755a46 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Mon, 27 Mar 2017 22:01:07 +0200 Subject: [PATCH 30/36] Handle %h prefixed (short) types in formatter functions --- src/fmt/print.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/fmt/print.c b/src/fmt/print.c index 85e9ebf9..c0247b49 100644 --- a/src/fmt/print.c +++ b/src/fmt/print.c @@ -303,6 +303,11 @@ int re_vhprintf(const char *fmt, va_list ap, re_vprintf_h *vph, void *arg) } break; + case 'h': + lenmod = LENMOD_NONE; + fm = true; + break; + case 'H': ph = va_arg(ap, re_printf_h *); ph_arg = va_arg(ap, void *); From 3d990f602b236a208a18d3bf356812d37500b7bc Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Fri, 21 Oct 2016 01:02:28 +0200 Subject: [PATCH 31/36] Add the possibility to set Diffie-Hellman parameters Add `tls_set_dh_params_pem` and `tls_set_dh_params_der` function --- include/re_tls.h | 2 + src/tls/openssl/tls.c | 153 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) diff --git a/include/re_tls.h b/include/re_tls.h index 050e0495..64dcee5c 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -54,6 +54,8 @@ int tls_srtp_keyinfo(const struct tls_conn *tc, enum srtp_suite *suite, uint8_t *srv_key, size_t srv_key_size); const char *tls_cipher_name(const struct tls_conn *tc); int tls_set_ciphers(struct tls *tls, const char *cipherv[], size_t count); +int tls_set_dh_params_pem(struct tls *tls, const char *pem, size_t len); +int tls_set_dh_params_der(struct tls *tls, const uint8_t *der, size_t len); int tls_set_servername(struct tls_conn *tc, const char *servername); diff --git a/src/tls/openssl/tls.c b/src/tls/openssl/tls.c index 8594ca54..f293644b 100644 --- a/src/tls/openssl/tls.c +++ b/src/tls/openssl/tls.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -837,6 +839,157 @@ int tls_set_ciphers(struct tls *tls, const char *cipherv[], size_t count) } +static int set_dh_params(struct tls *tls, DH *dh) +{ + int codes, r; +#if OPENSSL_VERSION_NUMBER < 0x1000200fL + EC_KEY *ec_key; +#endif + + if (!DH_check(dh, &codes)) + return ENOMEM; + if (codes) { +#if defined(DH_CHECK_P_NOT_PRIME) + if (codes & DH_CHECK_P_NOT_PRIME) + DEBUG_WARNING("set_dh_params: p is not prime\n"); +#endif +#if defined(DH_CHECK_P_NOT_SAFE_PRIME) + if (codes & DH_CHECK_P_NOT_SAFE_PRIME) + DEBUG_WARNING("set_dh_params: p is not safe prime\n"); +#endif +#if defined(DH_UNABLE_TO_CHECK_GENERATOR) + if (codes & DH_UNABLE_TO_CHECK_GENERATOR) + DEBUG_WARNING("set_dh_params: generator g " + "cannot be checked\n"); +#endif +#if defined(DH_NOT_SUITABLE_GENERATOR) + if (codes & DH_NOT_SUITABLE_GENERATOR) + DEBUG_WARNING("set_dh_params: generator g " + "is not suitable\n"); +#endif +#if defined(DH_CHECK_Q_NOT_PRIME) + if (codes & DH_CHECK_Q_NOT_PRIME) + DEBUG_WARNING("set_dh_params: q is not prime\n"); +#endif +#if defined(DH_CHECK_INVALID_Q_VALUE) + if (codes & DH_CHECK_INVALID_Q_VALUE) + DEBUG_WARNING("set_dh_params: q is invalid\n"); +#endif +#if defined(DH_CHECK_INVALID_J_VALUE) + if (codes & DH_CHECK_INVALID_J_VALUE) + DEBUG_WARNING("set_dh_params: j is invalid\n"); +#endif + return EINVAL; + } + + if (!SSL_CTX_set_tmp_dh(tls->ctx, dh)) { + DEBUG_WARNING("set_dh_params: set_tmp_dh failed\n"); + return ENOMEM; + } + +#if OPENSSL_VERSION_NUMBER >= 0x1000200fL + r = SSL_CTX_set_ecdh_auto(tls->ctx, 1); + if (!r) { + DEBUG_WARNING("set_dh_params: set_ecdh_auto failed\n"); + return ENOMEM; + } +#else + ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (!ec_key) + return ENOMEM; + r = SSL_CTX_set_tmp_ecdh(tls->ctx, ec_key); + EC_KEY_free(ec_key); + if (!r) { + DEBUG_WARNING("set_dh_params: set_tmp_ecdh failed\n"); + return ENOMEM; + } +#endif + + return 0; +} + + +/** + * Set Diffie-Hellman parameters on a TLS context + * + * @param tls TLS Context + * @param pem Diffie-Hellman parameters in PEM format + * @param len Length of PEM string + * + * @return 0 if success, otherwise errorcode + */ +int tls_set_dh_params_pem(struct tls *tls, const char *pem, size_t len) +{ + BIO *bio = NULL; + DH *dh = NULL; + int err = ENOMEM; + + if (!tls || !pem || !len) + return EINVAL; + + bio = BIO_new_mem_buf((char *)pem, (int)len); + if (!bio) + goto out; + + dh = PEM_read_bio_DHparams(bio, NULL, 0, NULL); + if (!dh) + goto out; + + err = set_dh_params(tls, dh); + if (err) + goto out; + + err = 0; + + out: + if (dh) + DH_free(dh); + if (bio) + BIO_free(bio); + if (err) + ERR_clear_error(); + + return err; +} + + +/** + * Set Diffie-Hellman parameters on a TLS context + * + * @param tls TLS Context + * @param der Diffie-Hellman parameters in DER format + * @param len Length of DER bytes + * + * @return 0 if success, otherwise errorcode + */ +int tls_set_dh_params_der(struct tls *tls, const uint8_t *der, size_t len) +{ + DH *dh = NULL; + int err = ENOMEM; + + if (!tls || !der || !len) + return EINVAL; + + dh = d2i_DHparams(NULL, &der, len); + if (!dh) + goto out; + + err = set_dh_params(tls, dh); + if (err) + goto out; + + err = 0; + + out: + if (dh) + DH_free(dh); + if (err) + ERR_clear_error(); + + return err; +} + + /** * Set the server name on a TLS Connection, using TLS SNI extension. * From 8c9828284c7ac8bb71f64231f4abd538246c3ef2 Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Wed, 22 Mar 2017 19:51:42 +0100 Subject: [PATCH 32/36] Explicitly use `long` as value for `SSL_CTX_set_ecdh_auto` call --- src/tls/openssl/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tls/openssl/tls.c b/src/tls/openssl/tls.c index f293644b..072602c4 100644 --- a/src/tls/openssl/tls.c +++ b/src/tls/openssl/tls.c @@ -888,7 +888,7 @@ static int set_dh_params(struct tls *tls, DH *dh) } #if OPENSSL_VERSION_NUMBER >= 0x1000200fL - r = SSL_CTX_set_ecdh_auto(tls->ctx, 1); + r = SSL_CTX_set_ecdh_auto(tls->ctx, (long) 1); if (!r) { DEBUG_WARNING("set_dh_params: set_ecdh_auto failed\n"); return ENOMEM; From 4deed71e1d43768a0ce85e35ccec986b036cebff Mon Sep 17 00:00:00 2001 From: Lennart Grahl Date: Sun, 26 Mar 2017 13:04:01 +0200 Subject: [PATCH 33/36] Fix use `long` for `SSL_CTX_set_ecdh_auto` and `SSL_CTX_set_tmp_ecdh` return values --- src/tls/openssl/tls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tls/openssl/tls.c b/src/tls/openssl/tls.c index 072602c4..0b6c3923 100644 --- a/src/tls/openssl/tls.c +++ b/src/tls/openssl/tls.c @@ -841,7 +841,8 @@ int tls_set_ciphers(struct tls *tls, const char *cipherv[], size_t count) static int set_dh_params(struct tls *tls, DH *dh) { - int codes, r; + int codes; + long r; #if OPENSSL_VERSION_NUMBER < 0x1000200fL EC_KEY *ec_key; #endif From eed008c7be33fbefe328b6d1abc8af143654a24d Mon Sep 17 00:00:00 2001 From: nacho Date: Tue, 30 Oct 2018 16:48:39 +0100 Subject: [PATCH 34/36] BoringSSL compatilibity fixes --- src/tls/openssl/tls.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tls/openssl/tls.h b/src/tls/openssl/tls.h index 2c621d54..927fb2ed 100644 --- a/src/tls/openssl/tls.h +++ b/src/tls/openssl/tls.h @@ -19,7 +19,8 @@ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ - !defined(LIBRESSL_VERSION_NUMBER) + !defined(LIBRESSL_VERSION_NUMBER) && \ + !defined(OPENSSL_IS_BORINGSSL) #define SSL_state SSL_get_state #define SSL_ST_OK TLS_ST_OK #endif From a53d2843722bee55ec61dc4ba37358bc20cdc8f1 Mon Sep 17 00:00:00 2001 From: nacho Date: Fri, 2 Nov 2018 11:31:47 +0100 Subject: [PATCH 35/36] Initial work --- include/re_main.h | 1 + src/main/main.c | 122 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/include/re_main.h b/include/re_main.h index cc9ac4ba..f9956302 100644 --- a/include/re_main.h +++ b/include/re_main.h @@ -59,6 +59,7 @@ enum poll_method { METHOD_SELECT, METHOD_EPOLL, METHOD_KQUEUE, + METHOD_LIBUV, /* sep */ METHOD_MAX }; diff --git a/src/main/main.c b/src/main/main.c index 3453ebd3..5ec18be1 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -34,6 +34,9 @@ #undef LIST_INIT #undef LIST_FOREACH #endif +#ifdef HAVE_LIBUV +#include +#endif #include #include #include @@ -91,6 +94,9 @@ struct re { int flags; /**< Polling flags (Read, Write, etc.) */ fd_h *fh; /**< Event handler */ void *arg; /**< Handler argument */ +#ifdef HAVE_LIBUV + uv_poll_t uv_poll; /**< libuv handler */ +#endif } *fhs; int maxfds; /**< Maximum number of polling fds */ int nfds; /**< Number of active file descriptors */ @@ -113,6 +119,10 @@ struct re { struct kevent *evlist; int kqfd; #endif + +#ifdef HAVE_LIBUV + uv_loop_t *uv_loop; +#endif #ifdef HAVE_PTHREAD pthread_mutex_t mutex; /**< Mutex for thread synchronization */ @@ -140,6 +150,9 @@ static struct re global_re = { NULL, -1, #endif +#ifdef HAVE_LIBUV + NULL, +#endif #ifdef HAVE_PTHREAD #if MAIN_DEBUG && defined (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, @@ -372,6 +385,74 @@ static int set_kqueue_fds(struct re *re, int fd, int flags) } #endif +#ifdef HAVE_LIBUV + +static void connection_poll_cb(uv_poll_t* handle, int status, int events) +{ + + struct re *re = re_get(); + int fd = handle->data; + int flags = 0; + + if (status < 0) + flags |= FD_EXCEP; + if (events & UV_READABLE) + flags |= FD_READ; + if (events & UV_WRITABLE) + flags |= FD_WRITE; + + re->fhs[fd].fh(flags, re->fhs[fd].arg); + +} + +static void close_cb (uv_handle_t* handle) +{ + struct re *re = re_get(); + int fd = handle->data; +} + +static int set_libuv_fds(struct re *re, int fd, int flags) +{ + + struct re *re = re_get(); + + int events = 0; + int err = 0; + + if (!re->uv_loop) + return EBADFD; + + uv_poll_t* uv_poll = re->fhs[fd].uv_poll; + + DEBUG_INFO("set_libuv_fds: fd=%d flags=0x%02x\n", fd, flags); + + poll_handle.data + + if (flags) { + + uv_poll.data = fd; + + if (flags & FD_READ) + events |= UV_READABLE; + if (flags & FD_WRITE) + events |= UV_WRITABLE; +// if (flags & FD_EXCEPT) + + if (uv_poll_init_socket (re->uv_loop, uv_poll, fd) != 0) { + err = 1; + } else if (uv_poll_start (uv_poll, events, connection_poll_cb) != 0) { + err = 2; + } + + } + else { + uv_poll_stop (uv_poll); + uv_close((uv_handle_t *) uv_poll, close_cb); + } + + return err; +} +#endif /** * Rebuild the file descriptor mapping table. This must be done whenever @@ -407,6 +488,11 @@ static int rebuild_fds(struct re *re) break; #endif +#ifdef HAVE_LIBUV + case METHOD_LIBUV: + err = set_libuv_fds(re, i, re->fhs[i].flags); + break; +#endif default: break; } @@ -483,6 +569,25 @@ static int poll_init(struct re *re) break; #endif + +#ifdef HAVE_LIBUV + case METHOD_LIBUV: + + if (!re->uv_poll_list) { + size_t sz = re->maxfds * sizeof(*re->uv_poll_list); + re->uv_poll_list = mem_zalloc(sz, NULL); + if (!re->uv_poll_list) + return ENOMEM; + } + + if (!re->uv_loop) { + DEBUG_INFO("creating livuv loop"); + re->uv_loop = uv_loop_new(); + if (!re->uv_loop) + return errno; + } + break; +#endif default: break; @@ -521,6 +626,13 @@ static void poll_close(struct re *re) re->evlist = mem_deref(re->evlist); #endif + +#ifdef HAVE_LIBUV + if (re->uv_loop) { + + } + re->uv_poll_list = mem_deref(re->uv_poll_list); +#endif } @@ -618,6 +730,14 @@ int fd_listen(int fd, int flags, fd_h *fh, void *arg) err = set_kqueue_fds(re, fd, flags); break; #endif + +#ifdef HAVE_LIBUV + case METHOD_LIBUV: + if (re->uv_loop == NULL) + return EBADFD; + err = set_libuv_fds(re, fd, flags); + break; +#endif default: break; @@ -729,7 +849,7 @@ static int fd_poll(struct re *re) } break; #endif - + default: (void)to; DEBUG_WARNING("no polling method set\n"); From f6dba97359ae12b9d551f264bcc2dab5c3ab8f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Mart=C3=ADn=20Oya?= Date: Sat, 3 Nov 2018 14:23:43 +0000 Subject: [PATCH 36/36] libuv support --- include/re_main.h | 7 +++ include/re_tmr.h | 6 +++ mk/re.mk | 10 ++++ src/main/main.c | 128 ++++++++++++++++++++++++++++++++-------------- src/main/method.c | 9 ++++ src/tmr/tmr.c | 78 ++++++++++++++++++++++++++-- 6 files changed, 195 insertions(+), 43 deletions(-) diff --git a/include/re_main.h b/include/re_main.h index f9956302..0199c707 100644 --- a/include/re_main.h +++ b/include/re_main.h @@ -4,6 +4,9 @@ * Copyright (C) 2010 Creytiv.com */ +#ifdef HAVE_LIBUV +#include +#endif enum { #ifndef FD_READ @@ -41,6 +44,9 @@ int libre_init(void); void libre_close(void); int re_main(re_signal_h *signalh); +#if HAVE_LIBUV +int re_main_uvloop (uv_loop_t* loop, re_signal_h *signalh ); +#endif void re_cancel(void); int re_debug(struct re_printf *pf, void *unused); @@ -65,6 +71,7 @@ enum poll_method { }; int poll_method_set(enum poll_method method); +enum poll_method poll_method_get (void); enum poll_method poll_method_best(void); const char *poll_method_name(enum poll_method method); int poll_method_type(enum poll_method *method, const struct pl *name); diff --git a/include/re_tmr.h b/include/re_tmr.h index b399fb17..8cd86c19 100644 --- a/include/re_tmr.h +++ b/include/re_tmr.h @@ -4,6 +4,9 @@ * Copyright (C) 2010 Creytiv.com */ +#ifdef HAVE_LIBUV +#include +#endif /** * Defines the timeout handler @@ -18,6 +21,9 @@ struct tmr { tmr_h *th; /**< Timeout handler */ void *arg; /**< Handler argument */ uint64_t jfs; /**< Jiffies for timeout */ +#ifdef HAVE_LIBUV + uv_timer_t* uv_timer; /**< libbuv handler */ +#endif }; diff --git a/mk/re.mk b/mk/re.mk index efb35c99..c7ef07aa 100644 --- a/mk/re.mk +++ b/mk/re.mk @@ -491,6 +491,15 @@ CFLAGS += -DUSE_ZLIB LIBS += -lz endif +USE_LIBUV := $(shell [ -f $(SYSROOT)/include/uv.h ] || \ + [ -f $(SYSROOT)/local/include/uv.h ] || \ + [ -f $(SYSROOT_ALT)/include/uv.h ] && echo "yes") + +ifneq ($(USE_LIBUV),) +CFLAGS += -D_XOPEN_SOURCE=600 -DHAVE_LIBUV +LIBS += -luv +endif + ifneq ($(OS),win32) @@ -687,6 +696,7 @@ info: @echo " USE_DTLS: $(USE_DTLS)" @echo " USE_DTLS_SRTP: $(USE_DTLS_SRTP)" @echo " USE_ZLIB: $(USE_ZLIB)" + @echo " USE_LIBUV: $(USE_LIBUV)" @echo " GCOV: $(GCOV)" @echo " GPROF: $(GPROF)" @echo " CROSS_COMPILE: $(CROSS_COMPILE)" diff --git a/src/main/main.c b/src/main/main.c index 5ec18be1..a087d9f7 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -34,9 +34,6 @@ #undef LIST_INIT #undef LIST_FOREACH #endif -#ifdef HAVE_LIBUV -#include -#endif #include #include #include @@ -50,7 +47,9 @@ #include #include #endif - +#ifdef HAVE_LIBUV +#include +#endif #define DEBUG_MODULE "main" #define DEBUG_LEVEL 5 @@ -121,6 +120,7 @@ struct re { #endif #ifdef HAVE_LIBUV + bool uv_loop_is_external; uv_loop_t *uv_loop; #endif @@ -151,6 +151,7 @@ static struct re global_re = { -1, #endif #ifdef HAVE_LIBUV + false, NULL, #endif #ifdef HAVE_PTHREAD @@ -387,15 +388,19 @@ static int set_kqueue_fds(struct re *re, int fd, int flags) #ifdef HAVE_LIBUV +static void libuv_fd_close (uv_handle_t* handle) { + +} + static void connection_poll_cb(uv_poll_t* handle, int status, int events) { struct re *re = re_get(); - int fd = handle->data; + int fd = (int) handle->data; int flags = 0; if (status < 0) - flags |= FD_EXCEP; + flags |= FD_EXCEPT; if (events & UV_READABLE) flags |= FD_READ; if (events & UV_WRITABLE) @@ -405,39 +410,29 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) } -static void close_cb (uv_handle_t* handle) -{ - struct re *re = re_get(); - int fd = handle->data; -} - static int set_libuv_fds(struct re *re, int fd, int flags) { - - struct re *re = re_get(); - int events = 0; int err = 0; - if (!re->uv_loop) + if (re->uv_loop == NULL) { return EBADFD; - - uv_poll_t* uv_poll = re->fhs[fd].uv_poll; + } - DEBUG_INFO("set_libuv_fds: fd=%d flags=0x%02x\n", fd, flags); + uv_poll_t* uv_poll = &re->fhs[fd].uv_poll; - poll_handle.data + DEBUG_INFO("set_libuv_fds: fd=%d flags=0x%02x\n", fd, flags); if (flags) { - uv_poll.data = fd; + uv_poll->data = (void*)fd; if (flags & FD_READ) events |= UV_READABLE; if (flags & FD_WRITE) events |= UV_WRITABLE; // if (flags & FD_EXCEPT) - + if (uv_poll_init_socket (re->uv_loop, uv_poll, fd) != 0) { err = 1; } else if (uv_poll_start (uv_poll, events, connection_poll_cb) != 0) { @@ -447,7 +442,9 @@ static int set_libuv_fds(struct re *re, int fd, int flags) } else { uv_poll_stop (uv_poll); - uv_close((uv_handle_t *) uv_poll, close_cb); +// if (!uv_is_closing((uv_handle_t *) uv_poll)) { +// uv_close ((uv_handle_t *) uv_poll, libuv_fd_close); +// } } return err; @@ -573,18 +570,11 @@ static int poll_init(struct re *re) #ifdef HAVE_LIBUV case METHOD_LIBUV: - if (!re->uv_poll_list) { - size_t sz = re->maxfds * sizeof(*re->uv_poll_list); - re->uv_poll_list = mem_zalloc(sz, NULL); - if (!re->uv_poll_list) - return ENOMEM; - } - - if (!re->uv_loop) { - DEBUG_INFO("creating livuv loop"); - re->uv_loop = uv_loop_new(); + if (re->uv_loop == NULL) { + re->uv_loop = malloc(sizeof *re->uv_loop); if (!re->uv_loop) return errno; + uv_loop_init (re->uv_loop); } break; #endif @@ -628,10 +618,13 @@ static void poll_close(struct re *re) #endif #ifdef HAVE_LIBUV - if (re->uv_loop) { - + if (re->uv_loop != NULL && !re->uv_loop_is_external) { + uv_stop (re->uv_loop); +// if (uv_loop_close (re->uv_loop) != UV_EBUSY) { +// free (re->uv_loop); +// re->uv_loop = NULL; +// } } - re->uv_poll_list = mem_deref(re->uv_poll_list); #endif } @@ -850,6 +843,18 @@ static int fd_poll(struct re *re) break; #endif +#ifdef HAVE_LIBUV + case METHOD_LIBUV: { + if (re->uv_loop == NULL) { + DEBUG_WARNING("no uv_loop\n"); + } else if (!re->uv_loop_is_external) { + int pending = uv_run (re->uv_loop, UV_RUN_NOWAIT); + } + n = 0; + } + break; +#endif + default: (void)to; DEBUG_WARNING("no polling method set\n"); @@ -952,6 +957,12 @@ static int fd_poll(struct re *re) } break; #endif +#ifdef HAVE_LIBUV + case METHOD_LIBUV: { + // noop + } + break; +#endif default: return EINVAL; @@ -1108,11 +1119,17 @@ int re_main(re_signal_h *signalh) if (EBADF == err) continue; #endif - break; } - - tmr_poll(&re->tmrl); +#ifdef HAVE_LIBUV + switch (re->method) { + case METHOD_LIBUV: + break; + default: + tmr_poll(&re->tmrl); + break; + } +#endif } re_unlock(re); @@ -1122,6 +1139,16 @@ int re_main(re_signal_h *signalh) return err; } +int re_main_uvloop (uv_loop_t* loop, re_signal_h *signalh) { + + struct re *re = re_get(); + re->uv_loop_is_external = true; + re->uv_loop = loop; + + return re_main (signalh); + +} + /** * Cancel the main polling loop @@ -1158,6 +1185,10 @@ int re_debug(struct re_printf *pf, void *unused) return err; } +enum poll_method poll_method_get () { + struct re *re = re_get(); + return re->method; +} /** * Set async I/O polling method. This function can also be called while the @@ -1199,6 +1230,10 @@ int poll_method_set(enum poll_method method) #ifdef HAVE_KQUEUE case METHOD_KQUEUE: break; +#endif +#ifdef HAVE_LIBUV + case METHOD_LIBUV: + break; #endif default: DEBUG_WARNING("poll method not supported: '%s'\n", @@ -1334,3 +1369,18 @@ struct list *tmrl_get(void) { return &re_get()->tmrl; } + +#ifdef HAVE_LIBUV +/** + * Get the uv_loop for this thread + * + * @return uv_loop_t* + * + * @note only used by tmr module + */ +uv_loop_t* get_libuv_loop(void); +uv_loop_t* get_libuv_loop(void) { + return re_get()->uv_loop; +} + +#endif diff --git a/src/main/method.c b/src/main/method.c index d4fc1fba..6644b211 100644 --- a/src/main/method.c +++ b/src/main/method.c @@ -14,6 +14,7 @@ static const char str_poll[] = "poll"; /**< POSIX.1-2001 poll */ static const char str_select[] = "select"; /**< POSIX.1-2001 select */ static const char str_epoll[] = "epoll"; /**< Linux epoll */ static const char str_kqueue[] = "kqueue"; +static const char str_libuv[] = "libuv"; /** @@ -49,6 +50,11 @@ enum poll_method poll_method_best(void) m = METHOD_SELECT; } #endif +#ifdef HAVE_LIBUV + if (METHOD_NULL == m) { + m = METHOD_LIBUV; + } +#endif return m; } @@ -69,6 +75,7 @@ const char *poll_method_name(enum poll_method method) case METHOD_SELECT: return str_select; case METHOD_EPOLL: return str_epoll; case METHOD_KQUEUE: return str_kqueue; + case METHOD_LIBUV: return str_libuv; default: return "???"; } } @@ -95,6 +102,8 @@ int poll_method_type(enum poll_method *method, const struct pl *name) *method = METHOD_EPOLL; else if (0 == pl_strcasecmp(name, str_kqueue)) *method = METHOD_KQUEUE; + else if (0 == pl_strcasecmp(name, str_libuv)) + *method = METHOD_LIBUV; else return ENOENT; diff --git a/src/tmr/tmr.c b/src/tmr/tmr.c index 73083f16..9e59f269 100644 --- a/src/tmr/tmr.c +++ b/src/tmr/tmr.c @@ -21,7 +21,10 @@ #include #include #include - +#ifdef HAVE_LIBUV +#include +#include +#endif #define DEBUG_MODULE "tmr" #define DEBUG_LEVEL 5 @@ -38,7 +41,10 @@ enum { }; extern struct list *tmrl_get(void); - +#ifdef HAVE_LIBUV +void libuv_timer_handler (uv_timer_t* handler); +extern uv_loop_t* get_libuv_loop(void); +#endif static bool inspos_handler(struct le *le, void *arg) { @@ -224,6 +230,27 @@ void tmr_init(struct tmr *tmr) memset(tmr, 0, sizeof(*tmr)); } +#ifdef HAVE_LIBUV + +static void libuv_timer_close (uv_handle_t* handle) { + free (handle); +} + +void libuv_timer_handler (uv_timer_t* handler) { + + struct tmr *tmr = ((uv_timer_t*)handler)->data; + + if (tmr != NULL) { + if (tmr->th != NULL) { + tmr->th (tmr->arg); + tmr->th = NULL; + } + uv_close((uv_handle_t *)tmr->uv_timer, libuv_timer_close); + tmr->uv_timer = NULL; + } +} + +#endif /** * Start a timer @@ -235,6 +262,41 @@ void tmr_init(struct tmr *tmr) */ void tmr_start(struct tmr *tmr, uint64_t delay, tmr_h *th, void *arg) { + +#ifdef HAVE_LIBUV + if (poll_method_get() == METHOD_LIBUV) { + + if (!tmr) + return; + + tmr->th = th; + tmr->arg = arg; + + if (th != NULL) { + + uv_loop_t* loop = get_libuv_loop(); + if (tmr->uv_timer == NULL) { + uv_timer_t* handler = (uv_timer_t*) malloc (sizeof(uv_timer_t)); + if (loop != NULL) { + handler->data = tmr; + uv_timer_init (loop, handler); + tmr->uv_timer = handler; + } + } + tmr->jfs = uv_now(loop) + delay; + uv_timer_start (tmr->uv_timer, libuv_timer_handler, delay, 0); + } else { + if (tmr->uv_timer != NULL) { + uv_timer_stop (tmr->uv_timer); + uv_close((uv_handle_t *)tmr->uv_timer, libuv_timer_close); + tmr->uv_timer = NULL; + } + } + + return; + } +#endif + struct list *tmrl = tmrl_get(); struct le *le; @@ -294,11 +356,19 @@ void tmr_cancel(struct tmr *tmr) */ uint64_t tmr_get_expire(const struct tmr *tmr) { - uint64_t jfs; - + uint64_t jfs; + if (!tmr || !tmr->th) return 0; +#ifdef HAVE_LIBUV + if (poll_method_get() == METHOD_LIBUV) { + uv_loop_t* loop = get_libuv_loop(); + jfs = uv_now(loop); + return (tmr->jfs > jfs) ? (tmr->jfs - jfs) : 0; + } +#endif + jfs = tmr_jiffies(); return (tmr->jfs > jfs) ? (tmr->jfs - jfs) : 0;