diff --git a/README.md b/README.md index bc0bac352..db5e20d70 100644 --- a/README.md +++ b/README.md @@ -727,13 +727,22 @@ Optionally included keys are: used TOS value is left unchanged. If this key is not present or its value is too large (256 or more), then the TOS value is reverted to the default (as per `--tos` command line). +* `DTLS` + + Contains a string and influences the behaviour of DTLS-SRTP. Currently the only recognized option + is `passive`, which instructs *rtpengine* to prefer the passive (i.e. server) role for the DTLS + handshake. The default is to take the active (client) role if possible. This is useful in cases where + the SRTP endpoint isn't able to receive or process the DTLS handshake packets, for example when it's + behind NAT or needs to finish ICE processing first. + An example of a complete `offer` request dictionary could be (SDP body abbreviated): { "command": "offer", "call-id": "cfBXzDSZqhYNcXM", "from-tag": "mS9rSAn0Cr", "sdp": "v=0\r\no=...", "via-branch": "5KiTRPZHH1nL6", "flags": [ "trust address" ], "replace": [ "origin", "session connection" ], "address family": "IP6", "received-from": [ "IP4", "10.65.31.43" ], - "ICE": "force", "transport protocol": "RTP/SAVPF", "media address": "2001:d8::6f24:65b" } + "ICE": "force", "transport protocol": "RTP/SAVPF", "media address": "2001:d8::6f24:65b", + "DTLS": "passive" } The response message only contains the key `sdp` in addition to `result`, which contains the re-written SDP body that the SIP proxy should insert into the SIP message. diff --git a/daemon/call.c b/daemon/call.c index afd0895ab..f166280fd 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1884,6 +1884,8 @@ static void __generate_crypto(const struct sdp_ng_flags *flags, struct call_medi MEDIA_SET(this, SETUP_ACTIVE); } else { + if (flags->dtls_passive && MEDIA_ISSET(this, SETUP_PASSIVE)) + MEDIA_CLEAR(this, SETUP_ACTIVE); /* if we can be active, we will, otherwise we'll be passive */ if (MEDIA_ISSET(this, SETUP_ACTIVE)) MEDIA_CLEAR(this, SETUP_PASSIVE); @@ -2167,6 +2169,10 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, && (tmp & (MEDIA_FLAG_SETUP_ACTIVE | MEDIA_FLAG_SETUP_PASSIVE)) == MEDIA_FLAG_SETUP_PASSIVE) MEDIA_CLEAR(other_media, SETUP_ACTIVE); + /* if passive mode is requested, honour it if we can */ + if (flags->dtls_passive && MEDIA_ISSET(other_media, SETUP_PASSIVE)) + MEDIA_CLEAR(other_media, SETUP_ACTIVE); + if (memcmp(&other_media->fingerprint, &sp->fingerprint, sizeof(sp->fingerprint))) { __fingerprint_changed(other_media); other_media->fingerprint = sp->fingerprint; diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 60739cb2c..b449c5de3 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -530,6 +530,14 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu STR_FMT(&s)); } + if (bencode_dictionary_get_str(input, "DTLS", &s)) { + if (!str_cmp(&s, "passive")) + out->dtls_passive = 1; + else + ilog(LOG_WARN, "Unknown 'DTLS' flag encountered: '"STR_FORMAT"'", + STR_FMT(&s)); + } + if ((list = bencode_dictionary_get_expect(input, "rtcp-mux", BENCODE_LIST))) { for (it = list->child; it; it = it->sibling) { if (!bencode_strcmp(it, "offer")) diff --git a/daemon/sdp.h b/daemon/sdp.h index 4036b550c..272c4eae1 100644 --- a/daemon/sdp.h +++ b/daemon/sdp.h @@ -31,7 +31,8 @@ struct sdp_ng_flags { rtcp_mux_accept:1, rtcp_mux_reject:1, strict_source:1, - media_handover:1; + media_handover:1, + dtls_passive:1; }; struct sdp_chopper { diff --git a/utils/ng-client b/utils/ng-client index 97f06177a..dcaff839c 100755 --- a/utils/ng-client +++ b/utils/ng-client @@ -29,6 +29,7 @@ GetOptions( 'sdp=s' => \$options{'sdp'}, 'sdp-file=s' => \$options{'sdp-file'}, 'ICE=s' => \$options{'ICE'}, + 'DTLS=s' => \$options{'DTLS'}, 'rtcp-mux-offer' => \$options{'rtcp-mux-offer'}, 'rtcp-mux-demux' => \$options{'rtcp-mux-demux'}, 'rtcp-mux-accept' => \$options{'rtcp-mux-accept'}, @@ -46,7 +47,7 @@ my $cmd = shift(@ARGV) or die; my %packet = (command => $cmd); -for my $x (split(',', 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,TOS')) { +for my $x (split(',', 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,TOS,DTLS')) { defined($options{$x}) and $packet{$x} = $options{$x}; } for my $x (split(',', 'trust address,symmetric,asymmetric,force,strict source,media handover')) {