/*! \brief Function which adds ICE attributes to a media stream */ static void add_ice_to_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media) { struct ast_rtp_engine_ice *ice; struct ao2_container *candidates; const char *username, *password; pj_str_t stmp; pjmedia_sdp_attr *attr; struct ao2_iterator it_candidates; struct ast_rtp_engine_ice_candidate *candidate; if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp)) || !(candidates = ice->get_local_candidates(session_media->rtp))) { return; } if ((username = ice->get_ufrag(session_media->rtp))) { attr = pjmedia_sdp_attr_create(pool, "ice-ufrag", pj_cstr(&stmp, username)); media->attr[media->attr_count++] = attr; } if ((password = ice->get_password(session_media->rtp))) { attr = pjmedia_sdp_attr_create(pool, "ice-pwd", pj_cstr(&stmp, password)); media->attr[media->attr_count++] = attr; } it_candidates = ao2_iterator_init(candidates, 0); for (; (candidate = ao2_iterator_next(&it_candidates)); ao2_ref(candidate, -1)) { struct ast_str *attr_candidate = ast_str_create(128); ast_str_set(&attr_candidate, -1, "%s %u %s %d %s ", candidate->foundation, candidate->id, candidate->transport, candidate->priority, ast_sockaddr_stringify_addr_remote(&candidate->address)); ast_str_append(&attr_candidate, -1, "%s typ ", ast_sockaddr_stringify_port(&candidate->address)); switch (candidate->type) { case AST_RTP_ICE_CANDIDATE_TYPE_HOST: ast_str_append(&attr_candidate, -1, "host"); break; case AST_RTP_ICE_CANDIDATE_TYPE_SRFLX: ast_str_append(&attr_candidate, -1, "srflx"); break; case AST_RTP_ICE_CANDIDATE_TYPE_RELAYED: ast_str_append(&attr_candidate, -1, "relay"); break; } if (!ast_sockaddr_isnull(&candidate->relay_address)) { ast_str_append(&attr_candidate, -1, " raddr %s rport", ast_sockaddr_stringify_addr_remote(&candidate->relay_address)); ast_str_append(&attr_candidate, -1, " %s", ast_sockaddr_stringify_port(&candidate->relay_address)); } attr = pjmedia_sdp_attr_create(pool, "candidate", pj_cstr(&stmp, ast_str_buffer(attr_candidate))); media->attr[media->attr_count++] = attr; ast_free(attr_candidate); } ao2_iterator_destroy(&it_candidates); ao2_ref(candidates, -1); }
struct ast_json *ast_json_ipaddr(const struct ast_sockaddr *addr, enum ast_transport transport_type) { struct ast_str *string = ast_str_alloca(64); if (!string) { return NULL; } ast_str_set(&string, 0, (ast_sockaddr_is_ipv4(addr) || ast_sockaddr_is_ipv4_mapped(addr)) ? "IPV4/" : "IPV6/"); if (transport_type) { char *transport_string = NULL; /* NOTE: None will be applied if multiple transport types are specified in transport_type */ switch(transport_type) { case AST_TRANSPORT_UDP: transport_string = "UDP"; break; case AST_TRANSPORT_TCP: transport_string = "TCP"; break; case AST_TRANSPORT_TLS: transport_string = "TLS"; break; case AST_TRANSPORT_WS: transport_string = "WS"; break; case AST_TRANSPORT_WSS: transport_string = "WSS"; break; } if (transport_string) { ast_str_append(&string, 0, "%s/", transport_string); } } ast_str_append(&string, 0, "%s", ast_sockaddr_stringify_addr(addr)); ast_str_append(&string, 0, "/%s", ast_sockaddr_stringify_port(addr)); return ast_json_string_create(ast_str_buffer(string)); }