Skip to content

libuv support #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 64 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
d7ee97f
Make it possible to create a DTLS socket without having an UDP socket…
lgrahl Oct 31, 2016
b3beb21
Raise FD_EXCEPT on EPOLLHUP (fixes closed pipes)
lgrahl Mar 1, 2017
f05afb5
Add the possibility to set Diffie-Hellman parameters
lgrahl Oct 20, 2016
ddc1ab1
Add Libs.private to pkg-config file
lgrahl Mar 22, 2017
8bf8b72
Merge branch 'dtls-socketless' into rawrtc-patched
lgrahl Mar 22, 2017
00a0945
Merge branch 'pipe-epoll-fix' into rawrtc-patched
lgrahl Mar 22, 2017
0ac7a62
Merge branch 'tls-set-dh-params' into rawrtc-patched
lgrahl Mar 22, 2017
69da9f1
Add install-static option to Makefile
lgrahl Mar 22, 2017
b614d2e
Merge branch 'makefile-improvements' into rawrtc-patched
lgrahl Mar 22, 2017
24ac34c
Print OpenSSL sysroot on make info
lgrahl Mar 22, 2017
114883e
Merge branch 'makefile-improvements' into rawrtc-patched
lgrahl Mar 22, 2017
0071283
Fix add include and libs directory when using `OPENSSL_SYSROOT`
lgrahl Mar 22, 2017
df950db
Merge branch 'makefile-improvements' into rawrtc-patched
lgrahl Mar 22, 2017
29b5a2b
Remove `OPENSSL_SYSROOT` (`SYSROOT_ALT` should be sufficient)
lgrahl Mar 22, 2017
adbe6a6
Merge branch 'makefile-improvements' into rawrtc-patched
lgrahl Mar 22, 2017
6abcc92
Explicitly use `long` as value for `SSL_CTX_set_ecdh_auto` call
lgrahl Mar 22, 2017
0fc077c
Merge branch 'tls-set-dh-params' into rawrtc-patched
lgrahl Mar 22, 2017
3762eb8
Fix use `long` for `SSL_CTX_set_ecdh_auto` and `SSL_CTX_set_tmp_ecdh`…
lgrahl Mar 26, 2017
12ae81d
Merge branch 'tls-set-dh-params' into rawrtc-patched
lgrahl Mar 26, 2017
ecc1a62
Handle %h prefixed (short) types in formatter functions
lgrahl Mar 27, 2017
d52e2df
Merge branch 'support-fmt-h' into rawrtc-patched
lgrahl Mar 27, 2017
5bedf3b
Allow 'c='-line in SPD media to be explicitly set to unspecified
lgrahl Apr 6, 2017
c709622
Merge branch 'sdp-media-address' into rawrtc-patched
lgrahl Apr 6, 2017
8aca84a
Allow to exclude direction attribute
lgrahl Apr 7, 2017
6f1f67a
Merge branch 'sdp-media-exclude-ldir' into rawrtc-patched
lgrahl Apr 7, 2017
35f6d0b
Less code duplication
lgrahl Apr 11, 2017
c12309a
Use `PREFIX ?= ...` instead of `ifndef`
lgrahl Apr 28, 2017
3844e14
Less code duplication
lgrahl Apr 11, 2017
728577b
Use `PREFIX ?= ...` instead of `ifndef`
lgrahl Apr 28, 2017
93b3fa3
Remove `install-static` target
lgrahl Apr 28, 2017
585f196
Merge branch 'makefile-improvements' into rawrtc-patched
lgrahl Apr 28, 2017
1c36501
Raise FD_EXCEPT on EPOLLHUP (fixes closed pipes)
lgrahl Mar 1, 2017
57ca16a
Make it possible to create a DTLS socket without having an UDP socket…
lgrahl Oct 31, 2016
e2c464e
Allow 'c='-line in SPD media to be explicitly set to unspecified
lgrahl Apr 6, 2017
625c787
Allow 'c='-line in SPD media to be explicitly set to unspecified
lgrahl Apr 6, 2017
0616c5e
Allow to exclude direction attribute
lgrahl Apr 7, 2017
96110a7
Merge branch 'pipe-epoll-fix' into rawrtc-patched
lgrahl May 8, 2017
ab1d110
Merge branch 'dtls-socketless' into rawrtc-patched
lgrahl May 8, 2017
640b305
Merge branch 'sdp-media-address' into rawrtc-patched
lgrahl May 8, 2017
f01cf0c
Merge branch 'sdp-media-exclude-ldir' into rawrtc-patched
lgrahl May 8, 2017
cf8bcea
Merge branch 'master' into rawrtc-patched
lgrahl Jun 14, 2017
244e02f
Return whether the packet has been handled in `dtls_receive`.
lgrahl Jul 28, 2017
6c90041
Merge branch 'dtls-socketless' into rawrtc-patched
lgrahl Jul 28, 2017
3a6d314
Make headroom of an outgoing DTLS packet configurable
lgrahl Jul 28, 2017
9d1ba44
Merge branch 'dtls-configurable-headroom' into rawrtc-patched
lgrahl Jul 28, 2017
fcb10a0
Make it possible to create a DTLS socket without having an UDP socket…
lgrahl Oct 31, 2016
53ee9fa
Return whether the packet has been handled in `dtls_receive`.
lgrahl Jul 28, 2017
97f455c
Make headroom of an outgoing DTLS packet configurable
lgrahl Jul 28, 2017
9db0181
Raise FD_EXCEPT on EPOLLHUP (fixes closed pipes)
lgrahl Mar 1, 2017
631c880
Handle %h prefixed (short) types in formatter functions
lgrahl Mar 27, 2017
3d990f6
Add the possibility to set Diffie-Hellman parameters
lgrahl Oct 20, 2016
8c98282
Explicitly use `long` as value for `SSL_CTX_set_ecdh_auto` call
lgrahl Mar 22, 2017
4deed71
Fix use `long` for `SSL_CTX_set_ecdh_auto` and `SSL_CTX_set_tmp_ecdh`…
lgrahl Mar 26, 2017
762f98f
Merge branch 'master' into rawrtc-patched
lgrahl Feb 11, 2018
7b52ff0
Merge branch 'dtls-configurable-headroom' into rawrtc-patched
lgrahl Feb 11, 2018
3a376df
Merge branch 'dtls-socketless' into rawrtc-patched
lgrahl Feb 11, 2018
954b254
Merge branch 'pipe-epoll-fix' into rawrtc-patched
lgrahl Feb 11, 2018
485ee70
Merge branch 'support-fmt-h' into rawrtc-patched
lgrahl Feb 11, 2018
7d83790
Merge branch 'tls-set-dh-params' into rawrtc-patched
lgrahl Feb 11, 2018
4681816
Merge branch 'master' into rawrtc-patched
lgrahl Oct 8, 2018
eed008c
BoringSSL compatilibity fixes
Oct 30, 2018
65ed024
Merge remote-tracking branch 'origin/rawrtc-patched'
Oct 31, 2018
a53d284
Initial work
Nov 2, 2018
f6dba97
libuv support
nachooya Nov 3, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/re_main.h
Original file line number Diff line number Diff line change
@@ -4,6 +4,9 @@
* Copyright (C) 2010 Creytiv.com
*/

#ifdef HAVE_LIBUV
#include <uv.h>
#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);

@@ -59,11 +65,13 @@ enum poll_method {
METHOD_SELECT,
METHOD_EPOLL,
METHOD_KQUEUE,
METHOD_LIBUV,
/* sep */
METHOD_MAX
};

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);
1 change: 1 addition & 0 deletions include/re_sdp.h
Original file line number Diff line number Diff line change
@@ -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);
11 changes: 11 additions & 0 deletions include/re_tls.h
Original file line number Diff line number Diff line change
@@ -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);


@@ -66,6 +68,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,8 +80,13 @@ 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);
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,
@@ -86,6 +96,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);
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);
6 changes: 6 additions & 0 deletions include/re_tmr.h
Original file line number Diff line number Diff line change
@@ -4,6 +4,9 @@
* Copyright (C) 2010 Creytiv.com
*/

#ifdef HAVE_LIBUV
#include <uv.h>
#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
};


10 changes: 10 additions & 0 deletions mk/re.mk
Original file line number Diff line number Diff line change
@@ -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)"
5 changes: 5 additions & 0 deletions src/fmt/print.c
Original file line number Diff line number Diff line change
@@ -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 *);
182 changes: 177 additions & 5 deletions src/main/main.c
Original file line number Diff line number Diff line change
@@ -47,7 +47,9 @@
#include <stdlib.h>
#include <pthread.h>
#endif

#ifdef HAVE_LIBUV
#include <uv.h>
#endif

#define DEBUG_MODULE "main"
#define DEBUG_LEVEL 5
@@ -91,6 +93,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 +118,11 @@ struct re {
struct kevent *evlist;
int kqfd;
#endif

#ifdef HAVE_LIBUV
bool uv_loop_is_external;
uv_loop_t *uv_loop;
#endif

#ifdef HAVE_PTHREAD
pthread_mutex_t mutex; /**< Mutex for thread synchronization */
@@ -140,6 +150,10 @@ static struct re global_re = {
NULL,
-1,
#endif
#ifdef HAVE_LIBUV
false,
NULL,
#endif
#ifdef HAVE_PTHREAD
#if MAIN_DEBUG && defined (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
@@ -372,6 +386,70 @@ static int set_kqueue_fds(struct re *re, int fd, int flags)
}
#endif

#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 = (int) handle->data;
int flags = 0;

if (status < 0)
flags |= FD_EXCEPT;
if (events & UV_READABLE)
flags |= FD_READ;
if (events & UV_WRITABLE)
flags |= FD_WRITE;

re->fhs[fd].fh(flags, re->fhs[fd].arg);

}

static int set_libuv_fds(struct re *re, int fd, int flags)
{
int events = 0;
int err = 0;

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);

if (flags) {

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) {
err = 2;
}

}
else {
uv_poll_stop (uv_poll);
// if (!uv_is_closing((uv_handle_t *) uv_poll)) {
// uv_close ((uv_handle_t *) uv_poll, libuv_fd_close);
// }
}

return err;
}
#endif

/**
* Rebuild the file descriptor mapping table. This must be done whenever
@@ -407,6 +485,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 +566,18 @@ static int poll_init(struct re *re)

break;
#endif

#ifdef HAVE_LIBUV
case METHOD_LIBUV:

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

default:
break;
@@ -521,6 +616,16 @@ static void poll_close(struct re *re)

re->evlist = mem_deref(re->evlist);
#endif

#ifdef HAVE_LIBUV
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;
// }
}
#endif
}


@@ -618,6 +723,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 +842,19 @@ 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");
@@ -786,6 +911,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);
@@ -830,6 +957,12 @@ static int fd_poll(struct re *re)
}
break;
#endif
#ifdef HAVE_LIBUV
case METHOD_LIBUV: {
// noop
}
break;
#endif

default:
return EINVAL;
@@ -986,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);

@@ -1000,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
@@ -1036,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
@@ -1077,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",
@@ -1212,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
9 changes: 9 additions & 0 deletions src/main/method.c
Original file line number Diff line number Diff line change
@@ -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;

20 changes: 20 additions & 0 deletions src/sdp/media.c
Original file line number Diff line number Diff line change
@@ -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;
}

@@ -512,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
*
8 changes: 5 additions & 3 deletions src/sdp/msg.c
Original file line number Diff line number Diff line change
@@ -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);
}
@@ -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);
6 changes: 6 additions & 0 deletions src/sdp/sdp.h
Original file line number Diff line number Diff line change
@@ -10,6 +10,11 @@ enum {
RTP_DYNPT_END = 127,
};

enum {
MEDIA_LADDR_SET = 1<<0,
MEDIA_LDIR_EXCLUDE = 1<<1,
};


struct sdp_session {
struct list lmedial;
@@ -27,6 +32,7 @@ struct sdp_session {

struct sdp_media {
struct le le;
uint8_t flags;
struct list lfmtl;
struct list rfmtl;
struct list lattrl;
154 changes: 154 additions & 0 deletions src/tls/openssl/tls.c
Original file line number Diff line number Diff line change
@@ -10,6 +10,8 @@
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/dh.h>
#include <openssl/ec.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_mem.h>
@@ -853,6 +855,158 @@ 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;
long 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, (long) 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.
*
3 changes: 2 additions & 1 deletion src/tls/openssl/tls.h
Original file line number Diff line number Diff line change
@@ -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
127 changes: 119 additions & 8 deletions src/tls/openssl/tls_udp.c
Original file line number Diff line number Diff line change
@@ -27,8 +27,9 @@


enum {
MTU_DEFAULT = 1400,
MTU_FALLBACK = 548,
MTU_DEFAULT = 1400,
MTU_FALLBACK = 548,
HEADROOM_DEFAULT = 4,
};


@@ -39,8 +40,11 @@ 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;
size_t headroom;
};


@@ -109,18 +113,17 @@ 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);
err = tc->sock->sendh(tc, &tc->peer, mb, tc->arg);

mem_deref(mb);

@@ -146,7 +149,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 +763,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 +802,20 @@ 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
*
* @return whether the packet has been handled.
*/
bool dtls_receive(struct dtls_sock *sock, struct sa *src, struct mbuf *mb) {
return recv_handler(src, mb, sock);
}


/**
* Create DTLS Socket
*
@@ -827,8 +861,57 @@ int dtls_listen(struct dtls_sock **sockp, const struct sa *laddr,
if (err)
goto out;

sock->mtu = MTU_DEFAULT;
sock->headroom = HEADROOM_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:
@@ -869,6 +952,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)
{
78 changes: 74 additions & 4 deletions src/tmr/tmr.c
Original file line number Diff line number Diff line change
@@ -21,7 +21,10 @@
#include <re_fmt.h>
#include <re_mem.h>
#include <re_tmr.h>

#ifdef HAVE_LIBUV
#include <uv.h>
#include <re_main.h>
#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;