diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 424f5add70894cbd0bbcda37c0501b34384b32cb..59f794454a578f0da48dfe25749fb63e4c558c67 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -5879,12 +5879,14 @@ static int iax2_getpeertrunk(struct ast_sockaddr addr) /*! \brief Create new call, interface with the PBX core */ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capability, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, unsigned int cachable) { - struct ast_channel *tmp; + struct ast_channel *tmp = NULL; struct chan_iax2_pvt *i; + struct iax2_peer *peer; struct ast_variable *v = NULL; struct ast_format_cap *native; struct ast_format *tmpfmt; struct ast_callid *callid; + char *peer_name = NULL; if (!(i = iaxs[callno])) { ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno); @@ -5896,9 +5898,27 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab return NULL; } - /* Don't hold call lock */ + if (!ast_strlen_zero(i->peer)) { + peer_name = ast_strdupa(i->peer); + } else if (!ast_strlen_zero(i->host)) { + peer_name = ast_strdupa(i->host); + } + + /* Don't hold call lock while making a channel or looking up a peer */ ast_mutex_unlock(&iaxsl[callno]); - tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "IAX2/%s-%d", i->host, i->callno); + + if (!ast_strlen_zero(peer_name)) { + peer = find_peer(peer_name, 1); + if (peer && peer->endpoint) { + tmp = ast_channel_alloc_with_endpoint(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, peer->endpoint, "IAX2/%s-%d", i->host, i->callno); + } + ao2_cleanup(peer); + } + + if (!tmp) { + tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "IAX2/%s-%d", i->host, i->callno); + } + ast_mutex_lock(&iaxsl[callno]); if (i != iaxs[callno]) { if (tmp) { diff --git a/channels/chan_motif.c b/channels/chan_motif.c index 1bdc8aa6b708518f54da97bff837da61ccc64020..e29485206f2e8d26882fc1b9ff27031d4fd566ee 100644 --- a/channels/chan_motif.c +++ b/channels/chan_motif.c @@ -75,6 +75,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/causes.h" #include "asterisk/abstract_jb.h" #include "asterisk/xmpp.h" +#include "asterisk/endpoints.h" #include "asterisk/stasis_channels.h" #include "asterisk/format_cache.h" @@ -783,7 +784,7 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j return NULL; } - if (!(chan = ast_channel_alloc(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", assignedids, requestor, 0, "Motif/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff)))) { + if (!(chan = ast_channel_alloc_with_endpoint(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", assignedids, requestor, 0, endpoint->connection->endpoint, "Motif/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff)))) { ao2_ref(caps, -1); return NULL; } diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 5812360c52822f17ae08e08e20d4439a6de6a86c..f638a1e35d51e177f2c738fe8519d5dda3795207 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -371,8 +371,12 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s return NULL; } - if (!(chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""), session->endpoint->accountcode, "", "", assignedids, requestor, 0, "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint), - (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)))) { + chan = ast_channel_alloc_with_endpoint(1, state, S_OR(session->id.number.str, ""), + S_OR(session->id.name.str, ""), session->endpoint->accountcode, "", + "", assignedids, requestor, 0, session->endpoint->persistent, + "PJSIP/%s-%08x", ast_sorcery_object_get_id(session->endpoint), + (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)); + if (!chan) { ao2_ref(caps, -1); return NULL; } @@ -455,8 +459,6 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, ast_channel_uniqueid(chan)); } - ast_endpoint_add_channel(session->endpoint->persistent, chan); - return chan; } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 44629dc3d85c871c4cc3f407253deac2f5e738c6..2a32971dced91fd43aabd28be831617925c9f9f4 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -8071,9 +8071,14 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit my_name = ast_strdupa(i->fromdomain); } - sip_pvt_unlock(i); /* Don't hold a sip pvt lock while we allocate a channel */ - tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "SIP/%s-%08x", my_name, (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)); + sip_pvt_unlock(i); + + if (i->relatedpeer && i->relatedpeer->endpoint) { + tmp = ast_channel_alloc_with_endpoint(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, i->relatedpeer->endpoint, "SIP/%s-%08x", my_name, (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)); + } else { + tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "SIP/%s-%08x", my_name, (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)); + } } if (!tmp) { ast_log(LOG_WARNING, "Unable to allocate AST channel structure for SIP channel\n"); @@ -8082,16 +8087,6 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit return NULL; } - if (i->relatedpeer && i->relatedpeer->endpoint) { - if (ast_endpoint_add_channel(i->relatedpeer->endpoint, tmp)) { - ast_channel_unlock(tmp); - ast_channel_unref(tmp); - ao2_ref(caps, -1); - sip_pvt_lock(i); - return NULL; - } - } - ast_channel_stage_snapshot(tmp); /* If we sent in a callid, bind it to the channel. */ diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index d118bc81f41db8bf60dfd2857f29bd49d3ef530c..d5d32c92185bd229e82be35758f98f4b389c35e4 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -1158,11 +1158,12 @@ struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const * and "default" context. * \note Since 12.0.0 this function returns with the newly created channel locked. */ -struct ast_channel * attribute_malloc __attribute__((format(printf, 14, 15))) +struct ast_channel * attribute_malloc __attribute__((format(printf, 15, 16))) __ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, enum ama_flags amaflag, + struct ast_endpoint *endpoint, const char *file, int line, const char *function, const char *name_fmt, ...); @@ -1178,9 +1179,14 @@ struct ast_channel * attribute_malloc __attribute__((format(printf, 14, 15))) * \note Since 12.0.0 this function returns with the newly created channel locked. */ #define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, ...) \ - __ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, \ + __ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, NULL, \ __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) +#define ast_channel_alloc_with_endpoint(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, endpoint, ...) \ + __ast_channel_alloc((needqueue), (state), (cid_num), (cid_name), (acctcode), (exten), (context), (assignedids), (requestor), (amaflag), (endpoint), \ + __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) + + #if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC) /*! * \brief Create a fake channel structure diff --git a/include/asterisk/endpoints.h b/include/asterisk/endpoints.h index 7a7a3f6b446197ed7dbd2fa163a4224644427ab2..663dd94d9c80fcb5211201010f8c61ffcdd12b74 100644 --- a/include/asterisk/endpoints.h +++ b/include/asterisk/endpoints.h @@ -77,11 +77,17 @@ const char *ast_endpoint_state_to_string(enum ast_endpoint_state state); struct ast_endpoint; /*! - * \brief Finds the endpoint with the given tech/resource id. + * \brief Finds the endpoint with the given tech[/resource] id. * * Endpoints are refcounted, so ao2_cleanup() when you're done. * - * \param id Tech/resource id to look for. + * \note The resource portion of an ID is optional. If not provided, + * an aggregate endpoint for the entire technology is returned. + * These endpoints must not be modified, but can be subscribed + * to in order to receive updates for all endpoints of a given + * technology. + * + * \param id Tech[/resource] id to look for. * \return Associated endpoint. * \return \c NULL if not found. * @@ -131,6 +137,9 @@ const char *ast_endpoint_get_tech(const struct ast_endpoint *endpoint); * * This is unique for the endpoint's technology, and immutable. * + * \note If the endpoint being queried is a technology aggregate + * endpoint, this will be an empty string. + * * \param endpoint The endpoint. * \return Resource name of the endpoint. * \return \c NULL if endpoint is \c NULL. diff --git a/include/asterisk/xmpp.h b/include/asterisk/xmpp.h index 58b14e4d3916d6620dc51f7e24157e72799606eb..294b4fdae60a25f74766446cad41069613dbdb84 100644 --- a/include/asterisk/xmpp.h +++ b/include/asterisk/xmpp.h @@ -106,6 +106,8 @@ struct ast_xmpp_message { AST_LIST_ENTRY(ast_xmpp_message) list; /*!< Linked list information */ }; +struct ast_endpoint; + /*! \brief XMPP Buddy */ struct ast_xmpp_buddy { char id[XMPP_MAX_JIDLEN]; /*!< JID of the buddy */ @@ -116,9 +118,11 @@ struct ast_xmpp_buddy { /*! \brief XMPP Client Connection */ struct ast_xmpp_client { AST_DECLARE_STRING_FIELDS( - AST_STRING_FIELD(name); /*!< Name of the client configuration */ + /*! Name of the client configuration */ + AST_STRING_FIELD(name); ); - char mid[6]; /* Message ID */ + /*! Message ID */ + char mid[6]; iksid *jid; iksparser *parser; iksfilter *filter; @@ -134,9 +138,14 @@ struct ast_xmpp_client { AST_LIST_HEAD(, ast_xmpp_message) messages; pthread_t thread; int timeout; - unsigned int reconnect:1; /*!< Reconnect this client */ - struct stasis_subscription *mwi_sub; /*!< If distributing event information the MWI subscription */ - struct stasis_subscription *device_state_sub; /*!< If distributing event information the device state subscription */ + /*! Reconnect this client */ + unsigned int reconnect:1; + /*! If distributing event information the MWI subscription */ + struct stasis_subscription *mwi_sub; + /*! If distributing event information the device state subscription */ + struct stasis_subscription *device_state_sub; + /*! The endpoint associated with this client */ + struct ast_endpoint *endpoint; }; /*! diff --git a/main/channel.c b/main/channel.c index b17dddeefe910011a807e9a8090d9f3bd99a05e4..e9e37c0fda6c59bf91656327224a9c0a2722067c 100644 --- a/main/channel.c +++ b/main/channel.c @@ -783,10 +783,11 @@ static void ast_channel_destructor(void *obj); static void ast_dummy_channel_destructor(void *obj); /*! \brief Create a new channel structure */ -static struct ast_channel * attribute_malloc __attribute__((format(printf, 13, 0))) +static struct ast_channel * attribute_malloc __attribute__((format(printf, 15, 0))) __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const struct ast_assigned_ids *assignedids, - const struct ast_channel *requestor, enum ama_flags amaflag, const char *file, int line, + const struct ast_channel *requestor, enum ama_flags amaflag, struct ast_endpoint *endpoint, + const char *file, int line, const char *function, const char *name_fmt, va_list ap) { struct ast_channel *tmp; @@ -963,6 +964,10 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char ao2_link(channels, tmp); + if (endpoint) { + ast_endpoint_add_channel(endpoint, tmp); + } + /* * And now, since the channel structure is built, and has its name, let * the world know of its existance @@ -975,6 +980,7 @@ struct ast_channel *__ast_channel_alloc(int needqueue, int state, const char *ci const char *cid_name, const char *acctcode, const char *exten, const char *context, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, enum ama_flags amaflag, + struct ast_endpoint *endpoint, const char *file, int line, const char *function, const char *name_fmt, ...) { @@ -983,7 +989,7 @@ struct ast_channel *__ast_channel_alloc(int needqueue, int state, const char *ci va_start(ap, name_fmt); result = __ast_channel_alloc_ap(needqueue, state, cid_num, cid_name, acctcode, exten, context, - assignedids, requestor, amaflag, file, line, function, name_fmt, ap); + assignedids, requestor, amaflag, endpoint, file, line, function, name_fmt, ap); va_end(ap); return result; diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index 4ad0ef3a0716941faf3c4029199638b71588bdd4..8a9e18eb0061e149815efd192dfd56361a021468 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -219,6 +219,7 @@ struct ast_channel { struct timeval sending_dtmf_tv; /*!< The time this channel started sending the current digit. (Invalid if sending_dtmf_digit is zero.) */ struct stasis_cp_single *topics; /*!< Topic for all channel's events */ struct stasis_forward *endpoint_forward; /*!< Subscription for event forwarding to endpoint's topic */ + struct stasis_forward *endpoint_cache_forward; /*!< Subscription for cache updates to endpoint's topic */ }; /*! \brief The monotonically increasing integer counter for channel uniqueids */ @@ -1528,6 +1529,7 @@ void ast_channel_internal_cleanup(struct ast_channel *chan) ast_string_field_free_memory(chan); chan->endpoint_forward = stasis_forward_cancel(chan->endpoint_forward); + chan->endpoint_cache_forward = stasis_forward_cancel(chan->endpoint_cache_forward); stasis_cp_single_unsubscribe(chan->topics); chan->topics = NULL; @@ -1570,8 +1572,14 @@ int ast_channel_forward_endpoint(struct ast_channel *chan, chan->endpoint_forward = stasis_forward_all(ast_channel_topic(chan), ast_endpoint_topic(endpoint)); + if (!chan->endpoint_forward) { + return -1; + } - if (chan->endpoint_forward == NULL) { + chan->endpoint_cache_forward = stasis_forward_all(ast_channel_topic_cached(chan), + ast_endpoint_topic(endpoint)); + if (!chan->endpoint_cache_forward) { + chan->endpoint_forward = stasis_forward_cancel(chan->endpoint_forward); return -1; } diff --git a/main/endpoints.c b/main/endpoints.c index 10b32e268d4899823e894fd5432a7db90f5b5b8b..985f6e634eebfcdae7322d748ac224cc660d05a7 100644 --- a/main/endpoints.c +++ b/main/endpoints.c @@ -46,8 +46,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") /*! Buckets for endpoint hash. Keep it prime! */ #define ENDPOINT_BUCKETS 127 +/*! Buckets for technology endpoints. */ +#define TECH_ENDPOINT_BUCKETS 11 + static struct ao2_container *endpoints; +static struct ao2_container *tech_endpoints; + struct ast_endpoint { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(tech); /*!< Technology (SIP, IAX2, etc.). */ @@ -69,6 +74,8 @@ struct ast_endpoint { struct stasis_message_router *router; /*! ast_str_container of channels associated with this endpoint */ struct ao2_container *channel_ids; + /*! Forwarding subscription from an endpoint to its tech endpoint */ + struct stasis_forward *tech_forward; }; static int endpoint_hash(const void *obj, int flags) @@ -121,7 +128,13 @@ static int endpoint_cmp(void *obj, void *arg, int flags) struct ast_endpoint *ast_endpoint_find_by_id(const char *id) { - return ao2_find(endpoints, id, OBJ_KEY); + struct ast_endpoint *endpoint = ao2_find(endpoints, id, OBJ_KEY); + + if (!endpoint) { + endpoint = ao2_find(tech_endpoints, id, OBJ_KEY); + } + + return endpoint; } struct stasis_topic *ast_endpoint_topic(struct ast_endpoint *endpoint) @@ -181,6 +194,8 @@ static void endpoint_dtor(void *obj) ao2_cleanup(endpoint->router); endpoint->router = NULL; + endpoint->tech_forward = stasis_forward_cancel(endpoint->tech_forward); + stasis_cp_single_unsubscribe(endpoint->topics); endpoint->topics = NULL; @@ -196,6 +211,7 @@ int ast_endpoint_add_channel(struct ast_endpoint *endpoint, { ast_assert(chan != NULL); ast_assert(endpoint != NULL); + ast_assert(!ast_strlen_zero(endpoint->resource)); ast_channel_forward_endpoint(chan, endpoint); @@ -242,19 +258,21 @@ static void endpoint_default(void *data, } } -struct ast_endpoint *ast_endpoint_create(const char *tech, const char *resource) +static struct ast_endpoint *endpoint_internal_create(const char *tech, const char *resource) { RAII_VAR(struct ast_endpoint *, endpoint, NULL, ao2_cleanup); + RAII_VAR(struct ast_endpoint *, tech_endpoint, NULL, ao2_cleanup); int r = 0; - if (ast_strlen_zero(tech)) { - ast_log(LOG_ERROR, "Endpoint tech cannot be empty\n"); - return NULL; - } - - if (ast_strlen_zero(resource)) { - ast_log(LOG_ERROR, "Endpoint resource cannot be empty\n"); - return NULL; + /* Get/create the technology endpoint */ + if (!ast_strlen_zero(resource)) { + tech_endpoint = ao2_find(tech_endpoints, tech, OBJ_KEY); + if (!tech_endpoint) { + tech_endpoint = endpoint_internal_create(tech, NULL); + if (!tech_endpoint) { + return NULL; + } + } } endpoint = ao2_alloc(sizeof(*endpoint), endpoint_dtor); @@ -268,10 +286,12 @@ struct ast_endpoint *ast_endpoint_create(const char *tech, const char *resource) if (ast_string_field_init(endpoint, 80) != 0) { return NULL; } - ast_string_field_set(endpoint, tech, tech); - ast_string_field_set(endpoint, resource, resource); - ast_string_field_build(endpoint, id, "%s/%s", tech, resource); + ast_string_field_set(endpoint, resource, S_OR(resource, "")); + ast_string_field_build(endpoint, id, "%s%s%s", + tech, + !ast_strlen_zero(resource) ? "/" : "", + S_OR(resource, "")); /* All access to channel_ids should be covered by the endpoint's * lock; no extra lock needed. */ @@ -287,24 +307,47 @@ struct ast_endpoint *ast_endpoint_create(const char *tech, const char *resource) return NULL; } - endpoint->router = stasis_message_router_create(ast_endpoint_topic(endpoint)); - if (!endpoint->router) { - return NULL; - } - r |= stasis_message_router_add(endpoint->router, - stasis_cache_clear_type(), endpoint_cache_clear, - endpoint); - r |= stasis_message_router_set_default(endpoint->router, - endpoint_default, endpoint); - - endpoint_publish_snapshot(endpoint); + if (!ast_strlen_zero(resource)) { + endpoint->router = stasis_message_router_create(ast_endpoint_topic(endpoint)); + if (!endpoint->router) { + return NULL; + } + r |= stasis_message_router_add(endpoint->router, + stasis_cache_clear_type(), endpoint_cache_clear, + endpoint); + r |= stasis_message_router_set_default(endpoint->router, + endpoint_default, endpoint); + if (r) { + return NULL; + } - ao2_link(endpoints, endpoint); + endpoint->tech_forward = stasis_forward_all(stasis_cp_single_topic(endpoint->topics), + stasis_cp_single_topic(tech_endpoint->topics)); + endpoint_publish_snapshot(endpoint); + ao2_link(endpoints, endpoint); + } else { + ao2_link(tech_endpoints, endpoint); + } ao2_ref(endpoint, +1); return endpoint; } +struct ast_endpoint *ast_endpoint_create(const char *tech, const char *resource) +{ + if (ast_strlen_zero(tech)) { + ast_log(LOG_ERROR, "Endpoint tech cannot be empty\n"); + return NULL; + } + + if (ast_strlen_zero(resource)) { + ast_log(LOG_ERROR, "Endpoint resource cannot be empty\n"); + return NULL; + } + + return endpoint_internal_create(tech, resource); +} + static struct stasis_message *create_endpoint_snapshot_message(struct ast_endpoint *endpoint) { RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup); @@ -368,6 +411,8 @@ void ast_endpoint_set_state(struct ast_endpoint *endpoint, enum ast_endpoint_state state) { ast_assert(endpoint != NULL); + ast_assert(!ast_strlen_zero(endpoint->resource)); + ao2_lock(endpoint); endpoint->state = state; ao2_unlock(endpoint); @@ -378,6 +423,8 @@ void ast_endpoint_set_max_channels(struct ast_endpoint *endpoint, int max_channels) { ast_assert(endpoint != NULL); + ast_assert(!ast_strlen_zero(endpoint->resource)); + ao2_lock(endpoint); endpoint->max_channels = max_channels; ao2_unlock(endpoint); @@ -407,6 +454,9 @@ struct ast_endpoint_snapshot *ast_endpoint_snapshot_create( void *obj; SCOPED_AO2LOCK(lock, endpoint); + ast_assert(endpoint != NULL); + ast_assert(!ast_strlen_zero(endpoint->resource)); + channel_count = ao2_container_count(endpoint->channel_ids); snapshot = ao2_alloc( @@ -440,6 +490,9 @@ static void endpoint_cleanup(void) { ao2_cleanup(endpoints); endpoints = NULL; + + ao2_cleanup(tech_endpoints); + tech_endpoints = NULL; } int ast_endpoint_init(void) @@ -448,10 +501,15 @@ int ast_endpoint_init(void) endpoints = ao2_container_alloc(ENDPOINT_BUCKETS, endpoint_hash, endpoint_cmp); - if (!endpoints) { return -1; } + tech_endpoints = ao2_container_alloc(TECH_ENDPOINT_BUCKETS, endpoint_hash, + endpoint_cmp); + if (!tech_endpoints) { + return -1; + } + return 0; } diff --git a/res/ari/resource_applications.h b/res/ari/resource_applications.h index 888f513de990a2b80cbf57ba0805135e9bbb83ed..be62e9d5fd275511e5fbfab8756ffdf11e5aabda 100644 --- a/res/ari/resource_applications.h +++ b/res/ari/resource_applications.h @@ -67,7 +67,7 @@ void ast_ari_applications_get(struct ast_variable *headers, struct ast_ari_appli struct ast_ari_applications_subscribe_args { /*! Application's name */ const char *application_name; - /*! Array of URI for event source (channel:{channelId}, bridge:{bridgeId}, endpoint:{tech}/{resource}, deviceState:{deviceName} */ + /*! Array of URI for event source (channel:{channelId}, bridge:{bridgeId}, endpoint:{tech}[/{resource}], deviceState:{deviceName} */ const char **event_source; /*! Length of event_source array. */ size_t event_source_count; @@ -99,7 +99,7 @@ void ast_ari_applications_subscribe(struct ast_variable *headers, struct ast_ari struct ast_ari_applications_unsubscribe_args { /*! Application's name */ const char *application_name; - /*! Array of URI for event source (channel:{channelId}, bridge:{bridgeId}, endpoint:{tech}/{resource}, deviceState:{deviceName} */ + /*! Array of URI for event source (channel:{channelId}, bridge:{bridgeId}, endpoint:{tech}[/{resource}], deviceState:{deviceName} */ const char **event_source; /*! Length of event_source array. */ size_t event_source_count; diff --git a/res/ari/resource_endpoints.c b/res/ari/resource_endpoints.c index 16b7ebd8d23e9c8bce0b80cc7e472b011356649f..ff2b150ddc3a2a97eccacb86e87ff57a3c44cab5 100644 --- a/res/ari/resource_endpoints.c +++ b/res/ari/resource_endpoints.c @@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/stasis_app.h" #include "asterisk/stasis_endpoints.h" #include "asterisk/channel.h" +#include "asterisk/message.h" void ast_ari_endpoints_list(struct ast_variable *headers, struct ast_ari_endpoints_list_args *args, @@ -82,6 +83,7 @@ void ast_ari_endpoints_list(struct ast_variable *headers, ast_ari_response_ok(response, ast_json_ref(json)); } + void ast_ari_endpoints_list_by_tech(struct ast_variable *headers, struct ast_ari_endpoints_list_by_tech_args *args, struct ast_ari_response *response) @@ -89,14 +91,17 @@ void ast_ari_endpoints_list_by_tech(struct ast_variable *headers, RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup); RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup); RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); + struct ast_endpoint *tech_endpoint; struct ao2_iterator i; void *obj; - if (!ast_get_channel_tech(args->tech)) { + tech_endpoint = ast_endpoint_find_by_id(args->tech); + if (!tech_endpoint) { ast_ari_response_error(response, 404, "Not Found", "No Endpoints found - invalid tech %s", args->tech); return; } + ao2_ref(tech_endpoint, -1); cache = ast_endpoint_cache(); if (!cache) { @@ -146,6 +151,7 @@ void ast_ari_endpoints_list_by_tech(struct ast_variable *headers, ao2_iterator_destroy(&i); ast_ari_response_ok(response, ast_json_ref(json)); } + void ast_ari_endpoints_get(struct ast_variable *headers, struct ast_ari_endpoints_get_args *args, struct ast_ari_response *response) diff --git a/res/res_xmpp.c b/res/res_xmpp.c index 0cfc37b4ca4a6e5ec239133c4015c7c5d260594d..758a5f09a448f3d2a4c4edf092409acb299ad10c 100644 --- a/res/res_xmpp.c +++ b/res/res_xmpp.c @@ -559,6 +559,10 @@ static void xmpp_client_destructor(void *obj) ast_xmpp_client_disconnect(client); + ast_endpoint_shutdown(client->endpoint); + ao2_cleanup(client->endpoint); + client->endpoint = NULL; + if (client->filter) { iks_filter_delete(client->filter); } @@ -593,6 +597,20 @@ static int xmpp_buddy_cmp(void *obj, void *arg, int flags) return !strcmp(buddy1->id, flags & OBJ_KEY ? id : buddy2->id) ? CMP_MATCH | CMP_STOP : 0; } +/*! \brief Internal function which changes the XMPP client state */ +static void xmpp_client_change_state(struct ast_xmpp_client *client, int state) +{ + if (state == client->state) { + return; + } + client->state = state; + if (client->state == XMPP_STATE_DISCONNECTED) { + ast_endpoint_set_state(client->endpoint, AST_ENDPOINT_OFFLINE); + } else if (client->state == XMPP_STATE_CONNECTED) { + ast_endpoint_set_state(client->endpoint, AST_ENDPOINT_ONLINE); + } +} + /*! \brief Allocator function for ast_xmpp_client */ static struct ast_xmpp_client *xmpp_client_alloc(const char *name) { @@ -605,6 +623,12 @@ static struct ast_xmpp_client *xmpp_client_alloc(const char *name) AST_LIST_HEAD_INIT(&client->messages); client->thread = AST_PTHREADT_NULL; + client->endpoint = ast_endpoint_create("XMPP", name); + if (!client->endpoint) { + ao2_ref(client, -1); + return NULL; + } + if (!(client->buddies = ao2_container_alloc(BUDDY_BUCKETS, xmpp_buddy_hash, xmpp_buddy_cmp))) { ast_log(LOG_ERROR, "Could not initialize buddy container for '%s'\n", name); ao2_ref(client, -1); @@ -626,7 +650,7 @@ static struct ast_xmpp_client *xmpp_client_alloc(const char *name) ast_string_field_set(client, name, name); client->timeout = 50; - client->state = XMPP_STATE_DISCONNECTED; + xmpp_client_change_state(client, XMPP_STATE_DISCONNECTED); ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); return client; @@ -2213,12 +2237,6 @@ static const struct ast_msg_tech msg_tech = { .msg_send = xmpp_send_cb, }; -/*! \brief Internal function which changes the XMPP client state */ -static void xmpp_client_change_state(struct ast_xmpp_client *client, int state) -{ - client->state = state; -} - /*! \brief Internal function which creates a buddy on a client */ static struct ast_xmpp_buddy *xmpp_client_create_buddy(struct ao2_container *container, const char *id) { @@ -3530,7 +3548,7 @@ static int xmpp_action_hook(void *data, int type, iks *node) int ast_xmpp_client_disconnect(struct ast_xmpp_client *client) { if ((client->thread != AST_PTHREADT_NULL) && !pthread_equal(pthread_self(), client->thread)) { - client->state = XMPP_STATE_DISCONNECTING; + xmpp_client_change_state(client, XMPP_STATE_DISCONNECTING); pthread_join(client->thread, NULL); client->thread = AST_PTHREADT_NULL; } @@ -3559,7 +3577,7 @@ int ast_xmpp_client_disconnect(struct ast_xmpp_client *client) iks_disconnect(client->parser); } - client->state = XMPP_STATE_DISCONNECTED; + xmpp_client_change_state(client, XMPP_STATE_DISCONNECTED); return 0; } @@ -3774,7 +3792,7 @@ static void *xmpp_client_thread(void *data) ast_log(LOG_WARNING, "JABBER: Not Supported\n"); } else if (res == IKS_NET_DROPPED) { ast_log(LOG_WARNING, "JABBER: Dropped?\n"); - } else { + } else if (res == IKS_NET_UNKNOWN) { ast_debug(5, "JABBER: Unknown\n"); } diff --git a/rest-api/api-docs/applications.json b/rest-api/api-docs/applications.json index 132dd641a6688784fb4f32b3e75bcfa8d8a91b38..cf0731c7cbab84cabf3ea12f9cceb14e38e00b7f 100644 --- a/rest-api/api-docs/applications.json +++ b/rest-api/api-docs/applications.json @@ -68,7 +68,7 @@ }, { "name": "eventSource", - "description": "URI for event source (channel:{channelId}, bridge:{bridgeId}, endpoint:{tech}/{resource}, deviceState:{deviceName}", + "description": "URI for event source (channel:{channelId}, bridge:{bridgeId}, endpoint:{tech}[/{resource}], deviceState:{deviceName}", "paramType": "query", "required": true, "allowMultiple": true, @@ -107,7 +107,7 @@ }, { "name": "eventSource", - "description": "URI for event source (channel:{channelId}, bridge:{bridgeId}, endpoint:{tech}/{resource}, deviceState:{deviceName}", + "description": "URI for event source (channel:{channelId}, bridge:{bridgeId}, endpoint:{tech}[/{resource}], deviceState:{deviceName}", "paramType": "query", "required": true, "allowMultiple": true,