2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2013, Digium, Inc.
6 * Mark Michelson <mmichelson@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
19 * \brief Opaque structure representing an RFC 3265 SIP subscription
23 <depend>pjproject</depend>
24 <depend>res_pjsip</depend>
25 <support_level>core</support_level>
31 #include <pjsip_simple.h>
34 #include "asterisk/res_pjsip_pubsub.h"
35 #include "asterisk/module.h"
36 #include "asterisk/linkedlists.h"
37 #include "asterisk/astobj2.h"
38 #include "asterisk/datastore.h"
39 #include "asterisk/uuid.h"
40 #include "asterisk/taskprocessor.h"
41 #include "asterisk/sched.h"
42 #include "asterisk/res_pjsip.h"
43 #include "asterisk/callerid.h"
44 #include "asterisk/manager.h"
45 #include "asterisk/test.h"
46 #include "res_pjsip/include/res_pjsip_private.h"
47 #include "asterisk/res_pjsip_presence_xml.h"
50 <manager name="PJSIPShowSubscriptionsInbound" language="en_US">
57 Provides a listing of all inbound subscriptions. An event <literal>InboundSubscriptionDetail</literal>
58 is issued for each subscription object. Once all detail events are completed an
59 <literal>InboundSubscriptionDetailComplete</literal> event is issued.
63 <manager name="PJSIPShowSubscriptionsOutbound" language="en_US">
70 Provides a listing of all outbound subscriptions. An event <literal>OutboundSubscriptionDetail</literal>
71 is issued for each subscription object. Once all detail events are completed an
72 <literal>OutboundSubscriptionDetailComplete</literal> event is issued.
76 <manager name="PJSIPShowResourceLists" language="en_US">
78 Displays settings for configured resource lists.
83 Provides a listing of all resource lists. An event <literal>ResourceListDetail</literal>
84 is issued for each resource list object. Once all detail events are completed a
85 <literal>ResourceListDetailComplete</literal> event is issued.
90 <configInfo name="res_pjsip_pubsub" language="en_US">
91 <synopsis>Module that implements publish and subscribe support.</synopsis>
92 <configFile name="pjsip.conf">
93 <configObject name="subscription_persistence">
94 <synopsis>Persists SIP subscriptions so they survive restarts.</synopsis>
95 <configOption name="packet">
96 <synopsis>Entire SIP SUBSCRIBE packet that created the subscription</synopsis>
98 <configOption name="src_name">
99 <synopsis>The source address of the subscription</synopsis>
101 <configOption name="src_port">
102 <synopsis>The source port of the subscription</synopsis>
104 <configOption name="transport_key">
105 <synopsis>The type of transport the subscription was received on</synopsis>
107 <configOption name="local_name">
108 <synopsis>The local address the subscription was received on</synopsis>
110 <configOption name="local_port">
111 <synopsis>The local port the subscription was received on</synopsis>
113 <configOption name="cseq">
114 <synopsis>The sequence number of the next NOTIFY to be sent</synopsis>
116 <configOption name="tag">
117 <synopsis>The local tag of the dialog for the subscription</synopsis>
119 <configOption name="endpoint">
120 <synopsis>The name of the endpoint that subscribed</synopsis>
122 <configOption name="expires">
123 <synopsis>The time at which the subscription expires</synopsis>
126 <configObject name="resource_list">
127 <synopsis>Resource list configuration parameters.</synopsis>
129 <para>This configuration object allows for RFC 4662 resource list subscriptions
130 to be specified. This can be useful to decrease the amount of subscription traffic
131 that a server has to process.</para>
133 <para>Current limitations limit the size of SIP NOTIFY requests that Asterisk sends
134 to 64000 bytes. If your resource list notifications are larger than this maximum, you
135 will need to make adjustments.</para>
138 <configOption name="type">
139 <synopsis>Must be of type 'resource_list'</synopsis>
141 <configOption name="event">
142 <synopsis>The SIP event package that the list resource belong to.</synopsis>
144 The SIP event package describes the types of resources that Asterisk reports
148 <enum name="presence"><para>
149 Device state and presence reporting.
151 <enum name="dialog"><para>
152 This is identical to <replaceable>presence</replaceable>.
154 <enum name="message-summary"><para>
155 Message-waiting indication (MWI) reporting.
160 <configOption name="list_item">
161 <synopsis>The name of a resource to report state on</synopsis>
163 <para>In general Asterisk looks up list items in the following way:</para>
164 <para>1. Check if the list item refers to another configured resource list.</para>
165 <para>2. Pass the name of the resource off to event-package-specific handlers
166 to find the specified resource.</para>
167 <para>The second part means that the way the list item is specified depends
168 on what type of list this is. For instance, if you have the <replaceable>event</replaceable>
169 set to <literal>presence</literal>, then list items should be in the form of
170 dialplan_extension@dialplan_context. For <literal>message-summary</literal> mailbox
171 names should be listed.</para>
174 <configOption name="full_state" default="no">
175 <synopsis>Indicates if the entire list's state should be sent out.</synopsis>
177 <para>If this option is enabled, and a resource changes state, then Asterisk will construct
178 a notification that contains the state of all resources in the list. If the option is
179 disabled, Asterisk will construct a notification that only contains the states of
180 resources that have changed.</para>
182 <para>Even with this option disabled, there are certain situations where Asterisk is forced
183 to send a notification with the states of all resources in the list. When a subscriber
184 renews or terminates its subscription to the list, Asterisk MUST send a full state
189 <configOption name="notification_batch_interval" default="0">
190 <synopsis>Time Asterisk should wait, in milliseconds, before sending notifications.</synopsis>
192 <para>When a resource's state changes, it may be desired to wait a certain amount before Asterisk
193 sends a notification to subscribers. This allows for other state changes to accumulate, so that
194 Asterisk can communicate multiple state changes in a single notification instead of rapidly sending
195 many notifications.</para>
199 <configObject name="inbound-publication">
200 <synopsis>The configuration for inbound publications</synopsis>
201 <configOption name="endpoint" default="">
202 <synopsis>Optional name of an endpoint that is only allowed to publish to this resource</synopsis>
204 <configOption name="type">
205 <synopsis>Must be of type 'inbound-publication'.</synopsis>
212 static pj_bool_t pubsub_on_rx_request(pjsip_rx_data *rdata);
214 static struct pjsip_module pubsub_module = {
215 .name = { "PubSub Module", 13 },
216 .priority = PJSIP_MOD_PRIORITY_APPLICATION,
217 .on_rx_request = pubsub_on_rx_request,
220 #define MOD_DATA_PERSISTENCE "sub_persistence"
221 #define MOD_DATA_MSG "sub_msg"
223 static const pj_str_t str_event_name = { "Event", 5 };
225 /*! \brief Scheduler used for automatically expiring publications */
226 static struct ast_sched_context *sched;
228 /*! \brief Number of buckets for publications (on a per handler) */
229 #define PUBLICATIONS_BUCKETS 37
231 /*! \brief Default expiration time for PUBLISH if one is not specified */
232 #define DEFAULT_PUBLISH_EXPIRES 3600
234 /*! \brief Number of buckets for subscription datastore */
235 #define DATASTORE_BUCKETS 53
237 /*! \brief Default expiration for subscriptions */
238 #define DEFAULT_EXPIRES 3600
240 /*! \brief Defined method for PUBLISH */
241 const pjsip_method pjsip_publish_method =
248 * \brief The types of PUBLISH messages defined in RFC 3903
250 enum sip_publish_type {
255 * This actually is not defined in RFC 3903. We use this as a constant
256 * to indicate that an incoming PUBLISH does not fit into any of the
257 * other categories and is thus invalid.
265 * The first PUBLISH sent. This will contain a non-zero Expires header
266 * as well as a body that indicates the current state of the endpoint
267 * that has sent the message. The initial PUBLISH is the only type
268 * of PUBLISH to not contain a Sip-If-Match header in it.
276 * Used to keep a published state from expiring. This will contain a
277 * non-zero Expires header but no body since its purpose is not to
286 * Used to change state from its previous value. This will contain
287 * a body updating the published state. May or may not contain an
296 * Used to remove published state from an ESC. This will contain
297 * an Expires header set to 0 and likely no body.
303 * \brief A vector of strings commonly used throughout this module
305 AST_VECTOR(resources, const char *);
308 * \brief Resource list configuration item
310 struct resource_list {
311 SORCERY_OBJECT(details);
312 /*! SIP event package the list uses. */
314 /*! Strings representing resources in the list. */
315 struct resources items;
316 /*! Indicates if Asterisk sends full or partial state on notifications. */
317 unsigned int full_state;
318 /*! Time, in milliseconds Asterisk waits before sending a batched notification.*/
319 unsigned int notification_batch_interval;
323 * Used to create new entity IDs by ESCs.
325 static int esc_etag_counter;
328 * \brief Structure representing a SIP publication
330 struct ast_sip_publication {
331 /*! Publication datastores set up by handlers */
332 struct ao2_container *datastores;
333 /*! \brief Entity tag for the publication */
335 /*! \brief Handler for this publication */
336 struct ast_sip_publish_handler *handler;
337 /*! \brief The endpoint with which the subscription is communicating */
338 struct ast_sip_endpoint *endpoint;
339 /*! \brief Expiration time of the publication */
341 /*! \brief Scheduled item for expiration of publication */
343 /*! \brief The resource the publication is to */
345 /*! \brief The name of the event type configuration */
346 char *event_configuration_name;
347 /*! \brief Data containing the above */
353 * \brief Structure used for persisting an inbound subscription
355 struct subscription_persistence {
356 /*! Sorcery object details */
357 SORCERY_OBJECT(details);
358 /*! The name of the endpoint involved in the subscrption */
360 /*! SIP message that creates the subscription */
361 char packet[PJSIP_MAX_PKT_LEN];
362 /*! Source address of the message */
363 char src_name[PJ_INET6_ADDRSTRLEN];
364 /*! Source port of the message */
366 /*! Local transport key type */
367 char transport_key[32];
368 /*! Local transport address */
369 char local_name[PJ_INET6_ADDRSTRLEN];
370 /*! Local transport port */
372 /*! Next CSeq to use for message */
374 /*! Local tag of the dialog */
376 /*! When this subscription expires */
377 struct timeval expires;
381 * \brief A tree of SIP subscriptions
383 * Because of the ability to subscribe to resource lists, a SIP
384 * subscription can result in a tree of subscriptions being created.
385 * This structure represents the information relevant to the subscription
386 * as a whole, to include the underlying PJSIP structure for the
389 struct sip_subscription_tree {
390 /*! The endpoint with which the subscription is communicating */
391 struct ast_sip_endpoint *endpoint;
392 /*! Serializer on which to place operations for this subscription */
393 struct ast_taskprocessor *serializer;
394 /*! The role for this subscription */
395 enum ast_sip_subscription_role role;
396 /*! Persistence information */
397 struct subscription_persistence *persistence;
398 /*! The underlying PJSIP event subscription structure */
400 /*! The underlying PJSIP dialog */
402 /*! Interval to use for batching notifications */
403 unsigned int notification_batch_interval;
404 /*! Scheduler ID for batched notification */
406 /*! Indicator if scheduled batched notification should be sent */
407 unsigned int send_scheduled_notify;
408 /*! The root of the subscription tree */
409 struct ast_sip_subscription *root;
410 /*! Is this subscription to a list? */
412 /*! Next item in the list */
413 AST_LIST_ENTRY(sip_subscription_tree) next;
417 * \brief Structure representing a "virtual" SIP subscription.
419 * This structure serves a dual purpose. Structurally, it is
420 * the constructed tree of subscriptions based on the resources
421 * being subscribed to. API-wise, this serves as the handle that
422 * subscription handlers use in order to interact with the pubsub API.
424 struct ast_sip_subscription {
425 /*! Subscription datastores set up by handlers */
426 struct ao2_container *datastores;
427 /*! The handler for this subscription */
428 const struct ast_sip_subscription_handler *handler;
429 /*! Pointer to the base of the tree */
430 struct sip_subscription_tree *tree;
431 /*! Body generaator for NOTIFYs */
432 struct ast_sip_pubsub_body_generator *body_generator;
433 /*! Vector of child subscriptions */
434 AST_VECTOR(, struct ast_sip_subscription *) children;
435 /*! Saved NOTIFY body text for this subscription */
436 struct ast_str *body_text;
437 /*! Indicator that the body text has changed since the last notification */
439 /*! The current state of the subscription */
440 pjsip_evsub_state subscription_state;
441 /*! For lists, the current version to place in the RLMI body */
442 unsigned int version;
443 /*! For lists, indicates if full state should always be communicated. */
444 unsigned int full_state;
445 /*! URI associated with the subscription */
447 /*! Name of resource being subscribed to */
452 * \brief Structure representing a publication resource
454 struct ast_sip_publication_resource {
455 /*! \brief Sorcery object details */
456 SORCERY_OBJECT(details);
457 /*! \brief Optional name of an endpoint that is only allowed to publish to this resource */
459 /*! \brief Mapping for event types to configuration */
460 struct ast_variable *events;
463 static const char *sip_subscription_roles_map[] = {
464 [AST_SIP_SUBSCRIBER] = "Subscriber",
465 [AST_SIP_NOTIFIER] = "Notifier"
468 AST_RWLIST_HEAD_STATIC(subscriptions, sip_subscription_tree);
470 AST_RWLIST_HEAD_STATIC(body_generators, ast_sip_pubsub_body_generator);
471 AST_RWLIST_HEAD_STATIC(body_supplements, ast_sip_pubsub_body_supplement);
473 static void pubsub_on_evsub_state(pjsip_evsub *sub, pjsip_event *event);
474 static void pubsub_on_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata,
475 int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body);
476 static void pubsub_on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code,
477 pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body);
478 static void pubsub_on_client_refresh(pjsip_evsub *sub);
479 static void pubsub_on_server_timeout(pjsip_evsub *sub);
481 static pjsip_evsub_user pubsub_cb = {
482 .on_evsub_state = pubsub_on_evsub_state,
483 .on_rx_refresh = pubsub_on_rx_refresh,
484 .on_rx_notify = pubsub_on_rx_notify,
485 .on_client_refresh = pubsub_on_client_refresh,
486 .on_server_timeout = pubsub_on_server_timeout,
489 /*! \brief Destructor for publication resource */
490 static void publication_resource_destroy(void *obj)
492 struct ast_sip_publication_resource *resource = obj;
494 ast_free(resource->endpoint);
495 ast_variables_destroy(resource->events);
498 /*! \brief Allocator for publication resource */
499 static void *publication_resource_alloc(const char *name)
501 return ast_sorcery_generic_alloc(sizeof(struct ast_sip_publication_resource), publication_resource_destroy);
504 /*! \brief Destructor for subscription persistence */
505 static void subscription_persistence_destroy(void *obj)
507 struct subscription_persistence *persistence = obj;
509 ast_free(persistence->endpoint);
510 ast_free(persistence->tag);
513 /*! \brief Allocator for subscription persistence */
514 static void *subscription_persistence_alloc(const char *name)
516 return ast_sorcery_generic_alloc(sizeof(struct subscription_persistence), subscription_persistence_destroy);
519 /*! \brief Function which creates initial persistence information of a subscription in sorcery */
520 static struct subscription_persistence *subscription_persistence_create(struct sip_subscription_tree *sub_tree)
522 char tag[PJ_GUID_STRING_LENGTH + 1];
524 /* The id of this persistence object doesn't matter as we keep it on the subscription and don't need to
525 * look it up by id at all.
527 struct subscription_persistence *persistence = ast_sorcery_alloc(ast_sip_get_sorcery(),
528 "subscription_persistence", NULL);
530 pjsip_dialog *dlg = sub_tree->dlg;
536 persistence->endpoint = ast_strdup(ast_sorcery_object_get_id(sub_tree->endpoint));
537 ast_copy_pj_str(tag, &dlg->local.info->tag, sizeof(tag));
538 persistence->tag = ast_strdup(tag);
540 ast_sorcery_create(ast_sip_get_sorcery(), persistence);
544 /*! \brief Function which updates persistence information of a subscription in sorcery */
545 static void subscription_persistence_update(struct sip_subscription_tree *sub_tree,
546 pjsip_rx_data *rdata)
550 if (!sub_tree->persistence) {
555 sub_tree->persistence->cseq = dlg->local.cseq;
559 pjsip_expires_hdr *expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
561 expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
562 sub_tree->persistence->expires = ast_tvadd(ast_tvnow(), ast_samp2tv(expires, 1));
564 ast_copy_string(sub_tree->persistence->packet, rdata->pkt_info.packet,
565 sizeof(sub_tree->persistence->packet));
566 ast_copy_string(sub_tree->persistence->src_name, rdata->pkt_info.src_name,
567 sizeof(sub_tree->persistence->src_name));
568 sub_tree->persistence->src_port = rdata->pkt_info.src_port;
569 ast_copy_string(sub_tree->persistence->transport_key, rdata->tp_info.transport->type_name,
570 sizeof(sub_tree->persistence->transport_key));
571 ast_copy_pj_str(sub_tree->persistence->local_name, &rdata->tp_info.transport->local_name.host,
572 sizeof(sub_tree->persistence->local_name));
573 sub_tree->persistence->local_port = rdata->tp_info.transport->local_name.port;
576 ast_sorcery_update(ast_sip_get_sorcery(), sub_tree->persistence);
579 /*! \brief Function which removes persistence of a subscription from sorcery */
580 static void subscription_persistence_remove(struct sip_subscription_tree *sub_tree)
582 if (!sub_tree->persistence) {
586 ast_sorcery_delete(ast_sip_get_sorcery(), sub_tree->persistence);
587 ao2_ref(sub_tree->persistence, -1);
591 static struct ast_sip_subscription_handler *find_sub_handler_for_event_name(const char *event_name);
592 static struct ast_sip_pubsub_body_generator *find_body_generator(char accept[AST_SIP_MAX_ACCEPT][64],
593 size_t num_accept, const char *body_type);
595 /*! \brief Retrieve a handler using the Event header of an rdata message */
596 static struct ast_sip_subscription_handler *subscription_get_handler_from_rdata(pjsip_rx_data *rdata)
598 pjsip_event_hdr *event_header;
600 struct ast_sip_subscription_handler *handler;
602 event_header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_event_name, rdata->msg_info.msg->hdr.next);
604 ast_log(LOG_WARNING, "Incoming SUBSCRIBE request with no Event header\n");
607 ast_copy_pj_str(event, &event_header->event_type, sizeof(event));
609 handler = find_sub_handler_for_event_name(event);
611 ast_log(LOG_WARNING, "No registered subscribe handler for event %s\n", event);
618 * \brief Accept headers that are exceptions to the rule
620 * Typically, when a SUBSCRIBE arrives, we attempt to find a
621 * body generator that matches one of the Accept headers in
622 * the request. When subscribing to a single resource, this works
623 * great. However, when subscribing to a list, things work
624 * differently. Most Accept header values are fine, but there
625 * are a couple that are endemic to resource lists that need
626 * to be ignored when searching for a body generator to use
627 * for the individual resources of the subscription.
629 const char *accept_exceptions[] = {
631 "application/rlmi+xml",
635 * \brief Is the Accept header from the SUBSCRIBE in the list of exceptions?
637 * \retval 1 This Accept header value is an exception to the rule.
638 * \retval 0 This Accept header is not an exception to the rule.
640 static int exceptional_accept(const pj_str_t *accept)
644 for (i = 0; i < ARRAY_LEN(accept_exceptions); ++i) {
645 if (!pj_strcmp2(accept, accept_exceptions[i])) {
653 /*! \brief Retrieve a body generator using the Accept header of an rdata message */
654 static struct ast_sip_pubsub_body_generator *subscription_get_generator_from_rdata(pjsip_rx_data *rdata,
655 const struct ast_sip_subscription_handler *handler)
657 pjsip_accept_hdr *accept_header = (pjsip_accept_hdr *) &rdata->msg_info.msg->hdr;
658 char accept[AST_SIP_MAX_ACCEPT][64];
659 size_t num_accept_headers = 0;
661 while ((accept_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, accept_header->next))) {
664 for (i = 0; i < accept_header->count; ++i) {
665 if (!exceptional_accept(&accept_header->values[i])) {
666 ast_copy_pj_str(accept[num_accept_headers], &accept_header->values[i], sizeof(accept[num_accept_headers]));
667 ++num_accept_headers;
672 if (num_accept_headers == 0) {
673 /* If a SUBSCRIBE contains no Accept headers, then we must assume that
674 * the default accept type for the event package is to be used.
676 ast_copy_string(accept[0], handler->notifier->default_accept, sizeof(accept[0]));
677 num_accept_headers = 1;
680 return find_body_generator(accept, num_accept_headers, handler->body_type);
683 /*! \brief Check if the rdata has a Supported header containing 'eventlist'
685 * \retval 1 rdata has an eventlist containing supported header
686 * \retval 0 rdata doesn't have an eventlist containing supported header
688 static int ast_sip_pubsub_has_eventlist_support(pjsip_rx_data *rdata)
690 pjsip_supported_hdr *supported_header = (pjsip_supported_hdr *) &rdata->msg_info.msg->hdr;
692 while ((supported_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_SUPPORTED, supported_header->next))) {
695 for (i = 0; i < supported_header->count; i++) {
696 if (!pj_stricmp2(&supported_header->values[i], "eventlist")) {
705 struct resource_tree;
708 * \brief A node for a resource tree.
711 AST_VECTOR(, struct tree_node *) children;
712 unsigned int full_state;
717 * \brief Helper function for retrieving a resource list for a given event.
719 * This will retrieve a resource list that corresponds to the resource and event provided.
721 * \param resource The name of the resource list to retrieve
722 * \param event The expected event name on the resource list
724 static struct resource_list *retrieve_resource_list(const char *resource, const char *event)
726 struct resource_list *list;
728 list = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "resource_list", resource);
733 if (strcmp(list->event, event)) {
734 ast_log(LOG_WARNING, "Found resource list %s, but its event type (%s) does not match SUBSCRIBE's (%s)\n",
735 resource, list->event, event);
744 * \brief Allocate a tree node
746 * In addition to allocating and initializing the tree node, the node is also added
747 * to the vector of visited resources. See \ref build_resource_tree for more information
748 * on the visited resources.
750 * \param resource The name of the resource for this tree node.
751 * \param visited The vector of resources that have been visited.
752 * \param if allocating a list, indicate whether full state is requested in notifications.
753 * \retval NULL Allocation failure.
754 * \retval non-NULL The newly-allocated tree_node
756 static struct tree_node *tree_node_alloc(const char *resource, struct resources *visited, unsigned int full_state)
758 struct tree_node *node;
760 node = ast_calloc(1, sizeof(*node) + strlen(resource) + 1);
765 strcpy(node->resource, resource);
766 if (AST_VECTOR_INIT(&node->children, 4)) {
770 node->full_state = full_state;
773 AST_VECTOR_APPEND(visited, resource);
779 * \brief Destructor for a tree node
781 * This function calls recursively in order to destroy
782 * all nodes lower in the tree from the given node in
783 * addition to the node itself.
785 * \param node The node to destroy.
787 static void tree_node_destroy(struct tree_node *node)
794 for (i = 0; i < AST_VECTOR_SIZE(&node->children); ++i) {
795 tree_node_destroy(AST_VECTOR_GET(&node->children, i));
797 AST_VECTOR_FREE(&node->children);
802 * \brief Determine if this resource has been visited already
804 * See \ref build_resource_tree for more information
806 * \param resource The resource currently being visited
807 * \param visited The resources that have previously been visited
809 static int have_visited(const char *resource, struct resources *visited)
813 for (i = 0; i < AST_VECTOR_SIZE(visited); ++i) {
814 if (!strcmp(resource, AST_VECTOR_GET(visited, i))) {
823 * \brief Build child nodes for a given parent.
825 * This iterates through the items on a resource list and creates tree nodes for each one. The
826 * tree nodes created are children of the supplied parent node. If an item in the resource
827 * list is itself a list, then this function is called recursively to provide children for
830 * If an item in a resource list is not a list, then the supplied subscription handler is
831 * called into as if a new SUBSCRIBE for the list item were presented. The handler's response
832 * is used to determine if the node can be added to the tree or not.
834 * If a parent node ends up having no child nodes added under it, then the parent node is
835 * pruned from the tree.
837 * \param endpoint The endpoint that sent the inbound SUBSCRIBE.
838 * \param handler The subscription handler for leaf nodes in the tree.
839 * \param list The configured resource list from which the child node is being built.
840 * \param parent The parent node for these children.
841 * \param visited The resources that have already been visited.
843 static void build_node_children(struct ast_sip_endpoint *endpoint, const struct ast_sip_subscription_handler *handler,
844 struct resource_list *list, struct tree_node *parent, struct resources *visited)
848 for (i = 0; i < AST_VECTOR_SIZE(&list->items); ++i) {
849 struct tree_node *current;
850 struct resource_list *child_list;
851 const char *resource = AST_VECTOR_GET(&list->items, i);
853 if (have_visited(resource, visited)) {
854 ast_debug(1, "Already visited resource %s. Avoiding duplicate resource or potential loop.\n", resource);
858 child_list = retrieve_resource_list(resource, list->event);
860 int resp = handler->notifier->new_subscribe(endpoint, resource);
861 if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
862 current = tree_node_alloc(resource, visited, 0);
864 ast_debug(1, "Subscription to leaf resource %s was successful, but encountered"
865 "allocation error afterwards\n", resource);
868 ast_debug(1, "Subscription to leaf resource %s resulted in success. Adding to parent %s\n",
869 resource, parent->resource);
870 AST_VECTOR_APPEND(&parent->children, current);
872 ast_debug(1, "Subscription to leaf resource %s resulted in error response %d\n",
876 ast_debug(1, "Resource %s (child of %s) is a list\n", resource, parent->resource);
877 current = tree_node_alloc(resource, visited, child_list->full_state);
879 ast_debug(1, "Cannot build children of resource %s due to allocation failure\n", resource);
882 build_node_children(endpoint, handler, child_list, current, visited);
883 if (AST_VECTOR_SIZE(¤t->children) > 0) {
884 ast_debug(1, "List %s had no successful children.\n", resource);
885 AST_VECTOR_APPEND(&parent->children, current);
887 ast_debug(1, "List %s had successful children. Adding to parent %s\n",
888 resource, parent->resource);
889 tree_node_destroy(current);
891 ao2_cleanup(child_list);
897 * \brief A resource tree
899 * When an inbound SUBSCRIBE arrives, the resource being subscribed to may
900 * be a resource list. If this is the case, the resource list may contain resources
901 * that are themselves lists. The structure needed to hold the resources is
904 * Upon receipt of the SUBSCRIBE, the tree is built by determining if subscriptions
905 * to the individual resources in the tree would be successful or not. Any successful
906 * subscriptions result in a node in the tree being created. Any unsuccessful subscriptions
907 * result in no node being created.
909 * This tree can be seen as a bare-bones analog of the tree of ast_sip_subscriptions that
910 * will end up being created to actually carry out the duties of a SIP SUBSCRIBE dialog.
912 struct resource_tree {
913 struct tree_node *root;
914 unsigned int notification_batch_interval;
918 * \brief Destroy a resource tree.
920 * This function makes no assumptions about how the tree itself was
921 * allocated and does not attempt to free the tree itself. Callers
922 * of this function are responsible for freeing the tree.
924 * \param tree The tree to destroy.
926 static void resource_tree_destroy(struct resource_tree *tree)
929 tree_node_destroy(tree->root);
934 * \brief Build a resource tree
936 * This function builds a resource tree based on the requested resource in a SUBSCRIBE request.
938 * This function also creates a container that has all resources that have been visited during
939 * creation of the tree, whether those resources resulted in a tree node being created or not.
940 * Keeping this container of visited resources allows for misconfigurations such as loops in
941 * the tree or duplicated resources to be detected.
943 * \param endpoint The endpoint that sent the SUBSCRIBE request.
944 * \param handler The subscription handler for leaf nodes in the tree.
945 * \param resource The resource requested in the SUBSCRIBE request.
946 * \param tree The tree that is to be built.
947 * \param has_eventlist_support
949 * \retval 200-299 Successfully subscribed to at least one resource.
950 * \retval 300-699 Failure to subscribe to requested resource.
952 static int build_resource_tree(struct ast_sip_endpoint *endpoint, const struct ast_sip_subscription_handler *handler,
953 const char *resource, struct resource_tree *tree, int has_eventlist_support)
955 RAII_VAR(struct resource_list *, list, NULL, ao2_cleanup);
956 struct resources visited;
958 if (!has_eventlist_support || !(list = retrieve_resource_list(resource, handler->event_name))) {
959 ast_debug(1, "Subscription to resource %s is not to a list\n", resource);
960 tree->root = tree_node_alloc(resource, NULL, 0);
964 return handler->notifier->new_subscribe(endpoint, resource);
967 ast_debug(1, "Subscription to resource %s is a list\n", resource);
968 if (AST_VECTOR_INIT(&visited, AST_VECTOR_SIZE(&list->items))) {
972 tree->root = tree_node_alloc(resource, &visited, list->full_state);
977 tree->notification_batch_interval = list->notification_batch_interval;
979 build_node_children(endpoint, handler, list, tree->root, &visited);
980 AST_VECTOR_FREE(&visited);
982 if (AST_VECTOR_SIZE(&tree->root->children) > 0) {
989 static int datastore_hash(const void *obj, int flags)
991 const struct ast_datastore *datastore = obj;
992 const char *uid = flags & OBJ_KEY ? obj : datastore->uid;
994 ast_assert(uid != NULL);
996 return ast_str_hash(uid);
999 static int datastore_cmp(void *obj, void *arg, int flags)
1001 const struct ast_datastore *datastore1 = obj;
1002 const struct ast_datastore *datastore2 = arg;
1003 const char *uid2 = flags & OBJ_KEY ? arg : datastore2->uid;
1005 ast_assert(datastore1->uid != NULL);
1006 ast_assert(uid2 != NULL);
1008 return strcmp(datastore1->uid, uid2) ? 0 : CMP_MATCH | CMP_STOP;
1011 static int subscription_remove_serializer(void *obj)
1013 struct sip_subscription_tree *sub_tree = obj;
1015 /* This is why we keep the dialog on the subscription. When the subscription
1016 * is destroyed, there is no guarantee that the underlying dialog is ready
1017 * to be destroyed. Furthermore, there's no guarantee in the opposite direction
1018 * either. The dialog could be destroyed before our subscription is. We fix
1019 * this problem by keeping a reference to the dialog until it is time to
1020 * destroy the subscription. We need to have the dialog available when the
1021 * subscription is destroyed so that we can guarantee that our attempt to
1022 * remove the serializer will be successful.
1024 ast_sip_dialog_set_serializer(sub_tree->dlg, NULL);
1025 ast_sip_dialog_set_endpoint(sub_tree->dlg, NULL);
1026 pjsip_dlg_dec_session(sub_tree->dlg, &pubsub_module);
1031 static void add_subscription(struct sip_subscription_tree *obj)
1033 SCOPED_LOCK(lock, &subscriptions, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
1034 AST_RWLIST_INSERT_TAIL(&subscriptions, obj, next);
1037 static void remove_subscription(struct sip_subscription_tree *obj)
1039 struct sip_subscription_tree *i;
1040 SCOPED_LOCK(lock, &subscriptions, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
1041 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&subscriptions, i, next) {
1043 AST_RWLIST_REMOVE_CURRENT(next);
1045 ast_debug(1, "Removing subscription to resource %s from list of subscriptions\n",
1046 ast_sip_subscription_get_resource_name(i->root));
1051 AST_RWLIST_TRAVERSE_SAFE_END;
1054 static void subscription_destructor(void *obj)
1056 struct ast_sip_subscription *sub = obj;
1058 ast_debug(3, "Destroying SIP subscription to resource %s\n", sub->resource);
1059 ast_free(sub->body_text);
1061 ao2_cleanup(sub->datastores);
1064 static struct ast_sip_subscription *allocate_subscription(const struct ast_sip_subscription_handler *handler,
1065 const char *resource, struct sip_subscription_tree *tree)
1067 struct ast_sip_subscription *sub;
1068 pjsip_sip_uri *contact_uri;
1070 sub = ao2_alloc(sizeof(*sub) + strlen(resource) + 1, subscription_destructor);
1074 strcpy(sub->resource, resource); /* Safe */
1076 sub->datastores = ao2_container_alloc(DATASTORE_BUCKETS, datastore_hash, datastore_cmp);
1077 if (!sub->datastores) {
1082 sub->body_text = ast_str_create(128);
1083 if (!sub->body_text) {
1088 sub->uri = pjsip_sip_uri_create(tree->dlg->pool, PJ_FALSE);
1089 contact_uri = pjsip_uri_get_uri(tree->dlg->local.contact->uri);
1090 pjsip_sip_uri_assign(tree->dlg->pool, sub->uri, contact_uri);
1091 pj_strdup2(tree->dlg->pool, &sub->uri->user, resource);
1093 sub->handler = handler;
1094 sub->subscription_state = PJSIP_EVSUB_STATE_ACTIVE;
1101 * \brief Create a tree of virtual subscriptions based on a resource tree node.
1103 * \param handler The handler to supply to leaf subscriptions.
1104 * \param resource The requested resource for this subscription.
1105 * \param generator Body generator to use for leaf subscriptions.
1106 * \param tree The root of the subscription tree.
1107 * \param current The tree node that corresponds to the subscription being created.
1109 static struct ast_sip_subscription *create_virtual_subscriptions(const struct ast_sip_subscription_handler *handler,
1110 const char *resource, struct ast_sip_pubsub_body_generator *generator,
1111 struct sip_subscription_tree *tree, struct tree_node *current)
1114 struct ast_sip_subscription *sub;
1116 sub = allocate_subscription(handler, resource, tree);
1121 sub->full_state = current->full_state;
1122 sub->body_generator = generator;
1124 for (i = 0; i < AST_VECTOR_SIZE(¤t->children); ++i) {
1125 struct ast_sip_subscription *child;
1126 struct tree_node *child_node = AST_VECTOR_GET(¤t->children, i);
1128 child = create_virtual_subscriptions(handler, child_node->resource, generator,
1132 ast_debug(1, "Child subscription to resource %s could not be created\n",
1133 child_node->resource);
1137 if (AST_VECTOR_APPEND(&sub->children, child)) {
1138 ast_debug(1, "Child subscription to resource %s could not be appended\n",
1139 child_node->resource);
1146 static void shutdown_subscriptions(struct ast_sip_subscription *sub)
1154 if (AST_VECTOR_SIZE(&sub->children) > 0) {
1155 for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
1156 shutdown_subscriptions(AST_VECTOR_GET(&sub->children, i));
1157 ao2_cleanup(AST_VECTOR_GET(&sub->children, i));
1162 if (sub->handler->subscription_shutdown) {
1163 sub->handler->subscription_shutdown(sub);
1167 static void subscription_tree_destructor(void *obj)
1169 struct sip_subscription_tree *sub_tree = obj;
1171 remove_subscription(sub_tree);
1173 subscription_persistence_remove(sub_tree);
1174 ao2_cleanup(sub_tree->endpoint);
1176 if (sub_tree->dlg) {
1177 ast_sip_push_task_synchronous(NULL, subscription_remove_serializer, sub_tree);
1180 shutdown_subscriptions(sub_tree->root);
1181 ao2_cleanup(sub_tree->root);
1183 ast_taskprocessor_unreference(sub_tree->serializer);
1184 ast_module_unref(ast_module_info->self);
1187 static void subscription_setup_dialog(struct sip_subscription_tree *sub_tree, pjsip_dialog *dlg)
1189 /* We keep a reference to the dialog until our subscription is destroyed. See
1190 * the subscription_destructor for more details
1192 pjsip_dlg_inc_session(dlg, &pubsub_module);
1193 sub_tree->dlg = dlg;
1194 ast_sip_dialog_set_serializer(dlg, sub_tree->serializer);
1195 ast_sip_dialog_set_endpoint(dlg, sub_tree->endpoint);
1196 pjsip_evsub_set_mod_data(sub_tree->evsub, pubsub_module.id, sub_tree);
1199 static struct sip_subscription_tree *allocate_subscription_tree(struct ast_sip_endpoint *endpoint)
1201 struct sip_subscription_tree *sub_tree;
1203 sub_tree = ao2_alloc(sizeof *sub_tree, subscription_tree_destructor);
1208 ast_module_ref(ast_module_info->self);
1210 sub_tree->serializer = ast_sip_create_serializer();
1211 if (!sub_tree->serializer) {
1212 ao2_ref(sub_tree, -1);
1216 sub_tree->endpoint = ao2_bump(endpoint);
1217 sub_tree->notify_sched_id = -1;
1219 add_subscription(sub_tree);
1224 * \brief Create a subscription tree based on a resource tree.
1226 * Using the previously-determined valid resources in the provided resource tree,
1227 * a corresponding tree of ast_sip_subscriptions are created. The root of the
1228 * subscription tree is a real subscription, and the rest in the tree are
1229 * virtual subscriptions.
1231 * \param handler The handler to use for leaf subscriptions
1232 * \param endpoint The endpoint that sent the SUBSCRIBE request
1233 * \param rdata The SUBSCRIBE content
1234 * \param resource The requested resource in the SUBSCRIBE request
1235 * \param generator The body generator to use in leaf subscriptions
1236 * \param tree The resource tree on which the subscription tree is based
1237 * \param dlg_status[out] The result of attempting to create a dialog.
1239 * \retval NULL Could not create the subscription tree
1240 * \retval non-NULL The root of the created subscription tree
1243 static struct sip_subscription_tree *create_subscription_tree(const struct ast_sip_subscription_handler *handler,
1244 struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *resource,
1245 struct ast_sip_pubsub_body_generator *generator, struct resource_tree *tree,
1246 pj_status_t *dlg_status)
1248 struct sip_subscription_tree *sub_tree;
1250 struct subscription_persistence *persistence;
1252 sub_tree = allocate_subscription_tree(endpoint);
1254 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
1257 sub_tree->role = AST_SIP_NOTIFIER;
1259 dlg = ast_sip_create_dialog_uas(endpoint, rdata, dlg_status);
1261 if (*dlg_status != PJ_EEXISTS) {
1262 ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
1264 ao2_ref(sub_tree, -1);
1268 persistence = ast_sip_mod_data_get(rdata->endpt_info.mod_data,
1269 pubsub_module.id, MOD_DATA_PERSISTENCE);
1271 /* Update the created dialog with the persisted information */
1272 pjsip_ua_unregister_dlg(pjsip_ua_instance(), dlg);
1273 pj_strdup2(dlg->pool, &dlg->local.info->tag, persistence->tag);
1274 dlg->local.tag_hval = pj_hash_calc_tolower(0, NULL, &dlg->local.info->tag);
1275 pjsip_ua_register_dlg(pjsip_ua_instance(), dlg);
1276 dlg->local.cseq = persistence->cseq;
1277 dlg->remote.cseq = persistence->cseq;
1280 pjsip_evsub_create_uas(dlg, &pubsub_cb, rdata, 0, &sub_tree->evsub);
1281 subscription_setup_dialog(sub_tree, dlg);
1283 ast_sip_mod_data_set(dlg->pool, dlg->mod_data, pubsub_module.id, MOD_DATA_MSG,
1284 pjsip_msg_clone(dlg->pool, rdata->msg_info.msg));
1286 sub_tree->notification_batch_interval = tree->notification_batch_interval;
1288 sub_tree->root = create_virtual_subscriptions(handler, resource, generator, sub_tree, tree->root);
1289 if (AST_VECTOR_SIZE(&sub_tree->root->children) > 0) {
1290 sub_tree->is_list = 1;
1296 static int generate_initial_notify(struct ast_sip_subscription *sub);
1297 static int send_notify(struct sip_subscription_tree *sub_tree, unsigned int force_full_state);
1299 /*! \brief Callback function to perform the actual recreation of a subscription */
1300 static int subscription_persistence_recreate(void *obj, void *arg, int flags)
1302 struct subscription_persistence *persistence = obj;
1303 pj_pool_t *pool = arg;
1304 pjsip_rx_data rdata = { { 0, }, };
1305 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
1306 struct sip_subscription_tree *sub_tree;
1307 struct ast_sip_pubsub_body_generator *generator;
1310 size_t resource_size;
1311 pjsip_sip_uri *request_uri;
1312 struct resource_tree tree;
1313 pjsip_expires_hdr *expires_header;
1314 struct ast_sip_subscription_handler *handler;
1316 /* If this subscription has already expired remove it */
1317 if (ast_tvdiff_ms(persistence->expires, ast_tvnow()) <= 0) {
1318 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1322 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", persistence->endpoint);
1324 ast_log(LOG_WARNING, "A subscription for '%s' could not be recreated as the endpoint was not found\n",
1325 persistence->endpoint);
1326 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1330 pj_pool_reset(pool);
1331 rdata.tp_info.pool = pool;
1333 if (ast_sip_create_rdata(&rdata, persistence->packet, persistence->src_name, persistence->src_port,
1334 persistence->transport_key, persistence->local_name, persistence->local_port)) {
1335 ast_log(LOG_WARNING, "A subscription for '%s' could not be recreated as the message could not be parsed\n",
1336 persistence->endpoint);
1337 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1341 request_uri = pjsip_uri_get_uri(rdata.msg_info.msg->line.req.uri);
1342 resource_size = pj_strlen(&request_uri->user) + 1;
1343 resource = alloca(resource_size);
1344 ast_copy_pj_str(resource, &request_uri->user, resource_size);
1346 /* Update the expiration header with the new expiration */
1347 expires_header = pjsip_msg_find_hdr(rdata.msg_info.msg, PJSIP_H_EXPIRES, rdata.msg_info.msg->hdr.next);
1348 if (!expires_header) {
1349 expires_header = pjsip_expires_hdr_create(pool, 0);
1350 if (!expires_header) {
1351 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1354 pjsip_msg_add_hdr(rdata.msg_info.msg, (pjsip_hdr*)expires_header);
1356 expires_header->ivalue = (ast_tvdiff_ms(persistence->expires, ast_tvnow()) / 1000);
1358 handler = subscription_get_handler_from_rdata(&rdata);
1359 if (!handler || !handler->notifier) {
1360 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1364 generator = subscription_get_generator_from_rdata(&rdata, handler);
1366 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1370 ast_sip_mod_data_set(rdata.tp_info.pool, rdata.endpt_info.mod_data,
1371 pubsub_module.id, MOD_DATA_PERSISTENCE, persistence);
1373 memset(&tree, 0, sizeof(tree));
1374 resp = build_resource_tree(endpoint, handler, resource, &tree,
1375 ast_sip_pubsub_has_eventlist_support(&rdata));
1376 if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
1377 pj_status_t dlg_status;
1379 sub_tree = create_subscription_tree(handler, endpoint, &rdata, resource, generator, &tree, &dlg_status);
1381 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1382 ast_log(LOG_WARNING, "Failed to re-create subscription for %s\n", persistence->endpoint);
1385 sub_tree->persistence = ao2_bump(persistence);
1386 subscription_persistence_update(sub_tree, &rdata);
1387 if (generate_initial_notify(sub_tree->root)) {
1388 pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
1390 send_notify(sub_tree, 1);
1392 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1394 resource_tree_destroy(&tree);
1399 /*! \brief Function which loads and recreates persisted subscriptions upon startup when the system is fully booted */
1400 static int subscription_persistence_load(void *data)
1402 struct ao2_container *persisted_subscriptions = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
1403 "subscription_persistence", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1406 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "rtd%p", PJSIP_POOL_RDATA_LEN,
1407 PJSIP_POOL_RDATA_INC);
1409 ast_log(LOG_WARNING, "Could not create a memory pool for recreating SIP subscriptions\n");
1413 ao2_callback(persisted_subscriptions, OBJ_NODATA, subscription_persistence_recreate, pool);
1415 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1417 ao2_ref(persisted_subscriptions, -1);
1421 /*! \brief Event callback which fires subscription persistence recreation when the system is fully booted */
1422 static void subscription_persistence_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
1424 struct ast_json_payload *payload;
1427 if (stasis_message_type(message) != ast_manager_get_generic_type()) {
1431 payload = stasis_message_data(message);
1432 type = ast_json_string_get(ast_json_object_get(payload->json, "type"));
1434 /* This subscription only responds to the FullyBooted event so that all modules have been loaded when we
1435 * recreate SIP subscriptions.
1437 if (strcmp(type, "FullyBooted")) {
1441 /* This has to be here so the subscription is recreated when the body generator is available */
1442 ast_sip_push_task(NULL, subscription_persistence_load, NULL);
1444 /* Once the system is fully booted we don't care anymore */
1445 stasis_unsubscribe(sub);
1448 typedef int (*on_subscription_t)(struct sip_subscription_tree *sub, void *arg);
1450 static int for_each_subscription(on_subscription_t on_subscription, void *arg)
1453 struct sip_subscription_tree *i;
1454 SCOPED_LOCK(lock, &subscriptions, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
1456 if (!on_subscription) {
1460 AST_RWLIST_TRAVERSE(&subscriptions, i, next) {
1461 if (on_subscription(i, arg)) {
1469 static void sip_subscription_to_ami(struct sip_subscription_tree *sub_tree,
1470 struct ast_str **buf)
1473 struct ast_sip_endpoint_id_configuration *id = &sub_tree->endpoint->id;
1475 ast_str_append(buf, 0, "Role: %s\r\n",
1476 sip_subscription_roles_map[sub_tree->role]);
1477 ast_str_append(buf, 0, "Endpoint: %s\r\n",
1478 ast_sorcery_object_get_id(sub_tree->endpoint));
1480 ast_copy_pj_str(str, &sub_tree->dlg->call_id->id, sizeof(str));
1481 ast_str_append(buf, 0, "Callid: %s\r\n", str);
1483 ast_str_append(buf, 0, "State: %s\r\n", pjsip_evsub_get_state_name(sub_tree->evsub));
1485 ast_callerid_merge(str, sizeof(str),
1486 S_COR(id->self.name.valid, id->self.name.str, NULL),
1487 S_COR(id->self.number.valid, id->self.number.str, NULL),
1490 ast_str_append(buf, 0, "Callerid: %s\r\n", str);
1492 /* XXX This needs to be done recursively for lists */
1493 if (sub_tree->root->handler->to_ami) {
1494 sub_tree->root->handler->to_ami(sub_tree->root, buf);
1499 void *ast_sip_subscription_get_header(const struct ast_sip_subscription *sub, const char *header)
1501 pjsip_dialog *dlg = sub->tree->dlg;
1502 pjsip_msg *msg = ast_sip_mod_data_get(dlg->mod_data, pubsub_module.id, MOD_DATA_MSG);
1505 pj_cstr(&name, header);
1507 return pjsip_msg_find_hdr_by_name(msg, &name, NULL);
1510 struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_subscription_handler *handler,
1511 struct ast_sip_endpoint *endpoint, const char *resource)
1513 struct ast_sip_subscription *sub;
1515 struct ast_sip_contact *contact;
1517 pjsip_tx_data *tdata;
1519 struct sip_subscription_tree *sub_tree = NULL;
1521 sub_tree = allocate_subscription_tree(endpoint);
1526 sub = allocate_subscription(handler, resource, sub_tree);
1528 ao2_cleanup(sub_tree);
1532 contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);
1533 if (!contact || ast_strlen_zero(contact->uri)) {
1534 ast_log(LOG_WARNING, "No contacts configured for endpoint %s. Unable to create SIP subsription\n",
1535 ast_sorcery_object_get_id(endpoint));
1536 ao2_ref(sub_tree, -1);
1537 ao2_cleanup(contact);
1541 dlg = ast_sip_create_dialog_uac(endpoint, contact->uri, NULL);
1542 ao2_cleanup(contact);
1544 ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
1545 ao2_ref(sub_tree, -1);
1549 pj_cstr(&event, handler->event_name);
1550 pjsip_evsub_create_uac(dlg, &pubsub_cb, &event, 0, &sub_tree->evsub);
1551 subscription_setup_dialog(sub_tree, dlg);
1553 evsub = sub_tree->evsub;
1555 if (pjsip_evsub_initiate(evsub, NULL, -1, &tdata) == PJ_SUCCESS) {
1556 pjsip_evsub_send_request(evsub, tdata);
1558 /* pjsip_evsub_terminate will result in pubsub_on_evsub_state,
1559 * being called and terminating the subscription. Therefore, we don't
1560 * need to decrease the reference count of sub here.
1562 pjsip_evsub_terminate(evsub, PJ_TRUE);
1563 ao2_ref(sub_tree, -1);
1570 struct ast_sip_endpoint *ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
1572 ast_assert(sub->tree->endpoint != NULL);
1573 return ao2_bump(sub->tree->endpoint);
1576 struct ast_taskprocessor *ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub)
1578 ast_assert(sub->tree->serializer != NULL);
1579 return sub->tree->serializer;
1583 * \brief Pre-allocate a buffer for the transmission
1585 * Typically, we let PJSIP do this step for us when we send a request. PJSIP's buffer
1586 * allocation algorithm is to allocate a buffer of PJSIP_MAX_PKT_LEN bytes and attempt
1587 * to write the packet to the allocated buffer. If the buffer is too small to hold the
1588 * packet, then we get told the message is too long to be sent.
1590 * When dealing with SIP NOTIFY, especially with RLS, it is possible to exceed
1591 * PJSIP_MAX_PKT_LEN. Rather than accepting the limitation imposed on us by default,
1592 * we instead take the strategy of pre-allocating the buffer, testing for ourselves
1593 * if the message will fit, and resizing the buffer as required.
1595 * RFC 3261 says that a SIP UDP request can be up to 65535 bytes long. We're capping
1596 * it at 64000 for a couple of reasons:
1597 * 1) Allocating more than 64K at a time is hard to justify
1598 * 2) If the message goes through proxies, those proxies will want to add Via and
1599 * Record-Route headers, making the message even larger. Giving some space for
1600 * those headers is a nice thing to do.
1602 * RFC 3261 does not place an upper limit on the size of TCP requests, but we are
1603 * going to impose the same 64K limit as a memory savings.
1605 * \param tdata The tdata onto which to allocate a buffer
1607 * \retval -1 The message is too large
1609 static int allocate_tdata_buffer(pjsip_tx_data *tdata)
1615 for (buf_size = PJSIP_MAX_PKT_LEN; size == -1 && buf_size < 64000; buf_size *= 2) {
1616 buf = pj_pool_alloc(tdata->pool, buf_size);
1617 size = pjsip_msg_print(tdata->msg, buf, buf_size);
1624 tdata->buf.start = buf;
1625 tdata->buf.cur = tdata->buf.start;
1626 tdata->buf.end = tdata->buf.start + buf_size;
1631 static int sip_subscription_send_request(struct sip_subscription_tree *sub_tree, pjsip_tx_data *tdata)
1633 #ifdef TEST_FRAMEWORK
1634 struct ast_sip_endpoint *endpoint = sub_tree->endpoint;
1638 if (allocate_tdata_buffer(tdata)) {
1639 ast_log(LOG_ERROR, "SIP request %s is too large to send.\n", tdata->info);
1643 res = pjsip_evsub_send_request(sub_tree->evsub, tdata) == PJ_SUCCESS ? 0 : -1;
1644 subscription_persistence_update(sub_tree, NULL);
1646 ast_test_suite_event_notify("SUBSCRIPTION_STATE_SET",
1649 pjsip_evsub_get_state_name(sub_tree->evsub),
1650 ast_sorcery_object_get_id(endpoint));
1656 * \brief Add a resource XML element to an RLMI body
1658 * Each resource element represents a subscribed resource in the list. This function currently
1659 * will unconditionally add an instance element to each created resource element. Instance
1660 * elements refer to later parts in the multipart body.
1662 * \param pool PJLIB allocation pool
1663 * \param cid Content-ID header of the resource
1664 * \param resource_name Name of the resource
1665 * \param resource_uri URI of the resource
1666 * \param state State of the subscribed resource
1668 static void add_rlmi_resource(pj_pool_t *pool, pj_xml_node *rlmi, const pjsip_generic_string_hdr *cid,
1669 const char *resource_name, const pjsip_sip_uri *resource_uri, pjsip_evsub_state state)
1671 static pj_str_t cid_name = { "cid", 3 };
1672 pj_xml_node *resource;
1674 pj_xml_node *instance;
1675 pj_xml_attr *cid_attr;
1677 char uri[PJSIP_MAX_URL_SIZE];
1679 /* This creates a string representing the Content-ID without the enclosing < > */
1680 const pj_str_t cid_stripped = {
1681 .ptr = cid->hvalue.ptr + 1,
1682 .slen = cid->hvalue.slen - 2,
1685 resource = ast_sip_presence_xml_create_node(pool, rlmi, "resource");
1686 name = ast_sip_presence_xml_create_node(pool, resource, "name");
1687 instance = ast_sip_presence_xml_create_node(pool, resource, "instance");
1689 pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, resource_uri, uri, sizeof(uri));
1690 ast_sip_presence_xml_create_attr(pool, resource, "uri", uri);
1692 pj_strdup2(pool, &name->content, resource_name);
1694 ast_generate_random_string(id, sizeof(id));
1696 ast_sip_presence_xml_create_attr(pool, instance, "id", id);
1697 ast_sip_presence_xml_create_attr(pool, instance, "state",
1698 state == PJSIP_EVSUB_STATE_TERMINATED ? "terminated" : "active");
1700 /* Use the PJLIB-util XML library directly here since we are using a
1704 cid_attr = pj_xml_attr_new(pool, &cid_name, &cid_stripped);
1705 pj_xml_add_attr(instance, cid_attr);
1709 * \brief A multipart body part and meta-information
1711 * When creating a multipart body part, the end result (the
1712 * pjsip_multipart_part) is hard to inspect without undoing
1713 * a lot of what was done to create it. Therefore, we use this
1714 * structure to store meta-information about the body part.
1716 * The main consumer of this is the creator of the RLMI body
1717 * part of a multipart resource list body.
1720 /*! Content-ID header for the body part */
1721 pjsip_generic_string_hdr *cid;
1722 /*! Subscribed resource represented in the body part */
1723 const char *resource;
1724 /*! URI for the subscribed body part */
1726 /*! Subscription state of the resource represented in the body part */
1727 pjsip_evsub_state state;
1728 /*! The actual body part that will be present in the multipart body */
1729 pjsip_multipart_part *part;
1733 * \brief Type declaration for container of body part structures
1735 AST_VECTOR(body_part_list, struct body_part *);
1738 * \brief Create a Content-ID header
1740 * Content-ID headers are required by RFC2387 for multipart/related
1741 * bodies. They serve as identifiers for each part of the multipart body.
1743 * \param pool PJLIB allocation pool
1744 * \param sub Subscription to a resource
1746 static pjsip_generic_string_hdr *generate_content_id_hdr(pj_pool_t *pool,
1747 const struct ast_sip_subscription *sub)
1749 static const pj_str_t cid_name = { "Content-ID", 10 };
1750 pjsip_generic_string_hdr *cid;
1755 /* '<' + '@' + '>' = 3. pj_str_t does not require a null-terminator */
1756 alloc_size = sizeof(id) + pj_strlen(&sub->uri->host) + 3;
1757 cid_value.ptr = pj_pool_alloc(pool, alloc_size);
1758 cid_value.slen = sprintf(cid_value.ptr, "<%s@%.*s>",
1759 ast_generate_random_string(id, sizeof(id)),
1760 (int) pj_strlen(&sub->uri->host), pj_strbuf(&sub->uri->host));
1761 cid = pjsip_generic_string_hdr_create(pool, &cid_name, &cid_value);
1766 static int rlmi_print_body(struct pjsip_msg_body *msg_body, char *buf, pj_size_t size)
1769 pj_xml_node *rlmi = msg_body->data;
1771 num_printed = pj_xml_print(rlmi, buf, size, PJ_TRUE);
1772 if (num_printed == AST_PJSIP_XML_PROLOG_LEN) {
1779 static void *rlmi_clone_data(pj_pool_t *pool, const void *data, unsigned len)
1781 const pj_xml_node *rlmi = data;
1783 return pj_xml_clone(pool, rlmi);
1787 * \brief Create an RLMI body part for a multipart resource list body
1789 * RLMI (Resource list meta information) is a special body type that lists
1790 * the subscribed resources and tells subscribers the number of subscribed
1791 * resources and what other body parts are in the multipart body. The
1792 * RLMI body also has a version number that a subscriber can use to ensure
1793 * that the locally-stored state corresponds to server state.
1795 * \param pool The allocation pool
1796 * \param sub The subscription representing the subscribed resource list
1797 * \param body_parts A container of body parts that RLMI will refer to
1798 * \param full_state Indicates whether this is a full or partial state notification
1799 * \return The multipart part representing the RLMI body
1801 static pjsip_multipart_part *build_rlmi_body(pj_pool_t *pool, struct ast_sip_subscription *sub,
1802 struct body_part_list *body_parts, unsigned int full_state)
1804 static const pj_str_t rlmi_type = { "application", 11 };
1805 static const pj_str_t rlmi_subtype = { "rlmi+xml", 8 };
1808 pjsip_multipart_part *rlmi_part;
1809 char version_str[32];
1810 char uri[PJSIP_MAX_URL_SIZE];
1811 pjsip_generic_string_hdr *cid;
1814 rlmi = ast_sip_presence_xml_create_node(pool, NULL, "list");
1815 ast_sip_presence_xml_create_attr(pool, rlmi, "xmlns", "urn:ietf:params:xml:ns:rlmi");
1817 ast_sip_subscription_get_local_uri(sub, uri, sizeof(uri));
1818 ast_sip_presence_xml_create_attr(pool, rlmi, "uri", uri);
1820 snprintf(version_str, sizeof(version_str), "%u", sub->version++);
1821 ast_sip_presence_xml_create_attr(pool, rlmi, "version", version_str);
1822 ast_sip_presence_xml_create_attr(pool, rlmi, "fullState", full_state ? "true" : "false");
1824 name = ast_sip_presence_xml_create_node(pool, rlmi, "name");
1825 pj_strdup2(pool, &name->content, ast_sip_subscription_get_resource_name(sub));
1827 for (i = 0; i < AST_VECTOR_SIZE(body_parts); ++i) {
1828 const struct body_part *part = AST_VECTOR_GET(body_parts, i);
1830 add_rlmi_resource(pool, rlmi, part->cid, part->resource, part->uri, part->state);
1833 rlmi_part = pjsip_multipart_create_part(pool);
1835 rlmi_part->body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body);
1836 pj_strdup(pool, &rlmi_part->body->content_type.type, &rlmi_type);
1837 pj_strdup(pool, &rlmi_part->body->content_type.subtype, &rlmi_subtype);
1838 pj_list_init(&rlmi_part->body->content_type.param);
1840 rlmi_part->body->data = pj_xml_clone(pool, rlmi);
1841 rlmi_part->body->clone_data = rlmi_clone_data;
1842 rlmi_part->body->print_body = rlmi_print_body;
1844 cid = generate_content_id_hdr(pool, sub);
1845 pj_list_insert_before(&rlmi_part->hdr, cid);
1850 static pjsip_msg_body *generate_notify_body(pj_pool_t *pool, struct ast_sip_subscription *root,
1851 unsigned int force_full_state);
1854 * \brief Destroy a list of body parts
1856 * \param parts The container of parts to destroy
1858 static void free_body_parts(struct body_part_list *parts)
1862 for (i = 0; i < AST_VECTOR_SIZE(parts); ++i) {
1863 struct body_part *part = AST_VECTOR_GET(parts, i);
1867 AST_VECTOR_FREE(parts);
1871 * \brief Allocate and initialize a body part structure
1873 * \param pool PJLIB allocation pool
1874 * \param sub Subscription representing a subscribed resource
1876 static struct body_part *allocate_body_part(pj_pool_t *pool, const struct ast_sip_subscription *sub)
1878 struct body_part *bp;
1880 bp = ast_calloc(1, sizeof(*bp));
1885 bp->cid = generate_content_id_hdr(pool, sub);
1886 bp->resource = sub->resource;
1887 bp->state = sub->subscription_state;
1894 * \brief Create a multipart body part for a subscribed resource
1896 * \param pool PJLIB allocation pool
1897 * \param sub The subscription representing a subscribed resource
1898 * \param parts A vector of parts to append the created part to.
1899 * \param use_full_state Unused locally, but may be passed to other functions
1901 static void build_body_part(pj_pool_t *pool, struct ast_sip_subscription *sub,
1902 struct body_part_list *parts, unsigned int use_full_state)
1904 struct body_part *bp;
1905 pjsip_msg_body *body;
1907 bp = allocate_body_part(pool, sub);
1912 body = generate_notify_body(pool, sub, use_full_state);
1914 /* Partial state was requested and the resource has not changed state */
1919 bp->part = pjsip_multipart_create_part(pool);
1920 bp->part->body = body;
1921 pj_list_insert_before(&bp->part->hdr, bp->cid);
1923 AST_VECTOR_APPEND(parts, bp);
1927 * \brief Create and initialize the PJSIP multipart body structure for a resource list subscription
1930 * \return The multipart message body
1932 static pjsip_msg_body *create_multipart_body(pj_pool_t *pool)
1934 pjsip_media_type media_type;
1935 pjsip_param *media_type_param;
1937 pj_str_t pj_boundary;
1939 pjsip_media_type_init2(&media_type, "multipart", "related");
1941 media_type_param = pj_pool_alloc(pool, sizeof(*media_type_param));
1942 pj_list_init(media_type_param);
1944 pj_strdup2(pool, &media_type_param->name, "type");
1945 pj_strdup2(pool, &media_type_param->value, "\"application/rlmi+xml\"");
1947 pj_list_insert_before(&media_type.param, media_type_param);
1949 pj_cstr(&pj_boundary, ast_generate_random_string(boundary, sizeof(boundary)));
1950 return pjsip_multipart_create(pool, &media_type, &pj_boundary);
1954 * \brief Create a resource list body for NOTIFY requests
1956 * Resource list bodies are multipart/related bodies. The first part of the multipart body
1957 * is an RLMI body that describes the rest of the parts to come. The other parts of the body
1958 * convey state of individual subscribed resources.
1960 * \param pool PJLIB allocation pool
1961 * \param sub Subscription details from which to generate body
1962 * \param force_full_state If true, ignore resource list settings and send a full state notification
1963 * \return The generated multipart/related body
1965 static pjsip_msg_body *generate_list_body(pj_pool_t *pool, struct ast_sip_subscription *sub,
1966 unsigned int force_full_state)
1969 pjsip_multipart_part *rlmi_part;
1970 pjsip_msg_body *multipart;
1971 struct body_part_list body_parts;
1972 unsigned int use_full_state = force_full_state ? 1 : sub->full_state;
1974 if (AST_VECTOR_INIT(&body_parts, AST_VECTOR_SIZE(&sub->children))) {
1978 for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
1979 build_body_part(pool, AST_VECTOR_GET(&sub->children, i), &body_parts, use_full_state);
1982 /* This can happen if issuing partial state and no children of the list have changed state */
1983 if (AST_VECTOR_SIZE(&body_parts) == 0) {
1987 multipart = create_multipart_body(pool);
1989 rlmi_part = build_rlmi_body(pool, sub, &body_parts, use_full_state);
1993 pjsip_multipart_add_part(pool, multipart, rlmi_part);
1995 for (i = 0; i < AST_VECTOR_SIZE(&body_parts); ++i) {
1996 pjsip_multipart_add_part(pool, multipart, AST_VECTOR_GET(&body_parts, i)->part);
1999 free_body_parts(&body_parts);
2004 * \brief Create the body for a NOTIFY request.
2006 * \param pool The pool used for allocations
2007 * \param root The root of the subscription tree
2008 * \param force_full_state If true, ignore resource list settings and send a full state notification
2010 static pjsip_msg_body *generate_notify_body(pj_pool_t *pool, struct ast_sip_subscription *root,
2011 unsigned int force_full_state)
2013 pjsip_msg_body *body;
2015 if (AST_VECTOR_SIZE(&root->children) == 0) {
2016 if (force_full_state || root->body_changed) {
2017 /* Not a list. We've already generated the body and saved it on the subscription.
2018 * Use that directly.
2024 pj_cstr(&type, ast_sip_subscription_get_body_type(root));
2025 pj_cstr(&subtype, ast_sip_subscription_get_body_subtype(root));
2026 pj_cstr(&text, ast_str_buffer(root->body_text));
2028 body = pjsip_msg_body_create(pool, &type, &subtype, &text);
2029 root->body_changed = 0;
2034 body = generate_list_body(pool, root, force_full_state);
2041 * \brief Shortcut method to create a Require: eventlist header
2043 static pjsip_require_hdr *create_require_eventlist(pj_pool_t *pool)
2045 pjsip_require_hdr *require;
2047 require = pjsip_require_hdr_create(pool);
2048 pj_strdup2(pool, &require->values[0], "eventlist");
2055 * \brief Send a NOTIFY request to a subscriber
2057 * \param sub_tree The subscription tree representing the subscription
2058 * \param force_full_state If true, ignore resource list settings and send full resource list state.
2060 * \retval non-zero Failure
2062 static int send_notify(struct sip_subscription_tree *sub_tree, unsigned int force_full_state)
2064 pjsip_evsub *evsub = sub_tree->evsub;
2065 pjsip_tx_data *tdata;
2067 if (ast_shutdown_final()
2068 && sub_tree->root->subscription_state == PJSIP_EVSUB_STATE_TERMINATED
2069 && sub_tree->persistence) {
2073 if (pjsip_evsub_notify(evsub, sub_tree->root->subscription_state,
2074 NULL, NULL, &tdata) != PJ_SUCCESS) {
2078 tdata->msg->body = generate_notify_body(tdata->pool, sub_tree->root, force_full_state);
2079 if (!tdata->msg->body) {
2080 pjsip_tx_data_dec_ref(tdata);
2084 if (sub_tree->is_list) {
2085 pjsip_require_hdr *require = create_require_eventlist(tdata->pool);
2086 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) require);
2089 if (sip_subscription_send_request(sub_tree, tdata)) {
2093 sub_tree->send_scheduled_notify = 0;
2098 static int serialized_send_notify(void *userdata)
2100 struct sip_subscription_tree *sub_tree = userdata;
2102 /* It's possible that between when the notification was scheduled
2103 * and now, that a new SUBSCRIBE arrived, requiring full state to be
2104 * sent out in an immediate NOTIFY. If that has happened, we need to
2105 * bail out here instead of sending the batched NOTIFY.
2107 if (!sub_tree->send_scheduled_notify) {
2108 ao2_cleanup(sub_tree);
2112 send_notify(sub_tree, 0);
2113 ast_test_suite_event_notify("SUBSCRIPTION_STATE_CHANGED",
2115 sub_tree->root->resource);
2116 sub_tree->notify_sched_id = -1;
2117 ao2_cleanup(sub_tree);
2121 static int sched_cb(const void *data)
2123 struct sip_subscription_tree *sub_tree = (struct sip_subscription_tree *) data;
2125 /* We don't need to bump the refcount of sub_tree since we bumped it when scheduling this task */
2126 ast_sip_push_task(sub_tree->serializer, serialized_send_notify, sub_tree);
2130 static int schedule_notification(struct sip_subscription_tree *sub_tree)
2132 /* There's already a notification scheduled */
2133 if (sub_tree->notify_sched_id > -1) {
2137 sub_tree->notify_sched_id = ast_sched_add(sched, sub_tree->notification_batch_interval, sched_cb, ao2_bump(sub_tree));
2138 if (sub_tree->notify_sched_id < 0) {
2142 sub_tree->send_scheduled_notify = 1;
2146 int ast_sip_subscription_notify(struct ast_sip_subscription *sub, struct ast_sip_body_data *notify_data,
2149 if (ast_sip_pubsub_generate_body_content(ast_sip_subscription_get_body_type(sub),
2150 ast_sip_subscription_get_body_subtype(sub), notify_data, &sub->body_text)) {
2154 sub->body_changed = 1;
2156 sub->subscription_state = PJSIP_EVSUB_STATE_TERMINATED;
2159 if (sub->tree->notification_batch_interval) {
2160 return schedule_notification(sub->tree);
2163 /* See the note in pubsub_on_rx_refresh() for why sub->tree is refbumped here */
2164 ao2_ref(sub->tree, +1);
2165 res = send_notify(sub->tree, 0);
2166 ast_test_suite_event_notify(terminate ? "SUBSCRIPTION_TERMINATED" : "SUBSCRIPTION_STATE_CHANGED",
2168 sub->tree->root->resource);
2169 ao2_ref(sub->tree, -1);
2175 void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
2177 pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, sub->uri, buf, size);
2180 void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
2182 pjsip_dialog *dlg = sub->tree->dlg;
2183 ast_copy_pj_str(buf, &dlg->remote.info_str, size);
2186 const char *ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
2188 return sub->resource;
2191 int ast_sip_subscription_is_terminated(const struct ast_sip_subscription *sub)
2193 return sub->subscription_state == PJSIP_EVSUB_STATE_TERMINATED ? 1 : 0;
2196 static int sip_subscription_accept(struct sip_subscription_tree *sub_tree, pjsip_rx_data *rdata, int response)
2200 /* If this is a persistence recreation the subscription has already been accepted */
2201 if (ast_sip_mod_data_get(rdata->endpt_info.mod_data, pubsub_module.id, MOD_DATA_PERSISTENCE)) {
2205 pj_list_init(&res_hdr);
2206 if (sub_tree->is_list) {
2207 /* If subscribing to a list, our response has to have a Require: eventlist header in it */
2208 pj_list_insert_before(&res_hdr, create_require_eventlist(rdata->tp_info.pool));
2211 return pjsip_evsub_accept(sub_tree->evsub, rdata, response, &res_hdr) == PJ_SUCCESS ? 0 : -1;
2214 static void subscription_datastore_destroy(void *obj)
2216 struct ast_datastore *datastore = obj;
2218 /* Using the destroy function (if present) destroy the data */
2219 if (datastore->info->destroy != NULL && datastore->data != NULL) {
2220 datastore->info->destroy(datastore->data);
2221 datastore->data = NULL;
2224 ast_free((void *) datastore->uid);
2225 datastore->uid = NULL;
2228 struct ast_datastore *ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
2230 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
2231 char uuid_buf[AST_UUID_STR_LEN];
2232 const char *uid_ptr = uid;
2238 datastore = ao2_alloc(sizeof(*datastore), subscription_datastore_destroy);
2243 datastore->info = info;
2244 if (ast_strlen_zero(uid)) {
2245 /* They didn't provide an ID so we'll provide one ourself */
2246 uid_ptr = ast_uuid_generate_str(uuid_buf, sizeof(uuid_buf));
2249 datastore->uid = ast_strdup(uid_ptr);
2250 if (!datastore->uid) {
2254 ao2_ref(datastore, +1);
2258 int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore)
2260 ast_assert(datastore != NULL);
2261 ast_assert(datastore->info != NULL);
2262 ast_assert(!ast_strlen_zero(datastore->uid));
2264 if (!ao2_link(subscription->datastores, datastore)) {
2270 struct ast_datastore *ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
2272 return ao2_find(subscription->datastores, name, OBJ_KEY);
2275 void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
2277 ao2_find(subscription->datastores, name, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
2280 int ast_sip_publication_add_datastore(struct ast_sip_publication *publication, struct ast_datastore *datastore)
2282 ast_assert(datastore != NULL);
2283 ast_assert(datastore->info != NULL);
2284 ast_assert(!ast_strlen_zero(datastore->uid));
2286 if (!ao2_link(publication->datastores, datastore)) {
2292 struct ast_datastore *ast_sip_publication_get_datastore(struct ast_sip_publication *publication, const char *name)
2294 return ao2_find(publication->datastores, name, OBJ_KEY);
2297 void ast_sip_publication_remove_datastore(struct ast_sip_publication *publication, const char *name)
2299 ao2_callback(publication->datastores, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA, NULL, (void *) name);
2302 AST_RWLIST_HEAD_STATIC(publish_handlers, ast_sip_publish_handler);
2304 static int publication_hash_fn(const void *obj, const int flags)
2306 const struct ast_sip_publication *publication = obj;
2307 const int *entity_tag = obj;
2309 return flags & OBJ_KEY ? *entity_tag : publication->entity_tag;
2312 static int publication_cmp_fn(void *obj, void *arg, int flags)
2314 const struct ast_sip_publication *publication1 = obj;
2315 const struct ast_sip_publication *publication2 = arg;
2316 const int *entity_tag = arg;
2318 return (publication1->entity_tag == (flags & OBJ_KEY ? *entity_tag : publication2->entity_tag) ?
2319 CMP_MATCH | CMP_STOP : 0);
2322 static void publish_add_handler(struct ast_sip_publish_handler *handler)
2324 SCOPED_LOCK(lock, &publish_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2325 AST_RWLIST_INSERT_TAIL(&publish_handlers, handler, next);
2328 int ast_sip_register_publish_handler(struct ast_sip_publish_handler *handler)
2330 if (ast_strlen_zero(handler->event_name)) {
2331 ast_log(LOG_ERROR, "No event package specified for publish handler. Cannot register\n");
2335 if (!(handler->publications = ao2_container_alloc(PUBLICATIONS_BUCKETS,
2336 publication_hash_fn, publication_cmp_fn))) {
2337 ast_log(LOG_ERROR, "Could not allocate publications container for event '%s'\n",
2338 handler->event_name);
2342 publish_add_handler(handler);
2344 ast_module_ref(ast_module_info->self);
2349 void ast_sip_unregister_publish_handler(struct ast_sip_publish_handler *handler)
2351 struct ast_sip_publish_handler *iter;
2352 SCOPED_LOCK(lock, &publish_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2353 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&publish_handlers, iter, next) {
2354 if (handler == iter) {
2355 AST_RWLIST_REMOVE_CURRENT(next);
2356 ao2_cleanup(handler->publications);
2357 ast_module_unref(ast_module_info->self);
2361 AST_RWLIST_TRAVERSE_SAFE_END;
2364 AST_RWLIST_HEAD_STATIC(subscription_handlers, ast_sip_subscription_handler);
2366 static void sub_add_handler(struct ast_sip_subscription_handler *handler)
2368 SCOPED_LOCK(lock, &subscription_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2369 AST_RWLIST_INSERT_TAIL(&subscription_handlers, handler, next);
2370 ast_module_ref(ast_module_info->self);
2373 static struct ast_sip_subscription_handler *find_sub_handler_for_event_name(const char *event_name)
2375 struct ast_sip_subscription_handler *iter;
2376 SCOPED_LOCK(lock, &subscription_handlers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
2378 AST_RWLIST_TRAVERSE(&subscription_handlers, iter, next) {
2379 if (!strcmp(iter->event_name, event_name)) {
2386 int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
2389 pj_str_t accept[AST_SIP_MAX_ACCEPT] = { {0, }, };
2390 struct ast_sip_subscription_handler *existing;
2393 if (ast_strlen_zero(handler->event_name)) {
2394 ast_log(LOG_ERROR, "No event package specified for subscription handler. Cannot register\n");
2398 existing = find_sub_handler_for_event_name(handler->event_name);
2400 ast_log(LOG_ERROR, "Unable to register subscription handler for event %s."
2401 "A handler is already registered\n", handler->event_name);
2405 for (i = 0; i < AST_SIP_MAX_ACCEPT && !ast_strlen_zero(handler->accept[i]); ++i) {
2406 pj_cstr(&accept[i], handler->accept[i]);
2409 pj_cstr(&event, handler->event_name);
2411 pjsip_evsub_register_pkg(&pubsub_module, &event, DEFAULT_EXPIRES, i, accept);
2413 sub_add_handler(handler);
2418 void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler)
2420 struct ast_sip_subscription_handler *iter;
2421 SCOPED_LOCK(lock, &subscription_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2422 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&subscription_handlers, iter, next) {
2423 if (handler == iter) {
2424 AST_RWLIST_REMOVE_CURRENT(next);
2425 ast_module_unref(ast_module_info->self);
2429 AST_RWLIST_TRAVERSE_SAFE_END;
2432 static struct ast_sip_pubsub_body_generator *find_body_generator_type_subtype(const char *content_type,
2433 const char *content_subtype)
2435 struct ast_sip_pubsub_body_generator *iter;
2436 SCOPED_LOCK(lock, &body_generators, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
2438 AST_LIST_TRAVERSE(&body_generators, iter, list) {
2439 if (!strcmp(iter->type, content_type) &&
2440 !strcmp(iter->subtype, content_subtype)) {
2448 static struct ast_sip_pubsub_body_generator *find_body_generator_accept(const char *accept)
2450 char *accept_copy = ast_strdupa(accept);
2451 char *subtype = accept_copy;
2452 char *type = strsep(&subtype, "/");
2454 if (ast_strlen_zero(type) || ast_strlen_zero(subtype)) {
2458 return find_body_generator_type_subtype(type, subtype);
2461 static struct ast_sip_pubsub_body_generator *find_body_generator(char accept[AST_SIP_MAX_ACCEPT][64],
2462 size_t num_accept, const char *body_type)
2465 struct ast_sip_pubsub_body_generator *generator = NULL;
2467 for (i = 0; i < num_accept; ++i) {
2468 generator = find_body_generator_accept(accept[i]);
2470 ast_debug(3, "Body generator %p found for accept type %s\n", generator, accept[i]);
2471 if (strcmp(generator->body_type, body_type)) {
2472 ast_log(LOG_WARNING, "Body generator '%s/%s'(%p) does not accept the type of data this event generates\n",
2473 generator->type, generator->subtype, generator);
2479 ast_debug(3, "No body generator found for accept type %s\n", accept[i]);
2486 static int generate_initial_notify(struct ast_sip_subscription *sub)
2490 struct ast_sip_body_data data = {
2491 .body_type = sub->handler->body_type,
2494 if (AST_VECTOR_SIZE(&sub->children) > 0) {
2497 for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
2498 if (generate_initial_notify(AST_VECTOR_GET(&sub->children, i))) {
2506 if (sub->handler->notifier->subscription_established(sub)) {
2510 notify_data = sub->handler->notifier->get_notify_data(sub);
2515 data.body_data = notify_data;
2517 res = ast_sip_pubsub_generate_body_content(ast_sip_subscription_get_body_type(sub),
2518 ast_sip_subscription_get_body_subtype(sub), &data, &sub->body_text);
2520 ao2_cleanup(notify_data);
2525 static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
2527 pjsip_expires_hdr *expires_header;
2528 struct ast_sip_subscription_handler *handler;
2529 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2530 struct sip_subscription_tree *sub_tree;
2531 struct ast_sip_pubsub_body_generator *generator;
2533 pjsip_uri *request_uri;
2534 pjsip_sip_uri *request_uri_sip;
2535 size_t resource_size;
2537 struct resource_tree tree;
2538 pj_status_t dlg_status;
2540 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2541 ast_assert(endpoint != NULL);
2543 if (!endpoint->subscription.allow) {
2544 ast_log(LOG_WARNING, "Subscriptions not permitted for endpoint %s.\n", ast_sorcery_object_get_id(endpoint));
2545 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 603, NULL, NULL, NULL);
2549 request_uri = rdata->msg_info.msg->line.req.uri;
2551 if (!PJSIP_URI_SCHEME_IS_SIP(request_uri) && !PJSIP_URI_SCHEME_IS_SIPS(request_uri)) {
2552 char uri_str[PJSIP_MAX_URL_SIZE];
2554 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, request_uri, uri_str, sizeof(uri_str));
2555 ast_log(LOG_WARNING, "Request URI '%s' is not a sip: or sips: URI.\n", uri_str);
2556 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
2560 request_uri_sip = pjsip_uri_get_uri(request_uri);
2561 resource_size = pj_strlen(&request_uri_sip->user) + 1;
2562 resource = alloca(resource_size);
2563 ast_copy_pj_str(resource, &request_uri_sip->user, resource_size);
2565 expires_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, rdata->msg_info.msg->hdr.next);
2567 if (expires_header) {
2568 if (expires_header->ivalue == 0) {
2569 ast_log(LOG_WARNING, "Subscription request from endpoint %s rejected. Expiration of 0 is invalid\n",
2570 ast_sorcery_object_get_id(endpoint));
2571 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 400, NULL, NULL, NULL);
2574 if (expires_header->ivalue < endpoint->subscription.minexpiry) {
2575 ast_log(LOG_WARNING, "Subscription expiration %d is too brief for endpoint %s. Minimum is %u\n",
2576 expires_header->ivalue, ast_sorcery_object_get_id(endpoint), endpoint->subscription.minexpiry);
2577 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 423, NULL, NULL, NULL);
2582 handler = subscription_get_handler_from_rdata(rdata);
2584 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2588 generator = subscription_get_generator_from_rdata(rdata, handler);
2590 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2594 memset(&tree, 0, sizeof(tree));
2595 resp = build_resource_tree(endpoint, handler, resource, &tree,
2596 ast_sip_pubsub_has_eventlist_support(rdata));
2597 if (!PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
2598 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);
2599 resource_tree_destroy(&tree);
2603 sub_tree = create_subscription_tree(handler, endpoint, rdata, resource, generator, &tree, &dlg_status);
2605 if (dlg_status != PJ_EEXISTS) {
2606 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
2609 sub_tree->persistence = subscription_persistence_create(sub_tree);
2610 subscription_persistence_update(sub_tree, rdata);
2611 sip_subscription_accept(sub_tree, rdata, resp);
2612 if (generate_initial_notify(sub_tree->root)) {
2613 pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
2615 send_notify(sub_tree, 1);
2616 ast_test_suite_event_notify("SUBSCRIPTION_ESTABLISHED",
2618 sub_tree->root->resource);
2622 resource_tree_destroy(&tree);
2626 static struct ast_sip_publish_handler *find_pub_handler(const char *event)
2628 struct ast_sip_publish_handler *iter = NULL;
2629 SCOPED_LOCK(lock, &publish_handlers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
2631 AST_RWLIST_TRAVERSE(&publish_handlers, iter, next) {
2632 if (strcmp(event, iter->event_name)) {
2633 ast_debug(3, "Event %s does not match %s\n", event, iter->event_name);
2636 ast_debug(3, "Event name match: %s = %s\n", event, iter->event_name);
2643 static enum sip_publish_type determine_sip_publish_type(pjsip_rx_data *rdata,
2644 pjsip_generic_string_hdr *etag_hdr, int *expires, int *entity_id)
2646 pjsip_expires_hdr *expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
2649 char etag[pj_strlen(&etag_hdr->hvalue) + 1];
2651 ast_copy_pj_str(etag, &etag_hdr->hvalue, sizeof(etag));
2653 if (sscanf(etag, "%30d", entity_id) != 1) {
2654 return SIP_PUBLISH_UNKNOWN;
2658 *expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
2661 return SIP_PUBLISH_REMOVE;
2662 } else if (!etag_hdr && rdata->msg_info.msg->body) {
2663 return SIP_PUBLISH_INITIAL;
2664 } else if (etag_hdr && !rdata->msg_info.msg->body) {
2665 return SIP_PUBLISH_REFRESH;
2666 } else if (etag_hdr && rdata->msg_info.msg->body) {
2667 return SIP_PUBLISH_MODIFY;
2670 return SIP_PUBLISH_UNKNOWN;
2673 /*! \brief Internal destructor for publications */
2674 static void publication_destroy_fn(void *obj)
2676 struct ast_sip_publication *publication = obj;
2678 ast_debug(3, "Destroying SIP publication\n");
2680 ao2_cleanup(publication->datastores);
2681 ao2_cleanup(publication->endpoint);
2684 static struct ast_sip_publication *sip_create_publication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata,
2685 const char *resource, const char *event_configuration_name)
2687 struct ast_sip_publication *publication;
2688 pjsip_expires_hdr *expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
2689 size_t resource_len = strlen(resource) + 1, event_configuration_name_len = strlen(event_configuration_name) + 1;
2692 ast_assert(endpoint != NULL);
2694 if (!(publication = ao2_alloc(sizeof(*publication) + resource_len + event_configuration_name_len, publication_destroy_fn))) {
2698 if (!(publication->datastores = ao2_container_alloc(DATASTORE_BUCKETS, datastore_hash, datastore_cmp))) {
2699 ao2_ref(publication, -1);
2703 publication->entity_tag = ast_atomic_fetchadd_int(&esc_etag_counter, +1);
2704 ao2_ref(endpoint, +1);
2705 publication->endpoint = endpoint;
2706 publication->expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
2707 publication->sched_id = -1;
2708 dst = publication->data;
2709 publication->resource = strcpy(dst, resource);
2710 dst += resource_len;
2711 publication->event_configuration_name = strcpy(dst, event_configuration_name);
2716 static int sip_publication_respond(struct ast_sip_publication *pub, int status_code,
2717 pjsip_rx_data *rdata)
2720 pjsip_tx_data *tdata;
2721 pjsip_transaction *tsx;
2723 if (pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, status_code, NULL, &tdata) != PJ_SUCCESS) {
2727 if (PJSIP_IS_STATUS_IN_CLASS(status_code, 200)) {
2728 RAII_VAR(char *, entity_tag, NULL, ast_free_ptr);
2729 RAII_VAR(char *, expires, NULL, ast_free_ptr);
2731 if ((ast_asprintf(&entity_tag, "%d", pub->entity_tag) < 0) ||
2732 (ast_asprintf(&expires, "%d", pub->expires) < 0)) {
2733 pjsip_tx_data_dec_ref(tdata);
2737 ast_sip_add_header(tdata, "SIP-ETag", entity_tag);
2738 ast_sip_add_header(tdata, "Expires", expires);
2741 if ((status = pjsip_tsx_create_uas(&pubsub_module, rdata, &tsx)) != PJ_SUCCESS) {
2745 pjsip_tsx_recv_msg(tsx, rdata);
2747 if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
2754 static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata,
2755 struct ast_sip_publish_handler *handler)
2757 struct ast_sip_publication *publication;
2758 char *resource_name;
2759 size_t resource_size;
2760 RAII_VAR(struct ast_sip_publication_resource *, resource, NULL, ao2_cleanup);
2761 struct ast_variable *event_configuration_name = NULL;
2762 pjsip_uri *request_uri;
2763 pjsip_sip_uri *request_uri_sip;
2766 request_uri = rdata->msg_info.msg->line.req.uri;
2768 if (!PJSIP_URI_SCHEME_IS_SIP(request_uri) && !PJSIP_URI_SCHEME_IS_SIPS(request_uri)) {
2769 char uri_str[PJSIP_MAX_URL_SIZE];
2771 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, request_uri, uri_str, sizeof(uri_str));
2772 ast_log(LOG_WARNING, "Request URI '%s' is not a sip: or sips: URI.\n", uri_str);
2773 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
2777 request_uri_sip = pjsip_uri_get_uri(request_uri);
2778 resource_size = pj_strlen(&request_uri_sip->user) + 1;
2779 resource_name = alloca(resource_size);
2780 ast_copy_pj_str(resource_name, &request_uri_sip->user, resource_size);
2782 resource = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "inbound-publication", resource_name);
2784 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
2788 if (!ast_strlen_zero(resource->endpoint) && strcmp(resource->endpoint, ast_sorcery_object_get_id(endpoint))) {
2789 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
2793 for (event_configuration_name = resource->events; event_configuration_name; event_configuration_name = event_configuration_name->next) {
2794 if (!strcmp(event_configuration_name->name, handler->event_name)) {
2799 if (!event_configuration_name) {
2800 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
2804 resp = handler->new_publication(endpoint, resource_name, event_configuration_name->value);
2806 if (!PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
2807 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);
2811 publication = sip_create_publication(endpoint, rdata, S_OR(resource_name, ""), event_configuration_name->value);
2814 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 503, NULL, NULL, NULL);
2818 publication->handler = handler;
2819 if (publication->handler->publication_state_change(publication, rdata->msg_info.msg->body,
2820 AST_SIP_PUBLISH_STATE_INITIALIZED)) {
2821 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
2822 ao2_cleanup(publication);
2826 sip_publication_respond(publication, resp, rdata);
2831 static int publish_expire_callback(void *data)
2833 RAII_VAR(struct ast_sip_publication *, publication, data, ao2_cleanup);
2835 if (publication->handler->publish_expire) {
2836 publication->handler->publish_expire(publication);
2842 static int publish_expire(const void *data)
2844 struct ast_sip_publication *publication = (struct ast_sip_publication*)data;
2846 ao2_unlink(publication->handler->publications, publication);
2847 publication->sched_id = -1;
2849 if (ast_sip_push_task(NULL, publish_expire_callback, publication)) {
2850 ao2_cleanup(publication);
2856 static pj_bool_t pubsub_on_rx_publish_request(pjsip_rx_data *rdata)
2858 pjsip_event_hdr *event_header;
2859 struct ast_sip_publish_handler *handler;
2860 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2862 static const pj_str_t str_sip_if_match = { "SIP-If-Match", 12 };
2863 pjsip_generic_string_hdr *etag_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_sip_if_match, NULL);
2864 enum sip_publish_type publish_type;
2865 RAII_VAR(struct ast_sip_publication *, publication, NULL, ao2_cleanup);
2866 int expires = 0, entity_id, response = 0;
2868 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2869 ast_assert(endpoint != NULL);
2871 event_header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_event_name, rdata->msg_info.msg->hdr.next);
2872 if (!event_header) {
2873 ast_log(LOG_WARNING, "Incoming PUBLISH request with no Event header\n");
2874 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2877 ast_copy_pj_str(event, &event_header->event_type, sizeof(event));
2879 handler = find_pub_handler(event);
2881 ast_log(LOG_WARNING, "No registered publish handler for event %s\n", event);
2882 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2886 publish_type = determine_sip_publish_type(rdata, etag_hdr, &expires, &entity_id);
2888 /* If this is not an initial publish ensure that a publication is present */
2889 if ((publish_type != SIP_PUBLISH_INITIAL) && (publish_type != SIP_PUBLISH_UNKNOWN)) {
2890 if (!(publication = ao2_find(handler->publications, &entity_id, OBJ_KEY | OBJ_UNLINK))) {
2891 static const pj_str_t str_conditional_request_failed = { "Conditional Request Failed", 26 };
2893 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 412, &str_conditional_request_failed,
2898 /* Per the RFC every response has to have a new entity tag */
2899 publication->entity_tag = ast_atomic_fetchadd_int(&esc_etag_counter, +1);
2901 /* Update the expires here so that the created responses will contain the correct value */
2902 publication->expires = expires;
2905 switch (publish_type) {
2906 case SIP_PUBLISH_INITIAL:
2907 publication = publish_request_initial(endpoint, rdata, handler);
2909 case SIP_PUBLISH_REFRESH:
2910 case SIP_PUBLISH_MODIFY:
2911 if (handler->publication_state_change(publication, rdata->msg_info.msg->body,
2912 AST_SIP_PUBLISH_STATE_ACTIVE)) {
2913 /* If an error occurs we want to terminate the publication */
2918 case SIP_PUBLISH_REMOVE:
2919 handler->publication_state_change(publication, rdata->msg_info.msg->body,
2920 AST_SIP_PUBLISH_STATE_TERMINATED);
2923 case SIP_PUBLISH_UNKNOWN:
2925 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 400, NULL, NULL, NULL);
2931 ao2_link(handler->publications, publication);
2933 AST_SCHED_REPLACE_UNREF(publication->sched_id, sched, expires * 1000, publish_expire, publication,
2934 ao2_ref(publication, -1), ao2_ref(publication, -1), ao2_ref(publication, +1));
2936 AST_SCHED_DEL_UNREF(sched, publication->sched_id, ao2_ref(publication, -1));
2941 sip_publication_respond(publication, response, rdata);
2947 struct ast_sip_endpoint *ast_sip_publication_get_endpoint(struct ast_sip_publication *pub)
2949 return pub->endpoint;
2952 const char *ast_sip_publication_get_resource(const struct ast_sip_publication *pub)
2954 return pub->resource;
2957 const char *ast_sip_publication_get_event_configuration(const struct ast_sip_publication *pub)
2959 return pub->event_configuration_name;
2962 int ast_sip_pubsub_register_body_generator(struct ast_sip_pubsub_body_generator *generator)
2964 struct ast_sip_pubsub_body_generator *existing;
2966 pj_size_t accept_len;
2968 existing = find_body_generator_type_subtype(generator->type, generator->subtype);
2970 ast_log(LOG_WARNING, "Cannot register body generator of %s/%s."
2971 "One is already registered.\n", generator->type, generator->subtype);
2975 AST_RWLIST_WRLOCK(&body_generators);
2976 AST_LIST_INSERT_HEAD(&body_generators, generator, list);
2977 AST_RWLIST_UNLOCK(&body_generators);
2979 /* Lengths of type and subtype plus space for a slash. pj_str_t is not
2980 * null-terminated, so there is no need to allocate for the extra null
2983 accept_len = strlen(generator->type) + strlen(generator->subtype) + 1;
2985 accept.ptr = alloca(accept_len);
2986 accept.slen = accept_len;
2987 /* Safe use of sprintf */
2988 sprintf(accept.ptr, "%s/%s", generator->type, generator->subtype);
2989 pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), &pubsub_module,
2990 PJSIP_H_ACCEPT, NULL, 1, &accept);
2995 void ast_sip_pubsub_unregister_body_generator(struct ast_sip_pubsub_body_generator *generator)
2997 struct ast_sip_pubsub_body_generator *iter;
2998 SCOPED_LOCK(lock, &body_generators, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
3000 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&body_generators, iter, list) {
3001 if (iter == generator) {
3002 AST_LIST_REMOVE_CURRENT(list);
3006 AST_RWLIST_TRAVERSE_SAFE_END;
3009 int ast_sip_pubsub_register_body_supplement(struct ast_sip_pubsub_body_supplement *supplement)
3011 AST_RWLIST_WRLOCK(&body_supplements);
3012 AST_RWLIST_INSERT_TAIL(&body_supplements, supplement, list);
3013 AST_RWLIST_UNLOCK(&body_supplements);
3018 void ast_sip_pubsub_unregister_body_supplement(struct ast_sip_pubsub_body_supplement *supplement)
3020 struct ast_sip_pubsub_body_supplement *iter;
3021 SCOPED_LOCK(lock, &body_supplements, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
3023 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&body_supplements, iter, list) {
3024 if (iter == supplement) {
3025 AST_LIST_REMOVE_CURRENT(list);
3029 AST_RWLIST_TRAVERSE_SAFE_END;
3032 const char *ast_sip_subscription_get_body_type(struct ast_sip_subscription *sub)
3034 return sub->body_generator->type;
3037 const char *ast_sip_subscription_get_body_subtype(struct ast_sip_subscription *sub)
3039 return sub->body_generator->subtype;
3042 int ast_sip_pubsub_generate_body_content(const char *type, const char *subtype,
3043 struct ast_sip_body_data *data, struct ast_str **str)
3045 struct ast_sip_pubsub_body_supplement *supplement;
3046 struct ast_sip_pubsub_body_generator *generator;
3050 generator = find_body_generator_type_subtype(type, subtype);
3052 ast_log(LOG_WARNING, "Unable to find a body generator for %s/%s\n",
3057 if (strcmp(data->body_type, generator->body_type)) {
3058 ast_log(LOG_WARNING, "Body generator does not accept the type of data provided\n");
3062 body = generator->allocate_body(data->body_data);
3064 ast_log(LOG_WARNING, "Unable to allocate a NOTIFY body of type %s/%s\n",
3069 if (generator->generate_body_content(body, data->body_data)) {
3074 AST_RWLIST_RDLOCK(&body_supplements);
3075 AST_RWLIST_TRAVERSE(&body_supplements, supplement, list) {
3076 if (!strcmp(generator->type, supplement->type) &&
3077 !strcmp(generator->subtype, supplement->subtype)) {
3078 res = supplement->supplement_body(body, data->body_data);
3084 AST_RWLIST_UNLOCK(&body_supplements);
3087 generator->to_string(body, str);
3091 if (generator->destroy_body) {
3092 generator->destroy_body(body);
3098 static pj_bool_t pubsub_on_rx_request(pjsip_rx_data *rdata)
3100 if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_subscribe_method())) {
3101 return pubsub_on_rx_subscribe_request(rdata);
3102 } else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_publish_method)) {
3103 return pubsub_on_rx_publish_request(rdata);
3109 static void pubsub_on_evsub_state(pjsip_evsub *evsub, pjsip_event *event)
3111 struct sip_subscription_tree *sub_tree;
3113 if (pjsip_evsub_get_state(evsub) != PJSIP_EVSUB_STATE_TERMINATED) {
3117 sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3122 ao2_cleanup(sub_tree);
3124 pjsip_evsub_set_mod_data(evsub, pubsub_module.id, NULL);
3127 static void set_state_terminated(struct ast_sip_subscription *sub)
3131 sub->subscription_state = PJSIP_EVSUB_STATE_TERMINATED;
3132 for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
3133 set_state_terminated(AST_VECTOR_GET(&sub->children, i));
3137 static void pubsub_on_rx_refresh(pjsip_evsub *evsub, pjsip_rx_data *rdata,
3138 int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body)
3140 struct sip_subscription_tree *sub_tree;
3142 sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3147 /* If sending a NOTIFY to terminate a subscription, then pubsub_on_evsub_state()
3148 * will be called when we send the NOTIFY, and that will result in dropping the
3149 * refcount of sub_tree by one, and possibly destroying the sub_tree. We need to
3150 * hold a reference to the sub_tree until this function returns so that we don't
3151 * try to read from or write to freed memory by accident
3153 ao2_ref(sub_tree, +1);
3155 if (pjsip_evsub_get_state(evsub) == PJSIP_EVSUB_STATE_TERMINATED) {
3156 set_state_terminated(sub_tree->root);
3159 if (send_notify(sub_tree, 1)) {
3163 ast_test_suite_event_notify(sub_tree->root->subscription_state == PJSIP_EVSUB_STATE_TERMINATED ?
3164 "SUBSCRIPTION_TERMINATED" : "SUBSCRIPTION_REFRESHED",
3165 "Resource: %s", sub_tree->root->resource);
3167 if (sub_tree->is_list) {
3168 pj_list_insert_before(res_hdr, create_require_eventlist(rdata->tp_info.pool));
3171 ao2_ref(sub_tree, -1);
3174 static void pubsub_on_rx_notify(pjsip_evsub *evsub, pjsip_rx_data *rdata, int *p_st_code,
3175 pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body)
3177 struct ast_sip_subscription *sub = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3183 sub->handler->subscriber->state_change(sub, rdata->msg_info.msg->body,
3184 pjsip_evsub_get_state(evsub));
3187 static int serialized_pubsub_on_client_refresh(void *userdata)
3189 struct sip_subscription_tree *sub_tree = userdata;
3190 pjsip_tx_data *tdata;
3192 if (pjsip_evsub_initiate(sub_tree->evsub, NULL, -1, &tdata) == PJ_SUCCESS) {
3193 pjsip_evsub_send_request(sub_tree->evsub, tdata);
3195 pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
3197 ao2_cleanup(sub_tree);
3201 static void pubsub_on_client_refresh(pjsip_evsub *evsub)
3203 struct sip_subscription_tree *sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3205 ao2_ref(sub_tree, +1);
3206 ast_sip_push_task(sub_tree->serializer, serialized_pubsub_on_client_refresh, sub_tree);
3209 static int serialized_pubsub_on_server_timeout(void *userdata)
3211 struct sip_subscription_tree *sub_tree = userdata;
3213 set_state_terminated(sub_tree->root);
3214 send_notify(sub_tree, 1);
3215 ast_test_suite_event_notify("SUBSCRIPTION_TERMINATED",
3217 sub_tree->root->resource);
3219 ao2_cleanup(sub_tree);
3223 static void pubsub_on_server_timeout(pjsip_evsub *evsub)
3225 struct sip_subscription_tree *sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3228 /* if a subscription has been terminated and the subscription
3229 timeout/expires is less than the time it takes for all pending
3230 transactions to end then the subscription timer will not have
3231 been canceled yet and sub will be null, so do nothing since
3232 the subscription has already been terminated. */
3236 ao2_ref(sub_tree, +1);
3237 ast_sip_push_task(sub_tree->serializer, serialized_pubsub_on_server_timeout, sub_tree);
3240 static int ami_subscription_detail(struct sip_subscription_tree *sub_tree,
3241 struct ast_sip_ami *ami,
3244 struct ast_str *buf;
3246 buf = ast_sip_create_ami_event(event, ami);
3251 sip_subscription_to_ami(sub_tree, &buf);
3252 astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));