--- channels/chan_sip.c 2013-03-27 19:51:29.000000000 +0000 +++ ../../asterisk-11.4.0-rc1/channels/chan_sip.c 2013-04-14 19:50:51.968832287 +0000 @@ -12531,6 +12531,11 @@ struct ao2_container *candidates; struct ao2_iterator i; struct ast_rtp_engine_ice_candidate *candidate; + int srflx_count = 0; + char port_buf[6]; + char *rtp_port; + char *rtcp_port; + int i_port; /* If no ICE support is present we can't very well add the attributes */ if (!ice || !(candidates = ice->get_local_candidates(instance))) { @@ -12549,8 +12554,37 @@ while ((candidate = ao2_iterator_next(&i))) { ast_str_append(a_buf, 0, "a=candidate:%s %d %s %d ", candidate->foundation, candidate->id, candidate->transport, candidate->priority); ast_str_append(a_buf, 0, "%s ", ast_sockaddr_stringify_host(&candidate->address)); - ast_str_append(a_buf, 0, "%s typ ", ast_sockaddr_stringify_port(&candidate->address)); + /* + * ASTERISK-21383 fix - as per RFC 5245 section 3: + * + * Default Destination/Candidate: The default destination for a + * component of a media stream is the transport address that would be + * used by an agent that is not ICE aware. For the RTP component, + * the default IP address is in the c line of the SDP, and the port + * is in the m line. For the RTCP component, it is in the rtcp + * attribute when present, and when not present, the IP address is in + * the c line and 1 plus the port is in the m line. A default + * candidate for a component is one whose transport address matches + * the default destination for that component. + */ + if(candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) { + // don't increment the port +1 for the first srflx candidate, only the second one + if(srflx_count == 0) { + srflx_count++; + ast_str_append(a_buf, 0, "%s typ ", ast_sockaddr_stringify_port(&candidate->address)); + } else { + ast_debug(3, "About to increment the port for the second srflx candidate by 1, as we assume rtcp attribute not present in SDP...\n"); + rtp_port = ast_sockaddr_stringify_port(&candidate->address); + i_port = atoi(rtp_port); + sprintf(port_buf, "%d", ++i_port); + rtcp_port = port_buf; + ast_debug(1, "Incremented candidate port for the second srflx component-id (rtcp) by 1 and set to %s\n", rtcp_port); + ast_str_append(a_buf, 0, "%s typ ", rtcp_port); + } + } else { + ast_str_append(a_buf, 0, "%s typ ", ast_sockaddr_stringify_port(&candidate->address)); + } if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) { ast_str_append(a_buf, 0, "host"); } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {