diff options
author | Alfred E. Heggestad <aeh@db.org> | 2014-02-09 11:50:07 +0100 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2014-02-09 11:50:07 +0100 |
commit | 98bf08bdcf2edd9d397f32650a8bfe62186fbecf (patch) | |
tree | ebc6ec71f44bff8c42e4eefced61948623df02fc /modules/zrtp | |
parent | e6ad5cf4401b860ba402d4b7b3c7c254bc87a019 (diff) |
baresip 0.4.10
Diffstat (limited to 'modules/zrtp')
-rw-r--r-- | modules/zrtp/module.mk | 12 | ||||
-rw-r--r-- | modules/zrtp/zrtp.c | 300 |
2 files changed, 312 insertions, 0 deletions
diff --git a/modules/zrtp/module.mk b/modules/zrtp/module.mk new file mode 100644 index 0000000..7bcc0ac --- /dev/null +++ b/modules/zrtp/module.mk @@ -0,0 +1,12 @@ +# +# module.mk +# +# Copyright (C) 2010 Creytiv.com +# + +MOD := zrtp +$(MOD)_SRCS += zrtp.c +$(MOD)_LFLAGS += -lzrtp -lbn +CFLAGS += -I/usr/local/include/libzrtp + +include mk/mod.mk diff --git a/modules/zrtp/zrtp.c b/modules/zrtp/zrtp.c new file mode 100644 index 0000000..1055483 --- /dev/null +++ b/modules/zrtp/zrtp.c @@ -0,0 +1,300 @@ +/** + * @file zrtp.c ZRTP: Media Path Key Agreement for Unicast Secure RTP + * + * Copyright (C) 2010 Creytiv.com + */ +#include <re.h> +#include <baresip.h> +#include <zrtp.h> + + +/** + * @defgroup zrtp zrtp + * + * ZRTP: Media Path Key Agreement for Unicast Secure RTP + * + * Experimental support for ZRTP + * + * See http://tools.ietf.org/html/rfc6189 + * + * Briefly tested with Twinkle 1.4.2 and Jitsi 2.2.4603.9615 + * + * This module is using ZRTP implementation in Freeswitch + * https://github.com/traviscross/libzrtp + */ + + +struct menc_sess { + zrtp_session_t *zrtp_session; +}; + +struct menc_media { + const struct menc_sess *sess; + struct udp_helper *uh; + struct sa raddr; + void *rtpsock; + zrtp_stream_t *zrtp_stream; +}; + + +static zrtp_global_t *zrtp_global; +static zrtp_config_t zrtp_config; + + +static void session_destructor(void *arg) +{ + struct menc_sess *st = arg; + + if (st->zrtp_session) + zrtp_session_down(st->zrtp_session); +} + + +static void media_destructor(void *arg) +{ + struct menc_media *st = arg; + + mem_deref(st->uh); + mem_deref(st->rtpsock); + + if (st->zrtp_stream) + zrtp_stream_stop(st->zrtp_stream); +} + + +static bool udp_helper_send(int *err, struct sa *dst, + struct mbuf *mb, void *arg) +{ + struct menc_media *st = arg; + unsigned int length; + zrtp_status_t s; + (void)dst; + + length = (unsigned int)mbuf_get_left(mb); + + s = zrtp_process_rtp(st->zrtp_stream, (char *)mbuf_buf(mb), &length); + if (s != zrtp_status_ok) { + warning("zrtp: zrtp_process_rtp failed (status = %d)\n", s); + return false; + } + + /* make sure target buffer is large enough */ + if (length > mbuf_get_space(mb)) { + warning("zrtp: zrtp_process_rtp: length > space (%u > %u)\n", + length, mbuf_get_space(mb)); + *err = ENOMEM; + } + + mb->end = mb->pos + length; + + return false; +} + + +static bool udp_helper_recv(struct sa *src, struct mbuf *mb, void *arg) +{ + struct menc_media *st = arg; + unsigned int length; + zrtp_status_t s; + (void)src; + + length = (unsigned int)mbuf_get_left(mb); + + s = zrtp_process_srtp(st->zrtp_stream, (char *)mbuf_buf(mb), &length); + if (s != zrtp_status_ok) { + + if (s == zrtp_status_drop) + return true; + + warning("zrtp: zrtp_process_srtp: %d\n", s); + return false; + } + + mb->end = mb->pos + length; + + return false; +} + + +static int session_alloc(struct menc_sess **sessp, struct sdp_session *sdp, + bool offerer, menc_error_h *errorh, void *arg) +{ + struct menc_sess *st; + zrtp_status_t s; + int err = 0; + (void)offerer; + (void)errorh; + (void)arg; + + if (!sessp || !sdp) + return EINVAL; + + st = mem_zalloc(sizeof(*st), session_destructor); + if (!st) + return ENOMEM; + + s = zrtp_session_init(zrtp_global, NULL, + ZRTP_SIGNALING_ROLE_UNKNOWN, &st->zrtp_session); + if (s != zrtp_status_ok) { + warning("zrtp: zrtp_session_init failed (status = %d)\n", s); + err = EPROTO; + goto out; + } + + out: + if (err) + mem_deref(st); + else + *sessp = st; + + return err; +} + + +static int media_alloc(struct menc_media **stp, struct menc_sess *sess, + struct rtp_sock *rtp, + int proto, void *rtpsock, void *rtcpsock, + struct sdp_media *sdpm) +{ + struct menc_media *st; + zrtp_status_t s; + int err = 0; + + if (!stp || !sess || proto != IPPROTO_UDP) + return EINVAL; + + st = *stp; + if (st) + goto start; + + st = mem_zalloc(sizeof(*st), media_destructor); + if (!st) + return ENOMEM; + + st->sess = sess; + st->rtpsock = mem_ref(rtpsock); + + err = udp_register_helper(&st->uh, rtpsock, 0, + udp_helper_send, udp_helper_recv, st); + if (err) + goto out; + + s = zrtp_stream_attach(sess->zrtp_session, &st->zrtp_stream); + if (s != zrtp_status_ok) { + warning("zrtp: zrtp_stream_attach failed (status=%d)\n", s); + err = EPROTO; + goto out; + } + + zrtp_stream_set_userdata(st->zrtp_stream, st); + + out: + if (err) { + mem_deref(st); + return err; + } + else + *stp = st; + + start: + if (sa_isset(sdp_media_raddr(sdpm), SA_ALL)) { + st->raddr = *sdp_media_raddr(sdpm); + + s = zrtp_stream_start(st->zrtp_stream, rtp_sess_ssrc(rtp)); + if (s != zrtp_status_ok) { + warning("zrtp: zrtp_stream_start: status = %d\n", s); + } + } + + return err; +} + + +static int zrtp_send_rtp_callback(const zrtp_stream_t *stream, + char *rtp_packet, + unsigned int rtp_packet_length) +{ + struct menc_media *st = zrtp_stream_get_userdata(stream); + struct mbuf *mb; + int err; + + if (!sa_isset(&st->raddr, SA_ALL)) + return zrtp_status_ok; + + mb = mbuf_alloc(rtp_packet_length); + if (!mb) + return zrtp_status_alloc_fail; + + (void)mbuf_write_mem(mb, (void *)rtp_packet, rtp_packet_length); + mb->pos = 0; + + err = udp_send(st->rtpsock, &st->raddr, mb); + if (err) { + warning("zrtp: udp_send %u bytes (%m)\n", + rtp_packet_length, err); + } + + mem_deref(mb); + + return zrtp_status_ok; +} + + +static struct menc menc_zrtp = { + LE_INIT, "zrtp", "RTP/AVP", session_alloc, media_alloc +}; + + +static int module_init(void) +{ + zrtp_status_t s; + char config_path[256] = ""; + int err; + + zrtp_config_defaults(&zrtp_config); + + err = conf_path_get(config_path, sizeof(config_path)); + if (err) { + warning("zrtp: could not get config path: %m\n", err); + return err; + } + if (re_snprintf(zrtp_config.cache_file_cfg.cache_path, + sizeof(zrtp_config.cache_file_cfg.cache_path), + "%s/zrtp_cache.dat", config_path) < 0) + return ENOMEM; + + rand_bytes(zrtp_config.zid, sizeof(zrtp_config.zid)); + + zrtp_config.cb.misc_cb.on_send_packet = zrtp_send_rtp_callback; + + s = zrtp_init(&zrtp_config, &zrtp_global); + if (zrtp_status_ok != s) { + warning("zrtp: zrtp_init() failed (status = %d)\n", s); + return ENOSYS; + } + + menc_register(&menc_zrtp); + + return 0; +} + + +static int module_close(void) +{ + menc_unregister(&menc_zrtp); + + if (zrtp_global) { + zrtp_down(zrtp_global); + zrtp_global = NULL; + } + + return 0; +} + + +EXPORT_SYM const struct mod_export DECL_EXPORTS(zrtp) = { + "zrtp", + "menc", + module_init, + module_close +}; |