diff --git a/daemon/codec.c b/daemon/codec.c index e1cc659ea..38886faab 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -320,6 +320,8 @@ next: // the list, as we must expect to potentially receive media in that codec, which we // then could not transcode. if (MEDIA_ISSET(receiver, TRANSCODE)) { + // XXX we also must switch all "passthrough" handlers to a special passthrough + // that substitutes out the SSRC for (GList *l = receiver->codecs_prefs_recv.head; l; ) { struct rtp_payload_type *pt = l->data; @@ -366,13 +368,16 @@ void codec_handlers_free(struct call_media *m) { } -static int handler_func_passthrough(struct codec_handler *h, struct call_media *media, - struct media_packet *mp) -{ +void codec_add_raw_packet(struct media_packet *mp, const str *raw) { struct codec_packet *p = g_slice_alloc(sizeof(*p)); - p->s = mp->raw; + p->s = *raw; p->free_func = NULL; g_queue_push_tail(&mp->packets_out, p); +} +static int handler_func_passthrough(struct codec_handler *h, struct call_media *media, + struct media_packet *mp) +{ + codec_add_raw_packet(mp, &mp->raw); return 0; } diff --git a/daemon/codec.h b/daemon/codec.h index 3852ad40f..3e3c6a584 100644 --- a/daemon/codec.h +++ b/daemon/codec.h @@ -33,11 +33,10 @@ struct codec_packet { void codec_handlers_update(struct call_media *receiver, struct call_media *sink); - struct codec_handler *codec_handler_get(struct call_media *, int payload_type); - void codec_handlers_free(struct call_media *); +void codec_add_raw_packet(struct media_packet *mp, const str *); void codec_packet_free(void *); void codec_rtp_payload_types(struct call_media *media, struct call_media *other_media, diff --git a/daemon/media_socket.c b/daemon/media_socket.c index de4758638..f1021505a 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -42,9 +42,10 @@ typedef int (*rewrite_func)(str *, struct packet_stream *, struct stream_fd *, c struct streamhandler_io { - rewrite_func rtp; - rewrite_func rtcp; - int (*kernel)(struct rtpengine_srtp *, struct packet_stream *); + rewrite_func rtp_crypt; + rewrite_func rtcp_crypt; + rtcp_filter_func *rtcp_filter; + int (*kernel)(struct rtpengine_srtp *, struct packet_stream *); }; struct streamhandler { const struct streamhandler_io *in; @@ -68,6 +69,7 @@ struct packet_handler_ctx { struct call_media *media; // stream->media struct packet_stream *sink; // where to send output packets to (forward destination) rewrite_func decrypt_func, encrypt_func; // handlers for decrypt/encrypt + rtcp_filter_func *rtcp_filter; struct packet_stream *in_srtp, *out_srtp; // SRTP contexts for decrypt/encrypt (relevant for muxed RTCP) int payload_type; // -1 if unknown or not RTP int rtcp; // true if this is an RTCP packet @@ -88,8 +90,6 @@ static int __k_null(struct rtpengine_srtp *s, struct packet_stream *); static int __k_srtp_encrypt(struct rtpengine_srtp *s, struct packet_stream *); static int __k_srtp_decrypt(struct rtpengine_srtp *s, struct packet_stream *); -static int call_noop_rtcp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *, - const struct timeval *, struct ssrc_ctx *); static int call_avp2savp_rtp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *, const struct timeval *, struct ssrc_ctx *); static int call_savp2avp_rtp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *, @@ -98,12 +98,6 @@ static int call_avp2savp_rtcp(str *s, struct packet_stream *, struct stream_fd * const struct timeval *, struct ssrc_ctx *); static int call_savp2avp_rtcp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *, const struct timeval *, struct ssrc_ctx *); -static int call_avpf2avp_rtcp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *, - const struct timeval *, struct ssrc_ctx *); -//static int call_avpf2savp_rtcp(str *s, struct packet_stream *); -static int call_savpf2avp_rtcp(str *s, struct packet_stream *, struct stream_fd *, const endpoint_t *, - const struct timeval *, struct ssrc_ctx *); -//static int call_savpf2savp_rtcp(str *s, struct packet_stream *); static struct logical_intf *__get_logical_interface(const str *name, sockfamily_t *fam); @@ -117,34 +111,34 @@ static const struct streamhandler_io __shio_noop = { // non-RTP protocols }; static const struct streamhandler_io __shio_noop_rtp = { .kernel = __k_null, - .rtcp = call_noop_rtcp, }; static const struct streamhandler_io __shio_decrypt = { .kernel = __k_srtp_decrypt, - .rtp = call_savp2avp_rtp, - .rtcp = call_savp2avp_rtcp, + .rtp_crypt = call_savp2avp_rtp, + .rtcp_crypt = call_savp2avp_rtcp, }; static const struct streamhandler_io __shio_encrypt = { .kernel = __k_srtp_encrypt, - .rtp = call_avp2savp_rtp, - .rtcp = call_avp2savp_rtcp, + .rtp_crypt = call_avp2savp_rtp, + .rtcp_crypt = call_avp2savp_rtcp, }; static const struct streamhandler_io __shio_decrypt_rtcp_only = { .kernel = __k_null, - .rtcp = call_savp2avp_rtcp, + .rtcp_crypt = call_savp2avp_rtcp, }; static const struct streamhandler_io __shio_encrypt_rtcp_only = { .kernel = __k_null, - .rtcp = call_avp2savp_rtcp, + .rtcp_crypt = call_avp2savp_rtcp, }; static const struct streamhandler_io __shio_avpf_strip = { .kernel = __k_null, - .rtcp = call_avpf2avp_rtcp, + .rtcp_filter = rtcp_avpf2avp_filter, }; static const struct streamhandler_io __shio_decrypt_avpf_strip = { .kernel = __k_srtp_decrypt, - .rtp = call_savp2avp_rtp, - .rtcp = call_savpf2avp_rtcp, + .rtp_crypt = call_savp2avp_rtp, + .rtcp_crypt = call_savp2avp_rtcp, + .rtcp_filter = rtcp_avpf2avp_filter, }; /* ********** */ @@ -869,17 +863,6 @@ static int rtcp_demux(const str *s, struct call_media *media) { return rtcp_demux_is_rtcp(s) ? 2 : 1; } -static int call_noop_rtcp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src, - const struct timeval *tv, struct ssrc_ctx *ssrc_ctx) -{ - rtcp_parse(s, sfd, src, tv); - return 0; -} -static int call_avpf2avp_rtcp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src, - const struct timeval *tv, struct ssrc_ctx *ssrc_ctx) -{ - return rtcp_avpf2avp(s, sfd, src, tv); // also does rtcp_parse -} static int call_avp2savp_rtp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src, const struct timeval *tv, struct ssrc_ctx *ssrc_ctx) { @@ -898,20 +881,7 @@ static int call_savp2avp_rtp(str *s, struct packet_stream *stream, struct stream static int call_savp2avp_rtcp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src, const struct timeval *tv, struct ssrc_ctx *ssrc_ctx) { - int ret = rtcp_savp2avp(s, &stream->selected_sfd->crypto, ssrc_ctx); - if (ret < 0) - return ret; - rtcp_parse(s, sfd, src, tv); - return ret; -} -static int call_savpf2avp_rtcp(str *s, struct packet_stream *stream, struct stream_fd *sfd, const endpoint_t *src, - const struct timeval *tv, struct ssrc_ctx *ssrc_ctx) -{ - int ret; - ret = rtcp_savp2avp(s, &stream->selected_sfd->crypto, ssrc_ctx); - if (ret < 0) - return ret; - return rtcp_avpf2avp(s, sfd, src, tv); + return rtcp_savp2avp(s, &stream->selected_sfd->crypto, ssrc_ctx); } @@ -1337,12 +1307,13 @@ static int media_packet_decrypt(struct packet_handler_ctx *phc) // XXX use an array with index instead of if/else if (G_LIKELY(!phc->rtcp)) { - phc->decrypt_func = phc->in_srtp->handler->in->rtp; - phc->encrypt_func = phc->in_srtp->handler->out->rtp; + phc->decrypt_func = phc->in_srtp->handler->in->rtp_crypt; + phc->encrypt_func = phc->in_srtp->handler->out->rtp_crypt; } else { - phc->decrypt_func = phc->in_srtp->handler->in->rtcp; - phc->encrypt_func = phc->in_srtp->handler->out->rtcp; + phc->decrypt_func = phc->in_srtp->handler->in->rtcp_crypt; + phc->encrypt_func = phc->in_srtp->handler->out->rtcp_crypt; + phc->rtcp_filter = phc->in_srtp->handler->in->rtcp_filter; } /* return values are: 0 = forward packet, -1 = error/dont forward, @@ -1513,6 +1484,27 @@ static void media_packet_kernel_check(struct packet_handler_ctx *phc) { } +static int do_rtcp(struct packet_handler_ctx *phc) { + int ret = -1; + // XXX use a handler for RTCP + // XXX rewrite/consume for transcoding + + GQueue rtcp_list = G_QUEUE_INIT; + if (rtcp_parse(&rtcp_list, &phc->s, phc->sfd, &phc->fsin, &phc->tv)) + goto out; + if (phc->rtcp_filter) + if (phc->rtcp_filter(&phc->s, &rtcp_list)) + goto out; + + codec_add_raw_packet(&phc->mp, &phc->s); + ret = 0; + +out: + rtcp_list_free(&rtcp_list); + return ret; +} + + /* called lock-free */ static int stream_packet(struct packet_handler_ctx *phc) { /** @@ -1596,12 +1588,18 @@ static int stream_packet(struct packet_handler_ctx *phc) { if (phc->call->recording) dump_packet(phc->call->recording, phc->stream, &phc->s); - // XXX use a handler for RTCP - struct codec_handler *transcoder = codec_handler_get(phc->media, phc->payload_type); - // this transfers the packet from 's' to 'packets_out' - phc->mp.raw = phc->s; - if (transcoder->func(transcoder, phc->media, &phc->mp)) - goto drop; + // RTCP detection is further up, so we could make this determination there + if (phc->mp.rtcp) { + if (do_rtcp(phc)) + goto drop; + } + else { + struct codec_handler *transcoder = codec_handler_get(phc->media, phc->payload_type); + // this transfers the packet from 's' to 'packets_out' + phc->mp.raw = phc->s; + if (transcoder->func(transcoder, phc->media, &phc->mp)) + goto drop; + } if (G_LIKELY(handler_ret >= 0)) handler_ret = media_packet_encrypt(phc); diff --git a/daemon/media_socket.h b/daemon/media_socket.h index 1f1e1c662..0eeab20a4 100644 --- a/daemon/media_socket.h +++ b/daemon/media_socket.h @@ -15,6 +15,9 @@ +typedef int rtcp_filter_func(str *, GQueue *); + + struct logical_intf { diff --git a/daemon/rtcp.c b/daemon/rtcp.c index d99924522..d6783b1f0 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -616,13 +616,13 @@ next: static void rtcp_ce_free(void *p) { g_slice_free1(sizeof(struct rtcp_chain_element), p); } -static void rtcp_list_free(GQueue *q) { +void rtcp_list_free(GQueue *q) { g_queue_clear_full(q, rtcp_ce_free); } -static int __rtcp_parse(GQueue *q, const str *_s, struct stream_fd *sfd, const endpoint_t *src, +int rtcp_parse(GQueue *q, const str *_s, struct stream_fd *sfd, const endpoint_t *src, const struct timeval *tv) { struct rtcp_header *hdr; @@ -704,26 +704,15 @@ error: return -1; } -void rtcp_parse(const str *s, struct stream_fd *sfd, const endpoint_t *src, const struct timeval *tv) { - GQueue rtcp_list = G_QUEUE_INIT; - if (__rtcp_parse(&rtcp_list, s, sfd, src, tv)) - return; - rtcp_list_free(&rtcp_list); -} - -int rtcp_avpf2avp(str *s, struct stream_fd *sfd, const endpoint_t *src, const struct timeval *tv) { - GQueue rtcp_list = G_QUEUE_INIT; +int rtcp_avpf2avp_filter(str *s, GQueue *rtcp_list) { GList *l; struct rtcp_chain_element *el; void *start; unsigned int removed, left; - if (__rtcp_parse(&rtcp_list, s, sfd, src, tv)) - return 0; - left = s->len; removed = 0; - for (l = rtcp_list.head; l; l = l->next) { + for (l = rtcp_list->head; l; l = l->next) { el = l->data; left -= el->len; @@ -740,8 +729,6 @@ int rtcp_avpf2avp(str *s, struct stream_fd *sfd, const endpoint_t *src, const st } } - rtcp_list_free(&rtcp_list); - s->len -= removed; if (!s->len) return -1; diff --git a/daemon/rtcp.h b/daemon/rtcp.h index cf7e3d870..480dd8ed3 100644 --- a/daemon/rtcp.h +++ b/daemon/rtcp.h @@ -3,6 +3,7 @@ #include "str.h" #include "call.h" +#include "media_socket.h" #include @@ -12,14 +13,15 @@ struct ssrc_ctx; -int rtcp_avpf2avp(str *, struct stream_fd *sfd, const endpoint_t *, const struct timeval *); int rtcp_avp2savp(str *, struct crypto_context *, struct ssrc_ctx *); int rtcp_savp2avp(str *, struct crypto_context *, struct ssrc_ctx *); int rtcp_payload(struct rtcp_packet **out, str *p, const str *s); -//void parse_and_log_rtcp_report(struct stream_fd *sfd, const str *, const endpoint_t *, const struct timeval *); -void rtcp_parse(const str *, struct stream_fd *sfd, const endpoint_t *, const struct timeval *); +int rtcp_parse(GQueue *q, const str *, struct stream_fd *sfd, const endpoint_t *, const struct timeval *); +void rtcp_list_free(GQueue *q); + +rtcp_filter_func rtcp_avpf2avp_filter; void rtcp_init();