diff --git a/daemon/call.c b/daemon/call.c index dc90318c3..e2f547e15 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -59,65 +59,6 @@ struct xmlrpc_helper { GQueue strings; }; -const struct transport_protocol transport_protocols[] = { - [PROTO_RTP_AVP] = { - .index = PROTO_RTP_AVP, - .name = "RTP/AVP", - .rtp = 1, - .srtp = 0, - .avpf = 0, - .tcp = 0, - }, - [PROTO_RTP_SAVP] = { - .index = PROTO_RTP_SAVP, - .name = "RTP/SAVP", - .rtp = 1, - .srtp = 1, - .avpf = 0, - .tcp = 0, - }, - [PROTO_RTP_AVPF] = { - .index = PROTO_RTP_AVPF, - .name = "RTP/AVPF", - .rtp = 1, - .srtp = 0, - .avpf = 1, - .tcp = 0, - }, - [PROTO_RTP_SAVPF] = { - .index = PROTO_RTP_SAVPF, - .name = "RTP/SAVPF", - .rtp = 1, - .srtp = 1, - .avpf = 1, - .tcp = 0, - }, - [PROTO_UDP_TLS_RTP_SAVP] = { - .index = PROTO_UDP_TLS_RTP_SAVP, - .name = "UDP/TLS/RTP/SAVP", - .rtp = 1, - .srtp = 1, - .avpf = 0, - .tcp = 0, - }, - [PROTO_UDP_TLS_RTP_SAVPF] = { - .index = PROTO_UDP_TLS_RTP_SAVPF, - .name = "UDP/TLS/RTP/SAVPF", - .rtp = 1, - .srtp = 1, - .avpf = 1, - .tcp = 0, - }, - [PROTO_UDPTL] = { - .index = PROTO_UDPTL, - .name = "udptl", - .rtp = 0, - .srtp = 0, - .avpf = 0, - .tcp = 0, - }, -}; -const int num_transport_protocols = G_N_ELEMENTS(transport_protocols); /* XXX rework these */ struct stats rtpe_statsps; @@ -2859,22 +2800,3 @@ void call_get_all_calls(GQueue *q) { rwlock_unlock_r(&rtpe_callhash_lock); } - - -const struct transport_protocol *transport_protocol(const str *s) { - int i; - - if (!s || !s->s) - goto out; - - for (i = 0; i < num_transport_protocols; i++) { - if (strlen(transport_protocols[i].name) != s->len) - continue; - if (strncasecmp(transport_protocols[i].name, s->s, s->len)) - continue; - return &transport_protocols[i]; - } - -out: - return NULL; -} diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 8579df685..f74ac24e4 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -38,20 +38,7 @@ #endif -typedef int (*rewrite_func)(str *, struct packet_stream *, struct stream_fd *, const endpoint_t *, - const struct timeval *, struct ssrc_ctx *); - -struct streamhandler_io { - 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; - const struct streamhandler_io *out; -}; struct intf_rr { struct logical_intf hash_key; mutex_t lock; @@ -79,7 +66,7 @@ struct packet_handler_ctx { }; -static void determine_handler(struct packet_stream *in, const struct packet_stream *out); +static void __determine_handler(struct packet_stream *in, const struct packet_stream *out); static int __k_null(struct rtpengine_srtp *s, struct packet_stream *); static int __k_srtp_encrypt(struct rtpengine_srtp *s, struct packet_stream *); @@ -100,6 +87,70 @@ static struct logical_intf *__get_logical_interface(const str *name, sockfamily_ +/* ********** */ + +const struct transport_protocol transport_protocols[] = { + [PROTO_RTP_AVP] = { + .index = PROTO_RTP_AVP, + .name = "RTP/AVP", + .rtp = 1, + .srtp = 0, + .avpf = 0, + .tcp = 0, + }, + [PROTO_RTP_SAVP] = { + .index = PROTO_RTP_SAVP, + .name = "RTP/SAVP", + .rtp = 1, + .srtp = 1, + .avpf = 0, + .tcp = 0, + }, + [PROTO_RTP_AVPF] = { + .index = PROTO_RTP_AVPF, + .name = "RTP/AVPF", + .rtp = 1, + .srtp = 0, + .avpf = 1, + .tcp = 0, + }, + [PROTO_RTP_SAVPF] = { + .index = PROTO_RTP_SAVPF, + .name = "RTP/SAVPF", + .rtp = 1, + .srtp = 1, + .avpf = 1, + .tcp = 0, + }, + [PROTO_UDP_TLS_RTP_SAVP] = { + .index = PROTO_UDP_TLS_RTP_SAVP, + .name = "UDP/TLS/RTP/SAVP", + .rtp = 1, + .srtp = 1, + .avpf = 0, + .tcp = 0, + }, + [PROTO_UDP_TLS_RTP_SAVPF] = { + .index = PROTO_UDP_TLS_RTP_SAVPF, + .name = "UDP/TLS/RTP/SAVPF", + .rtp = 1, + .srtp = 1, + .avpf = 1, + .tcp = 0, + }, + [PROTO_UDPTL] = { + .index = PROTO_UDPTL, + .name = "udptl", + .rtp = 0, + .srtp = 0, + .avpf = 0, + .tcp = 0, + }, +}; +const int num_transport_protocols = G_N_ELEMENTS(transport_protocols); + + +/* ********** */ static const struct streamhandler_io __shio_noop = { // non-RTP protocols .kernel = __k_null, @@ -994,7 +1045,7 @@ void kernelize(struct packet_stream *stream) { goto no_kernel; } - determine_handler(stream, sink); + __determine_handler(stream, sink); if (is_addr_unspecified(&sink->advertised_endpoint.address) || !sink->advertised_endpoint.port) @@ -1124,41 +1175,58 @@ void unkernelize(struct packet_stream *ps) { -/* must be called with call->master_lock held in R, and in->in_lock held */ -static void determine_handler(struct packet_stream *in, const struct packet_stream *out) { +const struct streamhandler *determine_handler(const struct transport_protocol *in_proto, + const struct transport_protocol *out_proto, int must_recrypt) +{ const struct streamhandler * const *sh_pp, *sh; const struct streamhandler * const * const *matrix; + matrix = __sh_matrix; + if (must_recrypt) + matrix = __sh_matrix_recrypt; + + sh_pp = matrix[in_proto->index]; + if (!sh_pp) + goto err; + sh = sh_pp[out_proto->index]; + if (!sh) + goto err; + return sh; + +err: + ilog(LOG_WARNING, "Unknown transport protocol encountered"); + return &__sh_noop; +} + +/* must be called with call->master_lock held in R, and in->in_lock held */ +static void __determine_handler(struct packet_stream *in, const struct packet_stream *out) { + const struct transport_protocol *in_proto, *out_proto; + int must_recrypt = 0; + if (in->handler) return; if (MEDIA_ISSET(in->media, PASSTHRU)) goto noop; - if (!in->media->protocol) + in_proto = in->media->protocol; + out_proto = out->media->protocol; + + if (!in_proto) goto err; - if (!out->media->protocol) + if (!out_proto) goto err; - matrix = __sh_matrix; if (MEDIA_ISSET(in->media, DTLS) || MEDIA_ISSET(out->media, DTLS)) - matrix = __sh_matrix_recrypt; + must_recrypt = 1; else if (in->call->recording) - matrix = __sh_matrix_recrypt; - else if (in->media->protocol->srtp && out->media->protocol->srtp + must_recrypt = 1; + else if (in_proto->srtp && out_proto->srtp && in->selected_sfd && out->selected_sfd && (crypto_params_cmp(&in->crypto.params, &out->selected_sfd->crypto.params) || crypto_params_cmp(&out->crypto.params, &in->selected_sfd->crypto.params))) - matrix = __sh_matrix_recrypt; - - - sh_pp = matrix[in->media->protocol->index]; - if (!sh_pp) - goto err; - sh = sh_pp[out->media->protocol->index]; - if (!sh) - goto err; - in->handler = sh; + must_recrypt = 1; + in->handler = determine_handler(in_proto, out_proto, must_recrypt); return; err: @@ -1362,7 +1430,7 @@ static void media_packet_rtp(struct packet_handler_ctx *phc) static int media_packet_decrypt(struct packet_handler_ctx *phc) { mutex_lock(&phc->in_srtp->in_lock); - determine_handler(phc->in_srtp, phc->sink); + __determine_handler(phc->in_srtp, phc->sink); // XXX use an array with index instead of if/else if (G_LIKELY(!phc->rtcp)) { @@ -1395,28 +1463,35 @@ static int media_packet_decrypt(struct packet_handler_ctx *phc) return ret; } -static int media_packet_encrypt(struct packet_handler_ctx *phc) { - int ret = 0; +int media_packet_encrypt(rewrite_func encrypt_func, struct packet_stream *out, struct media_packet *mp) { + int ret = 0x00; // 0x01 = error, 0x02 = update - if (!phc->encrypt_func) - return 0; + if (!encrypt_func) + return 0x00; - mutex_lock(&phc->out_srtp->out_lock); + mutex_lock(&out->out_lock); - for (GList *l = phc->mp.packets_out.head; l; l = l->next) { + for (GList *l = mp->packets_out.head; l; l = l->next) { struct codec_packet *p = l->data; - int encret = phc->encrypt_func(&p->s, phc->out_srtp, NULL, NULL, NULL, phc->mp.ssrc_out); + int encret = encrypt_func(&p->s, out, NULL, NULL, NULL, mp->ssrc_out); if (encret == 1) - phc->update = 1; + ret |= 0x02; else if (encret != 0) - ret = -1; + ret |= 0x01; } - mutex_unlock(&phc->out_srtp->out_lock); + mutex_unlock(&out->out_lock); return ret; } +static int __media_packet_encrypt(struct packet_handler_ctx *phc) { + int ret = media_packet_encrypt(phc->encrypt_func, phc->out_srtp, &phc->mp); + if (ret & 0x02) + phc->update = 1; + return (ret & 0x01) ? -1 : 0; +} + // returns: 0 = OK, forward packet; -1 = drop packet @@ -1681,7 +1756,7 @@ static int stream_packet(struct packet_handler_ctx *phc) { } if (G_LIKELY(handler_ret >= 0)) - handler_ret = media_packet_encrypt(phc); + handler_ret = __media_packet_encrypt(phc); if (phc->unkernelize) // for RTCP packet index updates unkernelize(phc->mp.stream); @@ -1846,3 +1921,21 @@ struct stream_fd *stream_fd_new(socket_t *fd, struct call *call, const struct lo return sfd; } + +const struct transport_protocol *transport_protocol(const str *s) { + int i; + + if (!s || !s->s) + goto out; + + for (i = 0; i < num_transport_protocols; i++) { + if (strlen(transport_protocols[i].name) != s->len) + continue; + if (strncasecmp(transport_protocols[i].name, s->s, s->len)) + continue; + return &transport_protocols[i]; + } + +out: + return NULL; +} diff --git a/include/call.h b/include/call.h index f16440e69..cb567c404 100644 --- a/include/call.h +++ b/include/call.h @@ -51,18 +51,6 @@ enum call_opmode { OP_OTHER, }; -enum transport_protocol_index { - PROTO_RTP_AVP = 0, - PROTO_RTP_SAVP, - PROTO_RTP_AVPF, - PROTO_RTP_SAVPF, - PROTO_UDP_TLS_RTP_SAVP, - PROTO_UDP_TLS_RTP_SAVPF, - PROTO_UDPTL, - - __PROTO_LAST, -}; - enum call_stream_state { CSS_UNKNOWN = 0, CSS_SHUTDOWN, @@ -200,6 +188,7 @@ struct codec_handler; struct rtp_payload_type; struct media_player; struct send_timer; +struct transport_protocol; typedef bencode_buffer_t call_buffer_t; @@ -210,17 +199,6 @@ typedef bencode_buffer_t call_buffer_t; -struct transport_protocol { - enum transport_protocol_index index; - const char *name; - int rtp:1; /* also set to 1 for SRTP */ - int srtp:1; - int avpf:1; - int tcp:1; -}; -extern const struct transport_protocol transport_protocols[]; - - struct stream_params { unsigned int index; /* starting with 1 */ str type; @@ -447,7 +425,6 @@ void __monologue_unkernelize(struct call_monologue *monologue); int call_stream_address46(char *o, struct packet_stream *ps, enum stream_address_format format, int *len, const struct local_intf *ifa, int keep_unspec); -const struct transport_protocol *transport_protocol(const str *s); void add_total_calls_duration_in_interval(struct timeval *interval_tv); void payload_type_free(struct rtp_payload_type *p); diff --git a/include/media_socket.h b/include/media_socket.h index 59fc21a59..e20dff182 100644 --- a/include/media_socket.h +++ b/include/media_socket.h @@ -16,10 +16,48 @@ struct media_packet; +struct transport_protocol; +struct ssrc_ctx; +struct rtpengine_srtp; typedef int rtcp_filter_func(struct media_packet *, GQueue *); +typedef int (*rewrite_func)(str *, struct packet_stream *, struct stream_fd *, const endpoint_t *, + const struct timeval *, struct ssrc_ctx *); +enum transport_protocol_index { + PROTO_RTP_AVP = 0, + PROTO_RTP_SAVP, + PROTO_RTP_AVPF, + PROTO_RTP_SAVPF, + PROTO_UDP_TLS_RTP_SAVP, + PROTO_UDP_TLS_RTP_SAVPF, + PROTO_UDPTL, + + __PROTO_LAST, +}; +struct transport_protocol { + enum transport_protocol_index index; + const char *name; + int rtp:1; /* also set to 1 for SRTP */ + int srtp:1; + int avpf:1; + int tcp:1; +}; +extern const struct transport_protocol transport_protocols[]; + + +struct streamhandler_io { + 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; + const struct streamhandler_io *out; +}; + struct logical_intf { @@ -131,6 +169,10 @@ void unkernelize(struct packet_stream *); void __stream_unconfirm(struct packet_stream *); int media_socket_dequeue(struct media_packet *mp, struct packet_stream *sink); +const struct streamhandler *determine_handler(const struct transport_protocol *in_proto, + const struct transport_protocol *out_proto, int must_recrypt); +int media_packet_encrypt(rewrite_func encrypt_func, struct packet_stream *out, struct media_packet *mp); +const struct transport_protocol *transport_protocol(const str *s); /* XXX shouldn't be necessary */ /*