diff --git a/README.md b/README.md index aaee16548..abcf6d891 100644 --- a/README.md +++ b/README.md @@ -829,6 +829,14 @@ Optionally included keys are: Valid values are: `RTP/AVP`, `RTP/AVPF`, `RTP/SAVP`, `RTP/SAVPF`. + Additionally the string `accept` can be given in `answer` messages to allow a special case: By + default (when no `transport-protocol` override is given) in answer messages, *rtpengine* will + use the transport protocol that was originally offered. However, an answering client may answer + with a different protocol than what was offered (e.g. offer was for `RTP/AVP` and answer comes + with `RTP/AVPF`). The default behaviour for *rtpengine* is to ignore this protocol change and + still proceed with the protocol that was originally offered. Using the `accept` option here + tells *rtpengine* to go along with this protocol change and pass it to the original offerer. + * `media address` This can be used to override both the addresses present in the SDP body diff --git a/daemon/call.c b/daemon/call.c index 9a2071a7f..5e8ddc4d7 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1878,14 +1878,30 @@ static void __update_media_protocol(struct call_media *media, struct call_media /* deduct protocol from stream parameters received */ if (other_media->protocol != sp->protocol) { other_media->protocol = sp->protocol; - /* if the endpoint changes the protocol, we reset the other side's + /* If the endpoint changes the protocol, we reset the other side's * protocol as well. this lets us remember our previous overrides, * but also lets endpoints re-negotiate. - * Exception: OSRTP answer/accept. */ - if (flags && flags->opmode == OP_ANSWER && other_media->protocol && other_media->protocol->rtp - && !other_media->protocol->srtp - && media->protocol && media->protocol->osrtp && flags->osrtp_accept) - ; + * Answers are a special case: handle OSRTP answer/accept, but otherwise + * answer with the same protocol that was offered, unless we're instructed + * not to. */ + if (flags && flags->opmode == OP_ANSWER) { + // OSRTP? + if (other_media->protocol && other_media->protocol->rtp + && !other_media->protocol->srtp + && media->protocol && media->protocol->osrtp) + { + // accept it? + if (flags->osrtp_accept) + ; + else + media->protocol = NULL; // reject + } + // pass through any other protocol change? + else if (!flags->protocol_accept) + ; + else + media->protocol = NULL; + } else media->protocol = NULL; } diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 330550c2a..f3f0a8810 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -931,8 +931,13 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu call_ng_flags_list(out, input, "T.38", ng_t38_option, NULL); #endif - bencode_get_alt(input, "transport-protocol", "transport protocol", &out->transport_protocol_str); - out->transport_protocol = transport_protocol(&out->transport_protocol_str); + str transport_protocol_str; + bencode_get_alt(input, "transport-protocol", "transport protocol", &transport_protocol_str); + if (!str_cmp(&transport_protocol_str, "accept")) + out->protocol_accept = 1; + else + out->transport_protocol = transport_protocol(&transport_protocol_str); + bencode_get_alt(input, "media-address", "media address", &out->media_address); if (bencode_get_alt(input, "address-family", "address family", &out->address_family_str)) out->address_family = get_socket_family_rfc(&out->address_family_str); diff --git a/include/call_interfaces.h b/include/call_interfaces.h index b8d772175..26b84802e 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -25,7 +25,6 @@ struct sdp_ng_flags { str received_from_family; str received_from_address; str media_address; - str transport_protocol_str; str address_family_str; const struct transport_protocol *transport_protocol; sockaddr_t parsed_received_from; @@ -47,6 +46,7 @@ struct sdp_ng_flags { rev_ptime; GHashTable *sdes_no; int asymmetric:1, + protocol_accept:1, no_redis_update:1, unidirectional:1, trust_address:1,