diff options
Diffstat (limited to 'res')
-rw-r--r-- | res/res_rtp_asterisk.c | 81 | ||||
-rw-r--r-- | res/res_stasis_device_state.c | 10 | ||||
-rw-r--r-- | res/res_xmpp.c | 16 |
3 files changed, 100 insertions, 7 deletions
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index f6bf34211..611920e80 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -182,6 +182,16 @@ struct ast_rtp_ioqueue_thread { /*! \brief List of ioqueue threads */ static AST_LIST_HEAD_STATIC(ioqueues, ast_rtp_ioqueue_thread); +/*! \brief Structure which contains ICE host candidate mapping information */ +struct ast_ice_host_candidate { + pj_sockaddr local; + pj_sockaddr advertised; + AST_RWLIST_ENTRY(ast_ice_host_candidate) next; +}; + +/*! \brief List of ICE host candidate mappings */ +static AST_RWLIST_HEAD_STATIC(host_candidates, ast_ice_host_candidate); + #endif #define FLAG_3389_WARNING (1 << 0) @@ -451,6 +461,38 @@ static void dtls_srtp_stop_timeout_timer(struct ast_rtp_instance *instance, stru static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *ice, int use_srtp); #ifdef HAVE_PJPROJECT +/*! \brief Helper function which clears the ICE host candidate mapping */ +static void host_candidate_overrides_clear(void) +{ + struct ast_ice_host_candidate *candidate; + + AST_RWLIST_WRLOCK(&host_candidates); + AST_RWLIST_TRAVERSE_SAFE_BEGIN(&host_candidates, candidate, next) { + AST_RWLIST_REMOVE_CURRENT(next); + ast_free(candidate); + } + AST_RWLIST_TRAVERSE_SAFE_END; + AST_RWLIST_UNLOCK(&host_candidates); +} + +/*! \brief Applies the ICE host candidate mapping */ +static void host_candidate_overrides_apply(unsigned int count, pj_sockaddr addrs[]) +{ + int pos; + struct ast_ice_host_candidate *candidate; + + AST_RWLIST_RDLOCK(&host_candidates); + for (pos = 0; pos < count; pos++) { + AST_LIST_TRAVERSE(&host_candidates, candidate, next) { + if (!pj_sockaddr_cmp(&candidate->local, &addrs[pos])) { + pj_sockaddr_copy_addr(&addrs[pos], &candidate->advertised); + break; + } + } + } + AST_RWLIST_UNLOCK(&host_candidates); +} + /*! \brief Helper function which updates an ast_sockaddr with the candidate used for the component */ static void update_address_with_ice_candidate(struct ast_rtp *rtp, enum ast_rtp_ice_component_type component, struct ast_sockaddr *cand_address) @@ -2368,6 +2410,8 @@ static void rtp_add_candidates_to_ice(struct ast_rtp_instance *instance, struct pj_enum_ip_interface(pj_AF_INET6(), &count, address); } + host_candidate_overrides_apply(count, address); + for (pos = 0; pos < count; pos++) { pj_sockaddr_set_port(&address[pos], port); ast_rtp_ice_add_cand(rtp, component, transport, PJ_ICE_CAND_TYPE_HOST, 65535, &address[pos], &address[pos], NULL, @@ -5257,6 +5301,11 @@ static int rtp_reload(int reload) const char *s; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; +#ifdef HAVE_PJPROJECT + struct ast_variable *var; + struct ast_ice_host_candidate *candidate; +#endif + cfg = ast_config_load2("rtp.conf", "rtp", config_flags); if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) { return 0; @@ -5283,6 +5332,7 @@ static int rtp_reload(int reload) turnaddr = pj_str(NULL); turnusername = pj_str(NULL); turnpassword = pj_str(NULL); + host_candidate_overrides_clear(); #endif if (cfg) { @@ -5362,6 +5412,36 @@ static int rtp_reload(int reload) if ((s = ast_variable_retrieve(cfg, "general", "turnpassword"))) { pj_strdup2_with_null(pool, &turnpassword, s); } + + AST_RWLIST_WRLOCK(&host_candidates); + for (var = ast_variable_browse(cfg, "ice_host_candidates"); var; var = var->next) { + struct ast_sockaddr local_addr, advertised_addr; + pj_str_t address; + + ast_sockaddr_setnull(&local_addr); + ast_sockaddr_setnull(&advertised_addr); + + if (ast_parse_arg(var->name, PARSE_ADDR | PARSE_PORT_IGNORE, &local_addr)) { + ast_log(LOG_WARNING, "Invalid local ICE host address: %s\n", var->name); + continue; + } + + if (ast_parse_arg(var->value, PARSE_ADDR | PARSE_PORT_IGNORE, &advertised_addr)) { + ast_log(LOG_WARNING, "Invalid advertised ICE host address: %s\n", var->value); + continue; + } + + if (!(candidate = ast_calloc(1, sizeof(*candidate)))) { + ast_log(LOG_ERROR, "Failed to allocate ICE host candidate mapping.\n"); + break; + } + + pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&address, ast_sockaddr_stringify(&local_addr)), &candidate->local); + pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&address, ast_sockaddr_stringify(&advertised_addr)), &candidate->advertised); + + AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next); + } + AST_RWLIST_UNLOCK(&host_candidates); #endif ast_config_destroy(cfg); } @@ -5464,6 +5544,7 @@ static int unload_module(void) ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp)); #ifdef HAVE_PJPROJECT + host_candidate_overrides_clear(); pj_thread_register_check(); rtp_terminate_pjproject(); #endif diff --git a/res/res_stasis_device_state.c b/res/res_stasis_device_state.c index c0b6859ca..be082dcc8 100644 --- a/res/res_stasis_device_state.c +++ b/res/res_stasis_device_state.c @@ -303,6 +303,12 @@ static void device_state_cb(void *data, struct stasis_subscription *sub, { struct ast_device_state_message *device_state; + if (stasis_subscription_final_message(sub, msg)) { + /* Remove stasis subscription's reference to device_state_subscription */ + ao2_ref(data, -1); + return; + } + if (ast_device_state_message_type() != stasis_message_type(msg)) { return; } @@ -365,10 +371,12 @@ static int subscribe_device_state(struct stasis_app *app, void *obj) ast_debug(3, "Subscribing to device %s\n", sub->device_name); - sub->sub = stasis_subscribe_pool(topic, device_state_cb, sub); + sub->sub = stasis_subscribe_pool(topic, device_state_cb, ao2_bump(sub)); if (!sub->sub) { ast_log(LOG_ERROR, "Unable to subscribe to device %s\n", sub->device_name); + /* Reference we added when attempting to stasis_subscribe_pool */ + ao2_ref(sub, -1); return -1; } diff --git a/res/res_xmpp.c b/res/res_xmpp.c index d9791431d..ed35cd169 100644 --- a/res/res_xmpp.c +++ b/res/res_xmpp.c @@ -3130,6 +3130,10 @@ done: /*! \brief Internal function called when we authenticated as a component */ static int xmpp_component_authenticating(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node) { + if (!strcmp(iks_name(node), "stream:features")) { + return 0; + } + if (strcmp(iks_name(node), "handshake")) { ast_log(LOG_ERROR, "Failed to authenticate component '%s'\n", client->name); return -1; @@ -3305,6 +3309,11 @@ static int xmpp_pak_presence(struct ast_xmpp_client *client, struct ast_xmpp_cli int status = pak->show ? pak->show : STATUS_DISAPPEAR; enum ast_device_state state = AST_DEVICE_UNAVAILABLE; + /* If this is a component presence probe request answer immediately with our presence status */ + if (ast_test_flag(&cfg->flags, XMPP_COMPONENT) && !ast_strlen_zero(type) && !strcasecmp(type, "probe")) { + xmpp_client_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), cfg->status, cfg->statusmsg); + } + /* If no resource is available this is a general buddy presence update, which we will ignore */ if (!pak->from->resource) { return 0; @@ -3319,11 +3328,6 @@ static int xmpp_pak_presence(struct ast_xmpp_client *client, struct ast_xmpp_cli return 0; } - /* If this is a component presence probe request answer immediately with our presence status */ - if (ast_test_flag(&cfg->flags, XMPP_COMPONENT) && !ast_strlen_zero(type) && !strcasecmp(type, "probe")) { - xmpp_client_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), cfg->status, cfg->statusmsg); - } - ao2_lock(buddy->resources); if (!(resource = ao2_callback(buddy->resources, OBJ_NOLOCK, xmpp_resource_cmp, pak->from->resource))) { @@ -3864,7 +3868,7 @@ static int xmpp_client_config_post_apply(void *obj, void *arg, int flags) cfg->client->jid = iks_id_new(cfg->client->stack, cfg->user); } - if (!cfg->client->jid || ast_strlen_zero(cfg->client->jid->user)) { + if (!cfg->client->jid || (ast_strlen_zero(cfg->client->jid->user) && !ast_test_flag(&cfg->flags, XMPP_COMPONENT))) { ast_log(LOG_ERROR, "Jabber identity '%s' could not be created for client '%s' - client not active\n", cfg->user, cfg->name); return -1; } |