f9b64f85fe67d29f57799d50844fd093ab493da1
[asterisk/asterisk.git] / res / res_pjsip_pubsub.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Mark Michelson <mmichelson@digium.com>
7  *
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.
13  *
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.
17  */
18 /*!
19  * \brief Opaque structure representing an RFC 3265 SIP subscription
20  */
21
22 /*** MODULEINFO
23         <depend>pjproject</depend>
24         <depend>res_pjsip</depend>
25         <support_level>core</support_level>
26  ***/
27
28 #include "asterisk.h"
29
30 #include <pjsip.h>
31 #include <pjsip_simple.h>
32 #include <pjlib.h>
33
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"
48
49 /*** DOCUMENTATION
50         <manager name="PJSIPShowSubscriptionsInbound" language="en_US">
51                 <synopsis>
52                         Lists subscriptions.
53                 </synopsis>
54                 <syntax />
55                 <description>
56                         <para>
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.
60                         </para>
61                 </description>
62         </manager>
63         <manager name="PJSIPShowSubscriptionsOutbound" language="en_US">
64                 <synopsis>
65                         Lists subscriptions.
66                 </synopsis>
67                 <syntax />
68                 <description>
69                         <para>
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.
73                         </para>
74                 </description>
75         </manager>
76         <manager name="PJSIPShowResourceLists" language="en_US">
77                 <synopsis>
78                         Displays settings for configured resource lists.
79                 </synopsis>
80                 <syntax />
81                 <description>
82                         <para>
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.
86                         </para>
87                 </description>
88         </manager>
89
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>
97                                 </configOption>
98                                 <configOption name="src_name">
99                                         <synopsis>The source address of the subscription</synopsis>
100                                 </configOption>
101                                 <configOption name="src_port">
102                                         <synopsis>The source port of the subscription</synopsis>
103                                 </configOption>
104                                 <configOption name="transport_key">
105                                         <synopsis>The type of transport the subscription was received on</synopsis>
106                                 </configOption>
107                                 <configOption name="local_name">
108                                         <synopsis>The local address the subscription was received on</synopsis>
109                                 </configOption>
110                                 <configOption name="local_port">
111                                         <synopsis>The local port the subscription was received on</synopsis>
112                                 </configOption>
113                                 <configOption name="cseq">
114                                         <synopsis>The sequence number of the next NOTIFY to be sent</synopsis>
115                                 </configOption>
116                                 <configOption name="tag">
117                                         <synopsis>The local tag of the dialog for the subscription</synopsis>
118                                 </configOption>
119                                 <configOption name="endpoint">
120                                         <synopsis>The name of the endpoint that subscribed</synopsis>
121                                 </configOption>
122                                 <configOption name="expires">
123                                         <synopsis>The time at which the subscription expires</synopsis>
124                                 </configOption>
125                         </configObject>
126                         <configObject name="resource_list">
127                                 <synopsis>Resource list configuration parameters.</synopsis>
128                                 <configOption name="type">
129                                         <synopsis>Must be of type 'resource_list'</synopsis>
130                                 </configOption>
131                                 <configOption name="event">
132                                         <synopsis>The SIP event package that the list resource belong to.</synopsis>
133                                         <description><para>
134                                                 The SIP event package describes the types of resources that Asterisk reports
135                                                 the state of.
136                                         </para>
137                                                 <enumlist>
138                                                         <enum name="presence"><para>
139                                                                 Device state and presence reporting.
140                                                         </para></enum>
141                                                         <enum name="message-summary"><para>
142                                                                 Message-waiting indication (MWI) reporting.
143                                                         </para></enum>
144                                                 </enumlist>
145                                         </description>
146                                 </configOption>
147                                 <configOption name="list_item">
148                                         <synopsis>The name of a resource to report state on</synopsis>
149                                         <description>
150                                                 <para>In general Asterisk looks up list items in the following way:</para>
151                                                 <para>1. Check if the list item refers to another configured resource list.</para>
152                                                 <para>2. Pass the name of the resource off to event-package-specific handlers
153                                                    to find the specified resource.</para>
154                                                 <para>The second part means that the way the list item is specified depends
155                                                 on what type of list this is. For instance, if you have the <replaceable>event</replaceable>
156                                                 set to <literal>presence</literal>, then list items should be in the form of
157                                                 dialplan_extension@dialplan_context. For <literal>message-summary</literal> mailbox
158                                                 names should be listed.</para>
159                                         </description>
160                                 </configOption>
161                                 <configOption name="full_state" default="no">
162                                         <synopsis>Indicates if the entire list's state should be sent out.</synopsis>
163                                         <description>
164                                                 <para>If this option is enabled, and a resource changes state, then Asterisk will construct
165                                                 a notification that contains the state of all resources in the list. If the option is
166                                                 disabled, Asterisk will construct a notification that only contains the states of
167                                                 resources that have changed.</para>
168                                                 <note>
169                                                         <para>Even with this option disabled, there are certain situations where Asterisk is forced
170                                                         to send a notification with the states of all resources in the list. When a subscriber
171                                                         renews or terminates its subscription to the list, Asterisk MUST send a full state
172                                                         notification.</para>
173                                                 </note>
174                                         </description>
175                                 </configOption>
176                                 <configOption name="notification_batch_interval" default="0">
177                                         <synopsis>Time Asterisk should wait, in milliseconds, before sending notifications.</synopsis>
178                                         <description>
179                                                 <para>When a resource's state changes, it may be desired to wait a certain amount before Asterisk
180                                                 sends a notification to subscribers. This allows for other state changes to accumulate, so that
181                                                 Asterisk can communicate multiple state changes in a single notification instead of rapidly sending
182                                                 many notifications.</para>
183                                         </description>
184                                 </configOption>
185                         </configObject>
186                         <configObject name="inbound-publication">
187                                 <synopsis>The configuration for inbound publications</synopsis>
188                                 <configOption name="endpoint" default="">
189                                         <synopsis>Optional name of an endpoint that is only allowed to publish to this resource</synopsis>
190                                 </configOption>
191                                 <configOption name="type">
192                                         <synopsis>Must be of type 'inbound-publication'.</synopsis>
193                                 </configOption>
194                         </configObject>
195                 </configFile>
196         </configInfo>
197  ***/
198
199 static pj_bool_t pubsub_on_rx_request(pjsip_rx_data *rdata);
200
201 static struct pjsip_module pubsub_module = {
202         .name = { "PubSub Module", 13 },
203         .priority = PJSIP_MOD_PRIORITY_APPLICATION,
204         .on_rx_request = pubsub_on_rx_request,
205 };
206
207 #define MOD_DATA_PERSISTENCE "sub_persistence"
208 #define MOD_DATA_MSG "sub_msg"
209
210 static const pj_str_t str_event_name = { "Event", 5 };
211
212 /*! \brief Scheduler used for automatically expiring publications */
213 static struct ast_sched_context *sched;
214
215 /*! \brief Number of buckets for publications (on a per handler) */
216 #define PUBLICATIONS_BUCKETS 37
217
218 /*! \brief Default expiration time for PUBLISH if one is not specified */
219 #define DEFAULT_PUBLISH_EXPIRES 3600
220
221 /*! \brief Number of buckets for subscription datastore */
222 #define DATASTORE_BUCKETS 53
223
224 /*! \brief Default expiration for subscriptions */
225 #define DEFAULT_EXPIRES 3600
226
227 /*! \brief Defined method for PUBLISH */
228 const pjsip_method pjsip_publish_method =
229 {
230         PJSIP_OTHER_METHOD,
231         { "PUBLISH", 7 }
232 };
233
234 /*!
235  * \brief The types of PUBLISH messages defined in RFC 3903
236  */
237 enum sip_publish_type {
238         /*!
239          * \brief Unknown
240          *
241          * \details
242          * This actually is not defined in RFC 3903. We use this as a constant
243          * to indicate that an incoming PUBLISH does not fit into any of the
244          * other categories and is thus invalid.
245          */
246         SIP_PUBLISH_UNKNOWN,
247
248         /*!
249          * \brief Initial
250          *
251          * \details
252          * The first PUBLISH sent. This will contain a non-zero Expires header
253          * as well as a body that indicates the current state of the endpoint
254          * that has sent the message. The initial PUBLISH is the only type
255          * of PUBLISH to not contain a Sip-If-Match header in it.
256          */
257         SIP_PUBLISH_INITIAL,
258
259         /*!
260          * \brief Refresh
261          *
262          * \details
263          * Used to keep a published state from expiring. This will contain a
264          * non-zero Expires header but no body since its purpose is not to
265          * update state.
266          */
267         SIP_PUBLISH_REFRESH,
268
269         /*!
270          * \brief Modify
271          *
272          * \details
273          * Used to change state from its previous value. This will contain
274          * a body updating the published state. May or may not contain an
275          * Expires header.
276          */
277         SIP_PUBLISH_MODIFY,
278
279         /*!
280          * \brief Remove
281          *
282          * \details
283          * Used to remove published state from an ESC. This will contain
284          * an Expires header set to 0 and likely no body.
285          */
286         SIP_PUBLISH_REMOVE,
287 };
288
289 /*!
290  * \brief A vector of strings commonly used throughout this module
291  */
292 AST_VECTOR(resources, const char *);
293
294 /*!
295  * \brief Resource list configuration item
296  */
297 struct resource_list {
298         SORCERY_OBJECT(details);
299         /*! SIP event package the list uses. */
300         char event[32];
301         /*! Strings representing resources in the list. */
302         struct resources items;
303         /*! Indicates if Asterisk sends full or partial state on notifications. */
304         unsigned int full_state;
305         /*! Time, in milliseconds Asterisk waits before sending a batched notification.*/
306         unsigned int notification_batch_interval;
307 };
308
309 /*!
310  * Used to create new entity IDs by ESCs.
311  */
312 static int esc_etag_counter;
313
314 /*!
315  * \brief Structure representing a SIP publication
316  */
317 struct ast_sip_publication {
318         /*! Publication datastores set up by handlers */
319         struct ao2_container *datastores;
320         /*! \brief Entity tag for the publication */
321         int entity_tag;
322         /*! \brief Handler for this publication */
323         struct ast_sip_publish_handler *handler;
324         /*! \brief The endpoint with which the subscription is communicating */
325         struct ast_sip_endpoint *endpoint;
326         /*! \brief Expiration time of the publication */
327         int expires;
328         /*! \brief Scheduled item for expiration of publication */
329         int sched_id;
330         /*! \brief The resource the publication is to */
331         char *resource;
332         /*! \brief The name of the event type configuration */
333         char *event_configuration_name;
334         /*! \brief Data containing the above */
335         char data[0];
336 };
337
338
339 /*!
340  * \brief Structure used for persisting an inbound subscription
341  */
342 struct subscription_persistence {
343         /*! Sorcery object details */
344         SORCERY_OBJECT(details);
345         /*! The name of the endpoint involved in the subscrption */
346         char *endpoint;
347         /*! SIP message that creates the subscription */
348         char packet[PJSIP_MAX_PKT_LEN];
349         /*! Source address of the message */
350         char src_name[PJ_INET6_ADDRSTRLEN];
351         /*! Source port of the message */
352         int src_port;
353         /*! Local transport key type */
354         char transport_key[32];
355         /*! Local transport address */
356         char local_name[PJ_INET6_ADDRSTRLEN];
357         /*! Local transport port */
358         int local_port;
359         /*! Next CSeq to use for message */
360         unsigned int cseq;
361         /*! Local tag of the dialog */
362         char *tag;
363         /*! When this subscription expires */
364         struct timeval expires;
365 };
366
367 /*!
368  * \brief A tree of SIP subscriptions
369  *
370  * Because of the ability to subscribe to resource lists, a SIP
371  * subscription can result in a tree of subscriptions being created.
372  * This structure represents the information relevant to the subscription
373  * as a whole, to include the underlying PJSIP structure for the
374  * subscription.
375  */
376 struct sip_subscription_tree {
377         /*! The endpoint with which the subscription is communicating */
378         struct ast_sip_endpoint *endpoint;
379         /*! Serializer on which to place operations for this subscription */
380         struct ast_taskprocessor *serializer;
381         /*! The role for this subscription */
382         enum ast_sip_subscription_role role;
383         /*! Persistence information */
384         struct subscription_persistence *persistence;
385         /*! The underlying PJSIP event subscription structure */
386         pjsip_evsub *evsub;
387         /*! The underlying PJSIP dialog */
388         pjsip_dialog *dlg;
389         /*! Interval to use for batching notifications */
390         unsigned int notification_batch_interval;
391         /*! Scheduler ID for batched notification */
392         int notify_sched_id;
393         /*! Indicator if scheduled batched notification should be sent */
394         unsigned int send_scheduled_notify;
395         /*! The root of the subscription tree */
396         struct ast_sip_subscription *root;
397         /*! Is this subscription to a list? */
398         int is_list;
399         /*! Next item in the list */
400         AST_LIST_ENTRY(sip_subscription_tree) next;
401 };
402
403 /*!
404  * \brief Structure representing a "virtual" SIP subscription.
405  *
406  * This structure serves a dual purpose. Structurally, it is
407  * the constructed tree of subscriptions based on the resources
408  * being subscribed to. API-wise, this serves as the handle that
409  * subscription handlers use in order to interact with the pubsub API.
410  */
411 struct ast_sip_subscription {
412         /*! Subscription datastores set up by handlers */
413         struct ao2_container *datastores;
414         /*! The handler for this subscription */
415         const struct ast_sip_subscription_handler *handler;
416         /*! Pointer to the base of the tree */
417         struct sip_subscription_tree *tree;
418         /*! Body generaator for NOTIFYs */
419         struct ast_sip_pubsub_body_generator *body_generator;
420         /*! Vector of child subscriptions */
421         AST_VECTOR(, struct ast_sip_subscription *) children;
422         /*! Saved NOTIFY body text for this subscription */
423         struct ast_str *body_text;
424         /*! Indicator that the body text has changed since the last notification */
425         int body_changed;
426         /*! The current state of the subscription */
427         pjsip_evsub_state subscription_state;
428         /*! For lists, the current version to place in the RLMI body */
429         unsigned int version;
430         /*! For lists, indicates if full state should always be communicated. */
431         unsigned int full_state;
432         /*! URI associated with the subscription */
433         pjsip_sip_uri *uri;
434         /*! Name of resource being subscribed to */
435         char resource[0];
436 };
437
438 /*!
439  * \brief Structure representing a publication resource
440  */
441 struct ast_sip_publication_resource {
442         /*! \brief Sorcery object details */
443         SORCERY_OBJECT(details);
444         /*! \brief Optional name of an endpoint that is only allowed to publish to this resource */
445         char *endpoint;
446         /*! \brief Mapping for event types to configuration */
447         struct ast_variable *events;
448 };
449
450 static const char *sip_subscription_roles_map[] = {
451         [AST_SIP_SUBSCRIBER] = "Subscriber",
452         [AST_SIP_NOTIFIER] = "Notifier"
453 };
454
455 AST_RWLIST_HEAD_STATIC(subscriptions, sip_subscription_tree);
456
457 AST_RWLIST_HEAD_STATIC(body_generators, ast_sip_pubsub_body_generator);
458 AST_RWLIST_HEAD_STATIC(body_supplements, ast_sip_pubsub_body_supplement);
459
460 static void pubsub_on_evsub_state(pjsip_evsub *sub, pjsip_event *event);
461 static void pubsub_on_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata,
462                 int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body);
463 static void pubsub_on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code,
464                 pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body);
465 static void pubsub_on_client_refresh(pjsip_evsub *sub);
466 static void pubsub_on_server_timeout(pjsip_evsub *sub);
467  
468 static pjsip_evsub_user pubsub_cb = {
469         .on_evsub_state = pubsub_on_evsub_state,
470         .on_rx_refresh = pubsub_on_rx_refresh,
471         .on_rx_notify = pubsub_on_rx_notify,
472         .on_client_refresh = pubsub_on_client_refresh,
473         .on_server_timeout = pubsub_on_server_timeout,
474 };
475
476 /*! \brief Destructor for publication resource */
477 static void publication_resource_destroy(void *obj)
478 {
479         struct ast_sip_publication_resource *resource = obj;
480
481         ast_free(resource->endpoint);
482         ast_variables_destroy(resource->events);
483 }
484
485 /*! \brief Allocator for publication resource */
486 static void *publication_resource_alloc(const char *name)
487 {
488         return ast_sorcery_generic_alloc(sizeof(struct ast_sip_publication_resource), publication_resource_destroy);
489 }
490
491 /*! \brief Destructor for subscription persistence */
492 static void subscription_persistence_destroy(void *obj)
493 {
494         struct subscription_persistence *persistence = obj;
495
496         ast_free(persistence->endpoint);
497         ast_free(persistence->tag);
498 }
499
500 /*! \brief Allocator for subscription persistence */
501 static void *subscription_persistence_alloc(const char *name)
502 {
503         return ast_sorcery_generic_alloc(sizeof(struct subscription_persistence), subscription_persistence_destroy);
504 }
505
506 /*! \brief Function which creates initial persistence information of a subscription in sorcery */
507 static struct subscription_persistence *subscription_persistence_create(struct sip_subscription_tree *sub_tree)
508 {
509         char tag[PJ_GUID_STRING_LENGTH + 1];
510
511         /* The id of this persistence object doesn't matter as we keep it on the subscription and don't need to
512          * look it up by id at all.
513          */
514         struct subscription_persistence *persistence = ast_sorcery_alloc(ast_sip_get_sorcery(),
515                 "subscription_persistence", NULL);
516
517         pjsip_dialog *dlg = sub_tree->dlg;
518
519         if (!persistence) {
520                 return NULL;
521         }
522
523         persistence->endpoint = ast_strdup(ast_sorcery_object_get_id(sub_tree->endpoint));
524         ast_copy_pj_str(tag, &dlg->local.info->tag, sizeof(tag));
525         persistence->tag = ast_strdup(tag);
526
527         ast_sorcery_create(ast_sip_get_sorcery(), persistence);
528         return persistence;
529 }
530
531 /*! \brief Function which updates persistence information of a subscription in sorcery */
532 static void subscription_persistence_update(struct sip_subscription_tree *sub_tree,
533         pjsip_rx_data *rdata)
534 {
535         pjsip_dialog *dlg;
536
537         if (!sub_tree->persistence) {
538                 return;
539         }
540
541         dlg = sub_tree->dlg;
542         sub_tree->persistence->cseq = dlg->local.cseq;
543
544         if (rdata) {
545                 int expires;
546                 pjsip_expires_hdr *expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
547
548                 expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
549                 sub_tree->persistence->expires = ast_tvadd(ast_tvnow(), ast_samp2tv(expires, 1));
550
551                 ast_copy_string(sub_tree->persistence->packet, rdata->pkt_info.packet,
552                                 sizeof(sub_tree->persistence->packet));
553                 ast_copy_string(sub_tree->persistence->src_name, rdata->pkt_info.src_name,
554                                 sizeof(sub_tree->persistence->src_name));
555                 sub_tree->persistence->src_port = rdata->pkt_info.src_port;
556                 ast_copy_string(sub_tree->persistence->transport_key, rdata->tp_info.transport->type_name,
557                         sizeof(sub_tree->persistence->transport_key));
558                 ast_copy_pj_str(sub_tree->persistence->local_name, &rdata->tp_info.transport->local_name.host,
559                         sizeof(sub_tree->persistence->local_name));
560                 sub_tree->persistence->local_port = rdata->tp_info.transport->local_name.port;
561         }
562
563         ast_sorcery_update(ast_sip_get_sorcery(), sub_tree->persistence);
564 }
565
566 /*! \brief Function which removes persistence of a subscription from sorcery */
567 static void subscription_persistence_remove(struct sip_subscription_tree *sub_tree)
568 {
569         if (!sub_tree->persistence) {
570                 return;
571         }
572
573         ast_sorcery_delete(ast_sip_get_sorcery(), sub_tree->persistence);
574         ao2_ref(sub_tree->persistence, -1);
575 }
576
577
578 static struct ast_sip_subscription_handler *find_sub_handler_for_event_name(const char *event_name);
579 static struct ast_sip_pubsub_body_generator *find_body_generator(char accept[AST_SIP_MAX_ACCEPT][64],
580                 size_t num_accept);
581
582 /*! \brief Retrieve a handler using the Event header of an rdata message */
583 static struct ast_sip_subscription_handler *subscription_get_handler_from_rdata(pjsip_rx_data *rdata)
584 {
585         pjsip_event_hdr *event_header;
586         char event[32];
587         struct ast_sip_subscription_handler *handler;
588
589         event_header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_event_name, rdata->msg_info.msg->hdr.next);
590         if (!event_header) {
591                 ast_log(LOG_WARNING, "Incoming SUBSCRIBE request with no Event header\n");
592                 return NULL;
593         }
594         ast_copy_pj_str(event, &event_header->event_type, sizeof(event));
595
596         handler = find_sub_handler_for_event_name(event);
597         if (!handler) {
598                 ast_log(LOG_WARNING, "No registered subscribe handler for event %s\n", event);
599         }
600
601         return handler;
602 }
603
604 /*!
605  * \brief Accept headers that are exceptions to the rule
606  *
607  * Typically, when a SUBSCRIBE arrives, we attempt to find a
608  * body generator that matches one of the Accept headers in
609  * the request. When subscribing to a single resource, this works
610  * great. However, when subscribing to a list, things work
611  * differently. Most Accept header values are fine, but there
612  * are a couple that are endemic to resource lists that need
613  * to be ignored when searching for a body generator to use
614  * for the individual resources of the subscription.
615  */
616 const char *accept_exceptions[] =  {
617         "multipart/related",
618         "application/rlmi+xml",
619 };
620
621 /*!
622  * \brief Is the Accept header from the SUBSCRIBE in the list of exceptions?
623  *
624  * \retval 1 This Accept header value is an exception to the rule.
625  * \retval 0 This Accept header is not an exception to the rule.
626  */
627 static int exceptional_accept(const pj_str_t *accept)
628 {
629         int i;
630
631         for (i = 0; i < ARRAY_LEN(accept_exceptions); ++i) {
632                 if (!pj_strcmp2(accept, accept_exceptions[i])) {
633                         return 1;
634                 }
635         }
636
637         return 0;
638 }
639
640 /*! \brief Retrieve a body generator using the Accept header of an rdata message */
641 static struct ast_sip_pubsub_body_generator *subscription_get_generator_from_rdata(pjsip_rx_data *rdata,
642         const struct ast_sip_subscription_handler *handler)
643 {
644         pjsip_accept_hdr *accept_header = (pjsip_accept_hdr *) &rdata->msg_info.msg->hdr;
645         char accept[AST_SIP_MAX_ACCEPT][64];
646         size_t num_accept_headers = 0;
647
648         while ((accept_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, accept_header->next))) {
649                 int i;
650
651                 for (i = 0; i < accept_header->count; ++i) {
652                         if (!exceptional_accept(&accept_header->values[i])) {
653                                 ast_copy_pj_str(accept[num_accept_headers], &accept_header->values[i], sizeof(accept[num_accept_headers]));
654                                 ++num_accept_headers;
655                         }
656                 }
657         }
658
659         if (num_accept_headers == 0) {
660                 /* If a SUBSCRIBE contains no Accept headers, then we must assume that
661                  * the default accept type for the event package is to be used.
662                  */
663                 ast_copy_string(accept[0], handler->notifier->default_accept, sizeof(accept[0]));
664                 num_accept_headers = 1;
665         }
666
667         return find_body_generator(accept, num_accept_headers);
668 }
669
670 struct resource_tree;
671
672 /*!
673  * \brief A node for a resource tree.
674  */
675 struct tree_node {
676         AST_VECTOR(, struct tree_node *) children;
677         unsigned int full_state;
678         char resource[0];
679 };
680
681 /*!
682  * \brief Helper function for retrieving a resource list for a given event.
683  *
684  * This will retrieve a resource list that corresponds to the resource and event provided.
685  *
686  * \param resource The name of the resource list to retrieve
687  * \param event The expected event name on the resource list
688  */
689 static struct resource_list *retrieve_resource_list(const char *resource, const char *event)
690 {
691         struct resource_list *list;
692
693         list = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "resource_list", resource);
694         if (!list) {
695                 return NULL;
696         }
697
698         if (strcmp(list->event, event)) {
699                 ast_log(LOG_WARNING, "Found resource list %s, but its event type (%s) does not match SUBSCRIBE's (%s)\n",
700                                 resource, list->event, event);
701                 ao2_cleanup(list);
702                 return NULL;
703         }
704
705         return list;
706 }
707
708 /*!
709  * \brief Allocate a tree node
710  *
711  * In addition to allocating and initializing the tree node, the node is also added
712  * to the vector of visited resources. See \ref build_resource_tree for more information
713  * on the visited resources.
714  *
715  * \param resource The name of the resource for this tree node.
716  * \param visited The vector of resources that have been visited.
717  * \param if allocating a list, indicate whether full state is requested in notifications.
718  * \retval NULL Allocation failure.
719  * \retval non-NULL The newly-allocated tree_node
720  */
721 static struct tree_node *tree_node_alloc(const char *resource, struct resources *visited, unsigned int full_state)
722 {
723         struct tree_node *node;
724
725         node = ast_calloc(1, sizeof(*node) + strlen(resource) + 1);
726         if (!node) {
727                 return NULL;
728         }
729
730         strcpy(node->resource, resource);
731         if (AST_VECTOR_INIT(&node->children, 4)) {
732                 ast_free(node);
733                 return NULL;
734         }
735         node->full_state = full_state;
736
737         if (visited) {
738                 AST_VECTOR_APPEND(visited, resource);
739         }
740         return node;
741 }
742
743 /*!
744  * \brief Destructor for a tree node
745  *
746  * This function calls recursively in order to destroy
747  * all nodes lower in the tree from the given node in
748  * addition to the node itself.
749  *
750  * \param node The node to destroy.
751  */
752 static void tree_node_destroy(struct tree_node *node)
753 {
754         int i;
755         if (!node) {
756                 return;
757         }
758
759         for (i = 0; i < AST_VECTOR_SIZE(&node->children); ++i) {
760                 tree_node_destroy(AST_VECTOR_GET(&node->children, i));
761         }
762         AST_VECTOR_FREE(&node->children);
763         ast_free(node);
764 }
765
766 /*!
767  * \brief Determine if this resource has been visited already
768  *
769  * See \ref build_resource_tree for more information
770  *
771  * \param resource The resource currently being visited
772  * \param visited The resources that have previously been visited
773  */
774 static int have_visited(const char *resource, struct resources *visited)
775 {
776         int i;
777
778         for (i = 0; i < AST_VECTOR_SIZE(visited); ++i) {
779                 if (!strcmp(resource, AST_VECTOR_GET(visited, i))) {
780                         return 1;
781                 }
782         }
783
784         return 0;
785 }
786
787 /*!
788  * \brief Build child nodes for a given parent.
789  *
790  * This iterates through the items on a resource list and creates tree nodes for each one. The
791  * tree nodes created are children of the supplied parent node. If an item in the resource
792  * list is itself a list, then this function is called recursively to provide children for
793  * the the new node.
794  *
795  * If an item in a resource list is not a list, then the supplied subscription handler is
796  * called into as if a new SUBSCRIBE for the list item were presented. The handler's response
797  * is used to determine if the node can be added to the tree or not.
798  *
799  * If a parent node ends up having no child nodes added under it, then the parent node is
800  * pruned from the tree.
801  *
802  * \param endpoint The endpoint that sent the inbound SUBSCRIBE.
803  * \param handler The subscription handler for leaf nodes in the tree.
804  * \param list The configured resource list from which the child node is being built.
805  * \param parent The parent node for these children.
806  * \param visited The resources that have already been visited.
807  */
808 static void build_node_children(struct ast_sip_endpoint *endpoint, const struct ast_sip_subscription_handler *handler,
809                 struct resource_list *list, struct tree_node *parent, struct resources *visited)
810 {
811         int i;
812
813         for (i = 0; i < AST_VECTOR_SIZE(&list->items); ++i) {
814                 struct tree_node *current;
815                 struct resource_list *child_list;
816                 const char *resource = AST_VECTOR_GET(&list->items, i);
817
818                 if (have_visited(resource, visited)) {
819                         ast_debug(1, "Already visited resource %s. Avoiding duplicate resource or potential loop.\n", resource);
820                         continue;
821                 }
822
823                 child_list = retrieve_resource_list(resource, list->event);
824                 if (!child_list) {
825                         int resp = handler->notifier->new_subscribe(endpoint, resource);
826                         if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
827                                 current = tree_node_alloc(resource, visited, 0);
828                                 if (!current) {
829                                         ast_debug(1, "Subscription to leaf resource %s was successful, but encountered"
830                                                         "allocation error afterwards\n", resource);
831                                         continue;
832                                 }
833                                 ast_debug(1, "Subscription to leaf resource %s resulted in success. Adding to parent %s\n",
834                                                 resource, parent->resource);
835                                 AST_VECTOR_APPEND(&parent->children, current);
836                         } else {
837                                 ast_debug(1, "Subscription to leaf resource %s resulted in error response %d\n",
838                                                 resource, resp);
839                         }
840                 } else {
841                         ast_debug(1, "Resource %s (child of %s) is a list\n", resource, parent->resource);
842                         current = tree_node_alloc(resource, visited, child_list->full_state);
843                         if (!current) {
844                                 ast_debug(1, "Cannot build children of resource %s due to allocation failure\n", resource);
845                                 continue;
846                         }
847                         build_node_children(endpoint, handler, child_list, current, visited);
848                         if (AST_VECTOR_SIZE(&current->children) > 0) {
849                                 ast_debug(1, "List %s had no successful children.\n", resource);
850                                 AST_VECTOR_APPEND(&parent->children, current);
851                         } else {
852                                 ast_debug(1, "List %s had successful children. Adding to parent %s\n",
853                                                 resource, parent->resource);
854                                 tree_node_destroy(current);
855                         }
856                         ao2_cleanup(child_list);
857                 }
858         }
859 }
860
861 /*!
862  * \brief A resource tree
863  *
864  * When an inbound SUBSCRIBE arrives, the resource being subscribed to may
865  * be a resource list. If this is the case, the resource list may contain resources
866  * that are themselves lists. The structure needed to hold the resources is
867  * a tree.
868  *
869  * Upon receipt of the SUBSCRIBE, the tree is built by determining if subscriptions
870  * to the individual resources in the tree would be successful or not. Any successful
871  * subscriptions result in a node in the tree being created. Any unsuccessful subscriptions
872  * result in no node being created.
873  *
874  * This tree can be seen as a bare-bones analog of the tree of ast_sip_subscriptions that
875  * will end up being created to actually carry out the duties of a SIP SUBSCRIBE dialog.
876  */
877 struct resource_tree {
878         struct tree_node *root;
879         unsigned int notification_batch_interval;
880 };
881
882 /*!
883  * \brief Destroy a resource tree.
884  *
885  * This function makes no assumptions about how the tree itself was
886  * allocated and does not attempt to free the tree itself. Callers
887  * of this function are responsible for freeing the tree.
888  *
889  * \param tree The tree to destroy.
890  */
891 static void resource_tree_destroy(struct resource_tree *tree)
892 {
893         if (tree) {
894                 tree_node_destroy(tree->root);
895         }
896 }
897
898 /*!
899  * \brief Build a resource tree
900  *
901  * This function builds a resource tree based on the requested resource in a SUBSCRIBE request.
902  *
903  * This function also creates a container that has all resources that have been visited during
904  * creation of the tree, whether those resources resulted in a tree node being created or not.
905  * Keeping this container of visited resources allows for misconfigurations such as loops in
906  * the tree or duplicated resources to be detected.
907  *
908  * \param endpoint The endpoint that sent the SUBSCRIBE request.
909  * \param handler The subscription handler for leaf nodes in the tree.
910  * \param resource The resource requested in the SUBSCRIBE request.
911  * \param tree The tree that is to be built.
912  *
913  * \retval 200-299 Successfully subscribed to at least one resource.
914  * \retval 300-699 Failure to subscribe to requested resource.
915  */
916 static int build_resource_tree(struct ast_sip_endpoint *endpoint, const struct ast_sip_subscription_handler *handler,
917                 const char *resource, struct resource_tree *tree)
918 {
919         struct resource_list *list;
920         struct resources visited;
921
922         list = retrieve_resource_list(resource, handler->event_name);
923         if (!list) {
924                 ast_debug(1, "Subscription to resource %s is not to a list\n", resource);
925                 tree->root = tree_node_alloc(resource, NULL, 0);
926                 if (!tree->root) {
927                         return 500;
928                 }
929                 return handler->notifier->new_subscribe(endpoint, resource);
930         }
931
932         ast_debug(1, "Subscription to resource %s is a list\n", resource);
933         if (AST_VECTOR_INIT(&visited, AST_VECTOR_SIZE(&list->items))) {
934                 return 500;
935         }
936
937         tree->root = tree_node_alloc(resource, &visited, list->full_state);
938         if (!tree->root) {
939                 return 500;
940         }
941
942         tree->notification_batch_interval = list->notification_batch_interval;
943
944         build_node_children(endpoint, handler, list, tree->root, &visited);
945         AST_VECTOR_FREE(&visited);
946         ao2_cleanup(list);
947
948         if (AST_VECTOR_SIZE(&tree->root->children) > 0) {
949                 return 200;
950         } else {
951                 return 500;
952         }
953 }
954
955 static int datastore_hash(const void *obj, int flags)
956 {
957         const struct ast_datastore *datastore = obj;
958         const char *uid = flags & OBJ_KEY ? obj : datastore->uid;
959
960         ast_assert(uid != NULL);
961
962         return ast_str_hash(uid);
963 }
964
965 static int datastore_cmp(void *obj, void *arg, int flags)
966 {
967         const struct ast_datastore *datastore1 = obj;
968         const struct ast_datastore *datastore2 = arg;
969         const char *uid2 = flags & OBJ_KEY ? arg : datastore2->uid;
970
971         ast_assert(datastore1->uid != NULL);
972         ast_assert(uid2 != NULL);
973
974         return strcmp(datastore1->uid, uid2) ? 0 : CMP_MATCH | CMP_STOP;
975 }
976
977 static int subscription_remove_serializer(void *obj)
978 {
979         struct sip_subscription_tree *sub_tree = obj;
980
981         /* This is why we keep the dialog on the subscription. When the subscription
982          * is destroyed, there is no guarantee that the underlying dialog is ready
983          * to be destroyed. Furthermore, there's no guarantee in the opposite direction
984          * either. The dialog could be destroyed before our subscription is. We fix
985          * this problem by keeping a reference to the dialog until it is time to
986          * destroy the subscription. We need to have the dialog available when the
987          * subscription is destroyed so that we can guarantee that our attempt to
988          * remove the serializer will be successful.
989          */
990         ast_sip_dialog_set_serializer(sub_tree->dlg, NULL);
991         pjsip_dlg_dec_session(sub_tree->dlg, &pubsub_module);
992
993         return 0;
994 }
995
996 static void add_subscription(struct sip_subscription_tree *obj)
997 {
998         SCOPED_LOCK(lock, &subscriptions, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
999         AST_RWLIST_INSERT_TAIL(&subscriptions, obj, next);
1000 }
1001
1002 static void remove_subscription(struct sip_subscription_tree *obj)
1003 {
1004         struct sip_subscription_tree *i;
1005         SCOPED_LOCK(lock, &subscriptions, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
1006         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&subscriptions, i, next) {
1007                 if (i == obj) {
1008                         AST_RWLIST_REMOVE_CURRENT(next);
1009                         ast_debug(1, "Removing subscription to resource %s from list of subscriptions\n",
1010                                         ast_sip_subscription_get_resource_name(i->root));
1011                         break;
1012                 }
1013         }
1014         AST_RWLIST_TRAVERSE_SAFE_END;
1015 }
1016
1017 static void subscription_destructor(void *obj)
1018 {
1019         struct ast_sip_subscription *sub = obj;
1020
1021         ast_debug(3, "Destroying SIP subscription to resource %s\n", sub->resource);
1022         ast_free(sub->body_text);
1023
1024         ao2_cleanup(sub->datastores);
1025 }
1026
1027 static struct ast_sip_subscription *allocate_subscription(const struct ast_sip_subscription_handler *handler,
1028                 const char *resource, struct sip_subscription_tree *tree)
1029 {
1030         struct ast_sip_subscription *sub;
1031         pjsip_sip_uri *contact_uri;
1032
1033         sub = ao2_alloc(sizeof(*sub) + strlen(resource) + 1, subscription_destructor);
1034         if (!sub) {
1035                 return NULL;
1036         }
1037         strcpy(sub->resource, resource); /* Safe */
1038
1039         sub->datastores = ao2_container_alloc(DATASTORE_BUCKETS, datastore_hash, datastore_cmp);
1040         if (!sub->datastores) {
1041                 ao2_ref(sub, -1);
1042                 return NULL;
1043         }
1044
1045         sub->body_text = ast_str_create(128);
1046         if (!sub->body_text) {
1047                 ao2_ref(sub, -1);
1048                 return NULL;
1049         }
1050
1051         sub->uri = pjsip_sip_uri_create(tree->dlg->pool, PJ_FALSE);
1052         contact_uri = pjsip_uri_get_uri(tree->dlg->local.contact->uri);
1053         pjsip_sip_uri_assign(tree->dlg->pool, sub->uri, contact_uri);
1054         pj_strdup2(tree->dlg->pool, &sub->uri->user, resource);
1055
1056         sub->handler = handler;
1057         sub->subscription_state = PJSIP_EVSUB_STATE_ACTIVE;
1058         sub->tree = tree;
1059
1060         return sub;
1061 }
1062
1063 /*!
1064  * \brief Create a tree of virtual subscriptions based on a resource tree node.
1065  *
1066  * \param handler The handler to supply to leaf subscriptions.
1067  * \param resource The requested resource for this subscription.
1068  * \param generator Body generator to use for leaf subscriptions.
1069  * \param tree The root of the subscription tree.
1070  * \param current The tree node that corresponds to the subscription being created.
1071  */
1072 static struct ast_sip_subscription *create_virtual_subscriptions(const struct ast_sip_subscription_handler *handler,
1073                 const char *resource, struct ast_sip_pubsub_body_generator *generator,
1074                 struct sip_subscription_tree *tree, struct tree_node *current)
1075 {
1076         int i;
1077         struct ast_sip_subscription *sub;
1078
1079         sub = allocate_subscription(handler, resource, tree);
1080         if (!sub) {
1081                 return NULL;
1082         }
1083
1084         sub->full_state = current->full_state;
1085         sub->body_generator = generator;
1086
1087         for (i = 0; i < AST_VECTOR_SIZE(&current->children); ++i) {
1088                 struct ast_sip_subscription *child;
1089                 struct tree_node *child_node = AST_VECTOR_GET(&current->children, i);
1090
1091                 child = create_virtual_subscriptions(handler, child_node->resource, generator,
1092                                 tree, child_node);
1093
1094                 if (!child) {
1095                         ast_debug(1, "Child subscription to resource %s could not be created\n",
1096                                         child_node->resource);
1097                         continue;
1098                 }
1099
1100                 if (AST_VECTOR_APPEND(&sub->children, child)) {
1101                         ast_debug(1, "Child subscription to resource %s could not be appended\n",
1102                                         child_node->resource);
1103                 }
1104         }
1105
1106         return sub;
1107 }
1108
1109 static void shutdown_subscriptions(struct ast_sip_subscription *sub)
1110 {
1111         int i;
1112
1113         if (AST_VECTOR_SIZE(&sub->children) > 0) {
1114                 for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
1115                         shutdown_subscriptions(AST_VECTOR_GET(&sub->children, i));
1116                         ao2_cleanup(AST_VECTOR_GET(&sub->children, i));
1117                 }
1118                 return;
1119         }
1120
1121         if (sub->handler->subscription_shutdown) {
1122                 sub->handler->subscription_shutdown(sub);
1123         }
1124 }
1125
1126 static void subscription_tree_destructor(void *obj)
1127 {
1128         struct sip_subscription_tree *sub_tree = obj;
1129
1130         remove_subscription(sub_tree);
1131
1132         subscription_persistence_remove(sub_tree);
1133         ao2_cleanup(sub_tree->endpoint);
1134
1135         if (sub_tree->dlg) {
1136                 ast_sip_push_task_synchronous(NULL, subscription_remove_serializer, sub_tree);
1137         }
1138
1139         shutdown_subscriptions(sub_tree->root);
1140         ao2_cleanup(sub_tree->root);
1141
1142         ast_taskprocessor_unreference(sub_tree->serializer);
1143         ast_module_unref(ast_module_info->self);
1144 }
1145
1146 static void subscription_setup_dialog(struct sip_subscription_tree *sub_tree, pjsip_dialog *dlg)
1147 {
1148         /* We keep a reference to the dialog until our subscription is destroyed. See
1149          * the subscription_destructor for more details
1150          */
1151         pjsip_dlg_inc_session(dlg, &pubsub_module);
1152         sub_tree->dlg = dlg;
1153         ast_sip_dialog_set_serializer(dlg, sub_tree->serializer);
1154         pjsip_evsub_set_mod_data(sub_tree->evsub, pubsub_module.id, sub_tree);
1155 }
1156
1157 static struct sip_subscription_tree *allocate_subscription_tree(struct ast_sip_endpoint *endpoint)
1158 {
1159         struct sip_subscription_tree *sub_tree;
1160
1161         sub_tree = ao2_alloc(sizeof *sub_tree, subscription_tree_destructor);
1162         if (!sub_tree) {
1163                 return NULL;
1164         }
1165
1166         ast_module_ref(ast_module_info->self);
1167
1168         sub_tree->serializer = ast_sip_create_serializer();
1169         if (!sub_tree->serializer) {
1170                 ao2_ref(sub_tree, -1);
1171                 return NULL;
1172         }
1173
1174         sub_tree->endpoint = ao2_bump(endpoint);
1175         sub_tree->notify_sched_id = -1;
1176
1177         add_subscription(sub_tree);
1178         return sub_tree;
1179 }
1180
1181 /*!
1182  * \brief Create a subscription tree based on a resource tree.
1183  *
1184  * Using the previously-determined valid resources in the provided resource tree,
1185  * a corresponding tree of ast_sip_subscriptions are created. The root of the
1186  * subscription tree is a real subscription, and the rest in the tree are
1187  * virtual subscriptions.
1188  *
1189  * \param handler The handler to use for leaf subscriptions
1190  * \param endpoint The endpoint that sent the SUBSCRIBE request
1191  * \param rdata The SUBSCRIBE content
1192  * \param resource The requested resource in the SUBSCRIBE request
1193  * \param generator The body generator to use in leaf subscriptions
1194  * \param tree The resource tree on which the subscription tree is based
1195  *
1196  * \retval NULL Could not create the subscription tree
1197  * \retval non-NULL The root of the created subscription tree
1198  */
1199
1200 static struct sip_subscription_tree *create_subscription_tree(const struct ast_sip_subscription_handler *handler,
1201                 struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *resource,
1202                 struct ast_sip_pubsub_body_generator *generator, struct resource_tree *tree)
1203 {
1204         struct sip_subscription_tree *sub_tree;
1205         pjsip_dialog *dlg;
1206         struct subscription_persistence *persistence;
1207
1208         sub_tree = allocate_subscription_tree(endpoint);
1209         if (!sub_tree) {
1210                 return NULL;
1211         }
1212
1213         dlg = ast_sip_create_dialog_uas(endpoint, rdata);
1214         if (!dlg) {
1215                 ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
1216                 ao2_ref(sub_tree, -1);
1217                 return NULL;
1218         }
1219
1220         persistence = ast_sip_mod_data_get(rdata->endpt_info.mod_data,
1221                         pubsub_module.id, MOD_DATA_PERSISTENCE);
1222         if (persistence) {
1223                 /* Update the created dialog with the persisted information */
1224                 pjsip_ua_unregister_dlg(pjsip_ua_instance(), dlg);
1225                 pj_strdup2(dlg->pool, &dlg->local.info->tag, persistence->tag);
1226                 dlg->local.tag_hval = pj_hash_calc_tolower(0, NULL, &dlg->local.info->tag);
1227                 pjsip_ua_register_dlg(pjsip_ua_instance(), dlg);
1228                 dlg->local.cseq = persistence->cseq;
1229                 dlg->remote.cseq = persistence->cseq;
1230         }
1231
1232         pjsip_evsub_create_uas(dlg, &pubsub_cb, rdata, 0, &sub_tree->evsub);
1233         subscription_setup_dialog(sub_tree, dlg);
1234
1235         ast_sip_mod_data_set(dlg->pool, dlg->mod_data, pubsub_module.id, MOD_DATA_MSG,
1236                         pjsip_msg_clone(dlg->pool, rdata->msg_info.msg));
1237
1238         sub_tree->notification_batch_interval = tree->notification_batch_interval;
1239
1240         sub_tree->root = create_virtual_subscriptions(handler, resource, generator, sub_tree, tree->root);
1241         if (AST_VECTOR_SIZE(&sub_tree->root->children) > 0) {
1242                 sub_tree->is_list = 1;
1243         }
1244
1245         return sub_tree;
1246 }
1247
1248 /*! \brief Callback function to perform the actual recreation of a subscription */
1249 static int subscription_persistence_recreate(void *obj, void *arg, int flags)
1250 {
1251         struct subscription_persistence *persistence = obj;
1252         pj_pool_t *pool = arg;
1253         pjsip_rx_data rdata = { { 0, }, };
1254         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
1255         struct sip_subscription_tree *sub_tree;
1256         struct ast_sip_pubsub_body_generator *generator;
1257         int resp;
1258         char *resource;
1259         size_t resource_size;
1260         pjsip_sip_uri *request_uri;
1261         struct resource_tree tree;
1262         pjsip_expires_hdr *expires_header;
1263         struct ast_sip_subscription_handler *handler;
1264
1265         /* If this subscription has already expired remove it */
1266         if (ast_tvdiff_ms(persistence->expires, ast_tvnow()) <= 0) {
1267                 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1268                 return 0;
1269         }
1270
1271         endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", persistence->endpoint);
1272         if (!endpoint) {
1273                 ast_log(LOG_WARNING, "A subscription for '%s' could not be recreated as the endpoint was not found\n",
1274                         persistence->endpoint);
1275                 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1276                 return 0;
1277         }
1278
1279         pj_pool_reset(pool);
1280         rdata.tp_info.pool = pool;
1281
1282         if (ast_sip_create_rdata(&rdata, persistence->packet, persistence->src_name, persistence->src_port,
1283                 persistence->transport_key, persistence->local_name, persistence->local_port)) {
1284                 ast_log(LOG_WARNING, "A subscription for '%s' could not be recreated as the message could not be parsed\n",
1285                         persistence->endpoint);
1286                 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1287                 return 0;
1288         }
1289
1290         request_uri = pjsip_uri_get_uri(rdata.msg_info.msg->line.req.uri);
1291         resource_size = pj_strlen(&request_uri->user) + 1;
1292         resource = alloca(resource_size);
1293         ast_copy_pj_str(resource, &request_uri->user, resource_size);
1294
1295         /* Update the expiration header with the new expiration */
1296         expires_header = pjsip_msg_find_hdr(rdata.msg_info.msg, PJSIP_H_EXPIRES, rdata.msg_info.msg->hdr.next);
1297         if (!expires_header) {
1298                 expires_header = pjsip_expires_hdr_create(pool, 0);
1299                 if (!expires_header) {
1300                         ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1301                         return 0;
1302                 }
1303                 pjsip_msg_add_hdr(rdata.msg_info.msg, (pjsip_hdr*)expires_header);
1304         }
1305         expires_header->ivalue = (ast_tvdiff_ms(persistence->expires, ast_tvnow()) / 1000);
1306
1307         handler = subscription_get_handler_from_rdata(&rdata);
1308         if (!handler || !handler->notifier) {
1309                 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1310                 return 0;
1311         }
1312
1313         generator = subscription_get_generator_from_rdata(&rdata, handler);
1314         if (!generator) {
1315                 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1316                 return 0;
1317         }
1318
1319         ast_sip_mod_data_set(rdata.tp_info.pool, rdata.endpt_info.mod_data,
1320                         pubsub_module.id, MOD_DATA_PERSISTENCE, persistence);
1321
1322         memset(&tree, 0, sizeof(tree));
1323         resp = build_resource_tree(endpoint, handler, resource, &tree);
1324         if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
1325                 sub_tree = create_subscription_tree(handler, endpoint, &rdata, resource, generator, &tree);
1326                 sub_tree->persistence = ao2_bump(persistence);
1327                 subscription_persistence_update(sub_tree, &rdata);
1328         } else {
1329                 ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
1330         }
1331         resource_tree_destroy(&tree);
1332
1333         return 0;
1334 }
1335
1336 /*! \brief Function which loads and recreates persisted subscriptions upon startup when the system is fully booted */
1337 static int subscription_persistence_load(void *data)
1338 {
1339         struct ao2_container *persisted_subscriptions = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
1340                 "subscription_persistence", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1341         pj_pool_t *pool;
1342
1343         pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "rtd%p", PJSIP_POOL_RDATA_LEN,
1344                 PJSIP_POOL_RDATA_INC);
1345         if (!pool) {
1346                 ast_log(LOG_WARNING, "Could not create a memory pool for recreating SIP subscriptions\n");
1347                 return 0;
1348         }
1349
1350         ao2_callback(persisted_subscriptions, OBJ_NODATA, subscription_persistence_recreate, pool);
1351
1352         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1353
1354         ao2_ref(persisted_subscriptions, -1);
1355         return 0;
1356 }
1357
1358 /*! \brief Event callback which fires subscription persistence recreation when the system is fully booted */
1359 static void subscription_persistence_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
1360 {
1361         struct ast_json_payload *payload;
1362         const char *type;
1363
1364         if (stasis_message_type(message) != ast_manager_get_generic_type()) {
1365                 return;
1366         }
1367
1368         payload = stasis_message_data(message);
1369         type = ast_json_string_get(ast_json_object_get(payload->json, "type"));
1370
1371         /* This subscription only responds to the FullyBooted event so that all modules have been loaded when we
1372          * recreate SIP subscriptions.
1373          */
1374         if (strcmp(type, "FullyBooted")) {
1375                 return;
1376         }
1377
1378         /* This has to be here so the subscription is recreated when the body generator is available */
1379         ast_sip_push_task(NULL, subscription_persistence_load, NULL);
1380
1381         /* Once the system is fully booted we don't care anymore */
1382         stasis_unsubscribe(sub);
1383 }
1384
1385 typedef int (*on_subscription_t)(struct sip_subscription_tree *sub, void *arg);
1386
1387 static int for_each_subscription(on_subscription_t on_subscription, void *arg)
1388 {
1389         int num = 0;
1390         struct sip_subscription_tree *i;
1391         SCOPED_LOCK(lock, &subscriptions, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
1392
1393         if (!on_subscription) {
1394                 return num;
1395         }
1396
1397         AST_RWLIST_TRAVERSE(&subscriptions, i, next) {
1398                 if (on_subscription(i, arg)) {
1399                         break;
1400                 }
1401                 ++num;
1402         }
1403         return num;
1404 }
1405
1406 static void sip_subscription_to_ami(struct sip_subscription_tree *sub_tree,
1407                                     struct ast_str **buf)
1408 {
1409         char str[256];
1410         struct ast_sip_endpoint_id_configuration *id = &sub_tree->endpoint->id;
1411
1412         ast_str_append(buf, 0, "Role: %s\r\n",
1413                        sip_subscription_roles_map[sub_tree->role]);
1414         ast_str_append(buf, 0, "Endpoint: %s\r\n",
1415                        ast_sorcery_object_get_id(sub_tree->endpoint));
1416
1417         ast_copy_pj_str(str, &sub_tree->dlg->call_id->id, sizeof(str));
1418         ast_str_append(buf, 0, "Callid: %s\r\n", str);
1419
1420         ast_str_append(buf, 0, "State: %s\r\n", pjsip_evsub_get_state_name(sub_tree->evsub));
1421
1422         ast_callerid_merge(str, sizeof(str),
1423                            S_COR(id->self.name.valid, id->self.name.str, NULL),
1424                            S_COR(id->self.number.valid, id->self.number.str, NULL),
1425                            "Unknown");
1426
1427         ast_str_append(buf, 0, "Callerid: %s\r\n", str);
1428
1429         /* XXX This needs to be done recursively for lists */
1430         if (sub_tree->root->handler->to_ami) {
1431                 sub_tree->root->handler->to_ami(sub_tree->root, buf);
1432         }
1433 }
1434
1435
1436 void *ast_sip_subscription_get_header(const struct ast_sip_subscription *sub, const char *header)
1437 {
1438         pjsip_dialog *dlg = sub->tree->dlg;
1439         pjsip_msg *msg = ast_sip_mod_data_get(dlg->mod_data, pubsub_module.id, MOD_DATA_MSG);
1440         pj_str_t name;
1441
1442         pj_cstr(&name, header);
1443
1444         return pjsip_msg_find_hdr_by_name(msg, &name, NULL);
1445 }
1446
1447 struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_subscription_handler *handler,
1448                 struct ast_sip_endpoint *endpoint, const char *resource)
1449 {
1450         struct ast_sip_subscription *sub;
1451         pjsip_dialog *dlg;
1452         struct ast_sip_contact *contact;
1453         pj_str_t event;
1454         pjsip_tx_data *tdata;
1455         pjsip_evsub *evsub;
1456         struct sip_subscription_tree *sub_tree = NULL;
1457
1458         sub_tree = allocate_subscription_tree(endpoint);
1459         if (!sub_tree) {
1460                 return NULL;
1461         }
1462
1463         sub = allocate_subscription(handler, resource, sub_tree);
1464         if (!sub) {
1465                 ao2_cleanup(sub_tree);
1466                 return NULL;
1467         }
1468
1469         contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);
1470         if (!contact || ast_strlen_zero(contact->uri)) {
1471                 ast_log(LOG_WARNING, "No contacts configured for endpoint %s. Unable to create SIP subsription\n",
1472                                 ast_sorcery_object_get_id(endpoint));
1473                 ao2_ref(sub_tree, -1);
1474                 ao2_cleanup(contact);
1475                 return NULL;
1476         }
1477
1478         dlg = ast_sip_create_dialog_uac(endpoint, contact->uri, NULL);
1479         ao2_cleanup(contact);
1480         if (!dlg) {
1481                 ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
1482                 ao2_ref(sub_tree, -1);
1483                 return NULL;
1484         }
1485
1486         pj_cstr(&event, handler->event_name);
1487         pjsip_evsub_create_uac(dlg, &pubsub_cb, &event, 0, &sub_tree->evsub);
1488         subscription_setup_dialog(sub_tree, dlg);
1489
1490         evsub = sub_tree->evsub;
1491
1492         if (pjsip_evsub_initiate(evsub, NULL, -1, &tdata) == PJ_SUCCESS) {
1493                 pjsip_evsub_send_request(evsub, tdata);
1494         } else {
1495                 /* pjsip_evsub_terminate will result in pubsub_on_evsub_state,
1496                  * being called and terminating the subscription. Therefore, we don't
1497                  * need to decrease the reference count of sub here.
1498                  */
1499                 pjsip_evsub_terminate(evsub, PJ_TRUE);
1500                 ao2_ref(sub_tree, -1);
1501                 return NULL;
1502         }
1503
1504         return sub;
1505 }
1506
1507 struct ast_sip_endpoint *ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
1508 {
1509         ast_assert(sub->tree->endpoint != NULL);
1510         return ao2_bump(sub->tree->endpoint);
1511 }
1512
1513 struct ast_taskprocessor *ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub)
1514 {
1515         ast_assert(sub->tree->serializer != NULL);
1516         return sub->tree->serializer;
1517 }
1518
1519 static int sip_subscription_send_request(struct sip_subscription_tree *sub_tree, pjsip_tx_data *tdata)
1520 {
1521 #ifdef TEST_FRAMEWORK
1522         struct ast_sip_endpoint *endpoint = sub_tree->endpoint;
1523 #endif
1524         int res;
1525
1526         res = pjsip_evsub_send_request(sub_tree->evsub, tdata) == PJ_SUCCESS ? 0 : -1;
1527         subscription_persistence_update(sub_tree, NULL);
1528
1529         ast_test_suite_event_notify("SUBSCRIPTION_STATE_SET",
1530                 "StateText: %s\r\n"
1531                 "Endpoint: %s\r\n",
1532                 pjsip_evsub_get_state_name(sub_tree->evsub),
1533                 ast_sorcery_object_get_id(endpoint));
1534
1535         return res;
1536 }
1537
1538 /*!
1539  * \brief Add a resource XML element to an RLMI body
1540  *
1541  * Each resource element represents a subscribed resource in the list. This function currently
1542  * will unconditionally add an instance element to each created resource element. Instance
1543  * elements refer to later parts in the multipart body.
1544  *
1545  * \param pool PJLIB allocation pool
1546  * \param cid Content-ID header of the resource
1547  * \param resource_name Name of the resource
1548  * \param resource_uri URI of the resource
1549  * \param state State of the subscribed resource
1550  */
1551 static void add_rlmi_resource(pj_pool_t *pool, pj_xml_node *rlmi, const pjsip_generic_string_hdr *cid,
1552                 const char *resource_name, const pjsip_sip_uri *resource_uri, pjsip_evsub_state state)
1553 {
1554         static pj_str_t cid_name = { "cid", 3 };
1555         pj_xml_node *resource;
1556         pj_xml_node *name;
1557         pj_xml_node *instance;
1558         pj_xml_attr *cid_attr;
1559         char id[6];
1560         char uri[PJSIP_MAX_URL_SIZE];
1561
1562         /* This creates a string representing the Content-ID without the enclosing < > */
1563         const pj_str_t cid_stripped = {
1564                 .ptr = cid->hvalue.ptr + 1,
1565                 .slen = cid->hvalue.slen - 2,
1566         };
1567
1568         resource = ast_sip_presence_xml_create_node(pool, rlmi, "resource");
1569         name = ast_sip_presence_xml_create_node(pool, resource, "name");
1570         instance = ast_sip_presence_xml_create_node(pool, resource, "instance");
1571
1572         pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, resource_uri, uri, sizeof(uri));
1573         ast_sip_presence_xml_create_attr(pool, resource, "uri", uri);
1574
1575         pj_strdup2(pool, &name->content, resource_name);
1576
1577         ast_generate_random_string(id, sizeof(id));
1578
1579         ast_sip_presence_xml_create_attr(pool, instance, "id", id);
1580         ast_sip_presence_xml_create_attr(pool, instance, "state",
1581                         state == PJSIP_EVSUB_STATE_TERMINATED ? "terminated" : "active");
1582
1583         /* Use the PJLIB-util XML library directly here since we are using a
1584          * pj_str_t
1585          */
1586
1587         cid_attr = pj_xml_attr_new(pool, &cid_name, &cid_stripped);
1588         pj_xml_add_attr(instance, cid_attr);
1589 }
1590
1591 /*!
1592  * \brief A multipart body part and meta-information
1593  *
1594  * When creating a multipart body part, the end result (the
1595  * pjsip_multipart_part) is hard to inspect without undoing
1596  * a lot of what was done to create it. Therefore, we use this
1597  * structure to store meta-information about the body part.
1598  *
1599  * The main consumer of this is the creator of the RLMI body
1600  * part of a multipart resource list body.
1601  */
1602 struct body_part {
1603         /*! Content-ID header for the body part */
1604         pjsip_generic_string_hdr *cid;
1605         /*! Subscribed resource represented in the body part */
1606         const char *resource;
1607         /*! URI for the subscribed body part */
1608         pjsip_sip_uri *uri;
1609         /*! Subscription state of the resource represented in the body part */
1610         pjsip_evsub_state state;
1611         /*! The actual body part that will be present in the multipart body */
1612         pjsip_multipart_part *part;
1613 };
1614
1615 /*!
1616  * \brief Type declaration for container of body part structures
1617  */
1618 AST_VECTOR(body_part_list, struct body_part *);
1619
1620 /*!
1621  * \brief Create a Content-ID header
1622  *
1623  * Content-ID headers are required by RFC2387 for multipart/related
1624  * bodies. They serve as identifiers for each part of the multipart body.
1625  *
1626  * \param pool PJLIB allocation pool
1627  * \param sub Subscription to a resource
1628  */
1629 static pjsip_generic_string_hdr *generate_content_id_hdr(pj_pool_t *pool,
1630                 const struct ast_sip_subscription *sub)
1631 {
1632         static const pj_str_t cid_name = { "Content-ID", 10 };
1633         pjsip_generic_string_hdr *cid;
1634         char id[6];
1635         size_t alloc_size;
1636         pj_str_t cid_value;
1637
1638         /* '<' + '@' + '>' = 3. pj_str_t does not require a null-terminator */
1639         alloc_size = sizeof(id) + pj_strlen(&sub->uri->host) + 3;
1640         cid_value.ptr = pj_pool_alloc(pool, alloc_size);
1641         cid_value.slen = sprintf(cid_value.ptr, "<%s@%.*s>",
1642                         ast_generate_random_string(id, sizeof(id)),
1643                         (int) pj_strlen(&sub->uri->host), pj_strbuf(&sub->uri->host));
1644         cid = pjsip_generic_string_hdr_create(pool, &cid_name, &cid_value);
1645
1646         return cid;
1647 }
1648
1649 static int rlmi_print_body(struct pjsip_msg_body *msg_body, char *buf, pj_size_t size)
1650 {
1651         int num_printed;
1652         pj_xml_node *rlmi = msg_body->data;
1653
1654         num_printed = pj_xml_print(rlmi, buf, size, PJ_TRUE);
1655         if (num_printed == AST_PJSIP_XML_PROLOG_LEN) {
1656                 return -1;
1657         }
1658
1659         return num_printed;
1660 }
1661
1662 static void *rlmi_clone_data(pj_pool_t *pool, const void *data, unsigned len)
1663 {
1664         const pj_xml_node *rlmi = data;
1665
1666         return pj_xml_clone(pool, rlmi);
1667 }
1668
1669 /*!
1670  * \brief Create an RLMI body part for a multipart resource list body
1671  *
1672  * RLMI (Resource list meta information) is a special body type that lists
1673  * the subscribed resources and tells subscribers the number of subscribed
1674  * resources and what other body parts are in the multipart body. The
1675  * RLMI body also has a version number that a subscriber can use to ensure
1676  * that the locally-stored state corresponds to server state.
1677  *
1678  * \param pool The allocation pool
1679  * \param sub The subscription representing the subscribed resource list
1680  * \param body_parts A container of body parts that RLMI will refer to
1681  * \param full_state Indicates whether this is a full or partial state notification
1682  * \return The multipart part representing the RLMI body
1683  */
1684 static pjsip_multipart_part *build_rlmi_body(pj_pool_t *pool, struct ast_sip_subscription *sub,
1685                 struct body_part_list *body_parts, unsigned int full_state)
1686 {
1687         static const pj_str_t rlmi_type = { "application", 11 };
1688         static const pj_str_t rlmi_subtype = { "rlmi+xml", 8 };
1689         pj_xml_node *rlmi;
1690         pj_xml_node *name;
1691         pjsip_multipart_part *rlmi_part;
1692         char version_str[32];
1693         char uri[PJSIP_MAX_URL_SIZE];
1694         pjsip_generic_string_hdr *cid;
1695         int i;
1696
1697         rlmi = ast_sip_presence_xml_create_node(pool, NULL, "list");
1698         ast_sip_presence_xml_create_attr(pool, rlmi, "xmlns", "urn:ietf:params:xml:ns:rlmi");
1699
1700         ast_sip_subscription_get_local_uri(sub, uri, sizeof(uri));
1701         ast_sip_presence_xml_create_attr(pool, rlmi, "uri", uri);
1702
1703         snprintf(version_str, sizeof(version_str), "%u", sub->version++);
1704         ast_sip_presence_xml_create_attr(pool, rlmi, "version", version_str);
1705         ast_sip_presence_xml_create_attr(pool, rlmi, "fullState", full_state ? "true" : "false");
1706
1707         name = ast_sip_presence_xml_create_node(pool, rlmi, "name");
1708         pj_strdup2(pool, &name->content, ast_sip_subscription_get_resource_name(sub));
1709
1710         for (i = 0; i < AST_VECTOR_SIZE(body_parts); ++i) {
1711                 const struct body_part *part = AST_VECTOR_GET(body_parts, i);
1712
1713                 add_rlmi_resource(pool, rlmi, part->cid, part->resource, part->uri, part->state);
1714         }
1715
1716         rlmi_part = pjsip_multipart_create_part(pool);
1717
1718         rlmi_part->body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body);
1719         pj_strdup(pool, &rlmi_part->body->content_type.type, &rlmi_type);
1720         pj_strdup(pool, &rlmi_part->body->content_type.subtype, &rlmi_subtype);
1721         pj_list_init(&rlmi_part->body->content_type.param);
1722
1723         rlmi_part->body->data = pj_xml_clone(pool, rlmi);
1724         rlmi_part->body->clone_data = rlmi_clone_data;
1725         rlmi_part->body->print_body = rlmi_print_body;
1726
1727         cid = generate_content_id_hdr(pool, sub);
1728         pj_list_insert_before(&rlmi_part->hdr, cid);
1729
1730         return rlmi_part;
1731 }
1732
1733 static pjsip_msg_body *generate_notify_body(pj_pool_t *pool, struct ast_sip_subscription *root,
1734                 unsigned int force_full_state);
1735
1736 /*!
1737  * \brief Destroy a list of body parts
1738  *
1739  * \param parts The container of parts to destroy
1740  */
1741 static void free_body_parts(struct body_part_list *parts)
1742 {
1743         int i;
1744
1745         for (i = 0; i < AST_VECTOR_SIZE(parts); ++i) {
1746                 struct body_part *part = AST_VECTOR_GET(parts, i);
1747                 ast_free(part);
1748         }
1749
1750         AST_VECTOR_FREE(parts);
1751 }
1752
1753 /*!
1754  * \brief Allocate and initialize a body part structure
1755  *
1756  * \param pool PJLIB allocation pool
1757  * \param sub Subscription representing a subscribed resource
1758  */
1759 static struct body_part *allocate_body_part(pj_pool_t *pool, const struct ast_sip_subscription *sub)
1760 {
1761         struct body_part *bp;
1762
1763         bp = ast_calloc(1, sizeof(*bp));
1764         if (!bp) {
1765                 return NULL;
1766         }
1767
1768         bp->cid = generate_content_id_hdr(pool, sub);
1769         bp->resource = sub->resource;
1770         bp->state = sub->subscription_state;
1771         bp->uri = sub->uri;
1772
1773         return bp;
1774 }
1775
1776 /*!
1777  * \brief Create a multipart body part for a subscribed resource
1778  *
1779  * \param pool PJLIB allocation pool
1780  * \param sub The subscription representing a subscribed resource
1781  * \param parts A vector of parts to append the created part to.
1782  * \param use_full_state Unused locally, but may be passed to other functions
1783  */
1784 static void build_body_part(pj_pool_t *pool, struct ast_sip_subscription *sub,
1785                 struct body_part_list *parts, unsigned int use_full_state)
1786 {
1787         struct body_part *bp;
1788         pjsip_msg_body *body;
1789
1790         bp = allocate_body_part(pool, sub);
1791         if (!bp) {
1792                 return;
1793         }
1794
1795         body = generate_notify_body(pool, sub, use_full_state);
1796         if (!body) {
1797                 /* Partial state was requested and the resource has not changed state */
1798                 ast_free(bp);
1799                 return;
1800         }
1801
1802         bp->part = pjsip_multipart_create_part(pool);
1803         bp->part->body = body;
1804         pj_list_insert_before(&bp->part->hdr, bp->cid);
1805
1806         AST_VECTOR_APPEND(parts, bp);
1807 }
1808
1809 /*!
1810  * \brief Create and initialize the PJSIP multipart body structure for a resource list subscription
1811  *
1812  * \param pool
1813  * \return The multipart message body
1814  */
1815 static pjsip_msg_body *create_multipart_body(pj_pool_t *pool)
1816 {
1817         pjsip_media_type media_type;
1818         pjsip_param *media_type_param;
1819         char boundary[6];
1820         pj_str_t pj_boundary;
1821
1822         pjsip_media_type_init2(&media_type, "multipart", "related");
1823
1824         media_type_param = pj_pool_alloc(pool, sizeof(*media_type_param));
1825         pj_list_init(media_type_param);
1826
1827         pj_strdup2(pool, &media_type_param->name, "type");
1828         pj_strdup2(pool, &media_type_param->value, "\"application/rlmi+xml\"");
1829
1830         pj_list_insert_before(&media_type.param, media_type_param);
1831
1832         pj_cstr(&pj_boundary, ast_generate_random_string(boundary, sizeof(boundary)));
1833         return pjsip_multipart_create(pool, &media_type, &pj_boundary);
1834 }
1835
1836 /*!
1837  * \brief Create a resource list body for NOTIFY requests
1838  *
1839  * Resource list bodies are multipart/related bodies. The first part of the multipart body
1840  * is an RLMI body that describes the rest of the parts to come. The other parts of the body
1841  * convey state of individual subscribed resources.
1842  *
1843  * \param pool PJLIB allocation pool
1844  * \param sub Subscription details from which to generate body
1845  * \param force_full_state If true, ignore resource list settings and send a full state notification
1846  * \return The generated multipart/related body
1847  */
1848 static pjsip_msg_body *generate_list_body(pj_pool_t *pool, struct ast_sip_subscription *sub,
1849                 unsigned int force_full_state)
1850 {
1851         int i;
1852         pjsip_multipart_part *rlmi_part;
1853         pjsip_msg_body *multipart;
1854         struct body_part_list body_parts;
1855         unsigned int use_full_state = force_full_state ? 1 : sub->full_state;
1856
1857         if (AST_VECTOR_INIT(&body_parts, AST_VECTOR_SIZE(&sub->children))) {
1858                 return NULL;
1859         }
1860
1861         for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
1862                 build_body_part(pool, AST_VECTOR_GET(&sub->children, i), &body_parts, use_full_state);
1863         }
1864
1865         /* This can happen if issuing partial state and no children of the list have changed state */
1866         if (AST_VECTOR_SIZE(&body_parts) == 0) {
1867                 return NULL;
1868         }
1869
1870         multipart = create_multipart_body(pool);
1871
1872         rlmi_part = build_rlmi_body(pool, sub, &body_parts, use_full_state);
1873         if (!rlmi_part) {
1874                 return NULL;
1875         }
1876         pjsip_multipart_add_part(pool, multipart, rlmi_part);
1877
1878         for (i = 0; i < AST_VECTOR_SIZE(&body_parts); ++i) {
1879                 pjsip_multipart_add_part(pool, multipart, AST_VECTOR_GET(&body_parts, i)->part);
1880         }
1881
1882         free_body_parts(&body_parts);
1883         return multipart;
1884 }
1885
1886 /*!
1887  * \brief Create the body for a NOTIFY request.
1888  *
1889  * \param pool The pool used for allocations
1890  * \param root The root of the subscription tree
1891  * \param force_full_state If true, ignore resource list settings and send a full state notification
1892  */
1893 static pjsip_msg_body *generate_notify_body(pj_pool_t *pool, struct ast_sip_subscription *root,
1894                 unsigned int force_full_state)
1895 {
1896         pjsip_msg_body *body;
1897
1898         if (AST_VECTOR_SIZE(&root->children) == 0) {
1899                 if (force_full_state || root->body_changed) {
1900                         /* Not a list. We've already generated the body and saved it on the subscription.
1901                          * Use that directly.
1902                          */
1903                         pj_str_t type;
1904                         pj_str_t subtype;
1905                         pj_str_t text;
1906
1907                         pj_cstr(&type, ast_sip_subscription_get_body_type(root));
1908                         pj_cstr(&subtype, ast_sip_subscription_get_body_subtype(root));
1909                         pj_cstr(&text, ast_str_buffer(root->body_text));
1910
1911                         body = pjsip_msg_body_create(pool, &type, &subtype, &text);
1912                         root->body_changed = 0;
1913                 } else {
1914                         body = NULL;
1915                 }
1916         } else {
1917                 body = generate_list_body(pool, root, force_full_state);
1918         }
1919
1920         return body;
1921 }
1922
1923 /*!
1924  * \brief Shortcut method to create a Require: eventlist header
1925  */
1926 static pjsip_require_hdr *create_require_eventlist(pj_pool_t *pool)
1927 {
1928         pjsip_require_hdr *require;
1929
1930         require = pjsip_require_hdr_create(pool);
1931         pj_strdup2(pool, &require->values[0], "eventlist");
1932         require->count = 1;
1933
1934         return require;
1935 }
1936
1937 /*!
1938  * \brief Send a NOTIFY request to a subscriber
1939  *
1940  * \param sub_tree The subscription tree representing the subscription
1941  * \param force_full_state If true, ignore resource list settings and send full resource list state.
1942  * \retval 0 Success
1943  * \retval non-zero Failure
1944  */
1945 static int send_notify(struct sip_subscription_tree *sub_tree, unsigned int force_full_state)
1946 {
1947         pjsip_evsub *evsub = sub_tree->evsub;
1948         pjsip_tx_data *tdata;
1949
1950         if (pjsip_evsub_notify(evsub, sub_tree->root->subscription_state,
1951                                 NULL, NULL, &tdata) != PJ_SUCCESS) {
1952                 return -1;
1953         }
1954
1955         tdata->msg->body = generate_notify_body(tdata->pool, sub_tree->root, force_full_state);
1956         if (!tdata->msg->body) {
1957                 pjsip_tx_data_dec_ref(tdata);
1958                 return -1;
1959         }
1960
1961         if (sub_tree->is_list) {
1962                 pjsip_require_hdr *require = create_require_eventlist(tdata->pool);
1963                 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) require);
1964         }
1965
1966         if (sip_subscription_send_request(sub_tree, tdata)) {
1967                 return -1;
1968         }
1969
1970         sub_tree->send_scheduled_notify = 0;
1971
1972         return 0;
1973 }
1974
1975 static int serialized_send_notify(void *userdata)
1976 {
1977         struct sip_subscription_tree *sub_tree = userdata;
1978
1979         /* It's possible that between when the notification was scheduled
1980          * and now, that a new SUBSCRIBE arrived, requiring full state to be
1981          * sent out in an immediate NOTIFY. If that has happened, we need to
1982          * bail out here instead of sending the batched NOTIFY.
1983          */
1984         if (!sub_tree->send_scheduled_notify) {
1985                 ao2_cleanup(sub_tree);
1986                 return 0;
1987         }
1988
1989         send_notify(sub_tree, 0);
1990         ao2_cleanup(sub_tree);
1991         return 0;
1992 }
1993
1994 static int sched_cb(const void *data)
1995 {
1996         struct sip_subscription_tree *sub_tree = (struct sip_subscription_tree *) data;
1997
1998         /* We don't need to bump the refcount of sub_tree since we bumped it when scheduling this task */
1999         ast_sip_push_task(sub_tree->serializer, serialized_send_notify, sub_tree);
2000         return 0;
2001 }
2002
2003 static int schedule_notification(struct sip_subscription_tree *sub_tree)
2004 {
2005         /* There's already a notification scheduled */
2006         if (sub_tree->notify_sched_id > -1) {
2007                 return 0;
2008         }
2009
2010         sub_tree->notify_sched_id = ast_sched_add(sched, sub_tree->notification_batch_interval, sched_cb, ao2_bump(sub_tree));
2011         if (sub_tree->notify_sched_id < 0) {
2012                 return -1;
2013         }
2014
2015         sub_tree->send_scheduled_notify = 1;
2016         return 0;
2017 }
2018
2019 int ast_sip_subscription_notify(struct ast_sip_subscription *sub, void *notify_data,
2020                 int terminate)
2021 {
2022         if (ast_sip_pubsub_generate_body_content(ast_sip_subscription_get_body_type(sub),
2023                                 ast_sip_subscription_get_body_subtype(sub), notify_data, &sub->body_text)) {
2024                 return -1;
2025         }
2026
2027         sub->body_changed = 1;
2028         if (terminate) {
2029                 sub->subscription_state = PJSIP_EVSUB_STATE_TERMINATED;
2030         }
2031
2032         if (sub->tree->notification_batch_interval) {
2033                 return schedule_notification(sub->tree);
2034         } else {
2035                 /* See the note in pubsub_on_rx_refresh() for why sub->tree is refbumped here */
2036                 ao2_ref(sub->tree, +1);
2037                 return send_notify(sub->tree, 0);
2038                 ao2_ref(sub->tree, -1);
2039         }
2040 }
2041
2042 void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
2043 {
2044         pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, sub->uri, buf, size);
2045 }
2046
2047 void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
2048 {
2049         pjsip_dialog *dlg = sub->tree->dlg;
2050         ast_copy_pj_str(buf, &dlg->remote.info_str, size);
2051 }
2052
2053 const char *ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
2054 {
2055         return sub->resource;
2056 }
2057
2058 static int sip_subscription_accept(struct sip_subscription_tree *sub_tree, pjsip_rx_data *rdata, int response)
2059 {
2060         pjsip_hdr res_hdr;
2061
2062         /* If this is a persistence recreation the subscription has already been accepted */
2063         if (ast_sip_mod_data_get(rdata->endpt_info.mod_data, pubsub_module.id, MOD_DATA_PERSISTENCE)) {
2064                 return 0;
2065         }
2066
2067         pj_list_init(&res_hdr);
2068         if (sub_tree->is_list) {
2069                 /* If subscribing to a list, our response has to have a Require: eventlist header in it */
2070                 pj_list_insert_before(&res_hdr, create_require_eventlist(rdata->tp_info.pool));
2071         }
2072
2073         return pjsip_evsub_accept(sub_tree->evsub, rdata, response, &res_hdr) == PJ_SUCCESS ? 0 : -1;
2074 }
2075
2076 static void subscription_datastore_destroy(void *obj)
2077 {
2078         struct ast_datastore *datastore = obj;
2079
2080         /* Using the destroy function (if present) destroy the data */
2081         if (datastore->info->destroy != NULL && datastore->data != NULL) {
2082                 datastore->info->destroy(datastore->data);
2083                 datastore->data = NULL;
2084         }
2085
2086         ast_free((void *) datastore->uid);
2087         datastore->uid = NULL;
2088 }
2089
2090 struct ast_datastore *ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
2091 {
2092         RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
2093         const char *uid_ptr = uid;
2094
2095         if (!info) {
2096                 return NULL;
2097         }
2098
2099         datastore = ao2_alloc(sizeof(*datastore), subscription_datastore_destroy);
2100         if (!datastore) {
2101                 return NULL;
2102         }
2103
2104         datastore->info = info;
2105         if (ast_strlen_zero(uid)) {
2106                 /* They didn't provide an ID so we'll provide one ourself */
2107                 struct ast_uuid *uuid = ast_uuid_generate();
2108                 char uuid_buf[AST_UUID_STR_LEN];
2109                 if (!uuid) {
2110                         return NULL;
2111                 }
2112                 uid_ptr = ast_uuid_to_str(uuid, uuid_buf, sizeof(uuid_buf));
2113                 ast_free(uuid);
2114         }
2115
2116         datastore->uid = ast_strdup(uid_ptr);
2117         if (!datastore->uid) {
2118                 return NULL;
2119         }
2120
2121         ao2_ref(datastore, +1);
2122         return datastore;
2123 }
2124
2125 int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore)
2126 {
2127         ast_assert(datastore != NULL);
2128         ast_assert(datastore->info != NULL);
2129         ast_assert(!ast_strlen_zero(datastore->uid));
2130
2131         if (!ao2_link(subscription->datastores, datastore)) {
2132                 return -1;
2133         }
2134         return 0;
2135 }
2136
2137 struct ast_datastore *ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
2138 {
2139         return ao2_find(subscription->datastores, name, OBJ_KEY);
2140 }
2141
2142 void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
2143 {
2144         ao2_find(subscription->datastores, name, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
2145 }
2146
2147 int ast_sip_publication_add_datastore(struct ast_sip_publication *publication, struct ast_datastore *datastore)
2148 {
2149         ast_assert(datastore != NULL);
2150         ast_assert(datastore->info != NULL);
2151         ast_assert(!ast_strlen_zero(datastore->uid));
2152
2153         if (!ao2_link(publication->datastores, datastore)) {
2154                 return -1;
2155         }
2156         return 0;
2157 }
2158
2159 struct ast_datastore *ast_sip_publication_get_datastore(struct ast_sip_publication *publication, const char *name)
2160 {
2161         return ao2_find(publication->datastores, name, OBJ_KEY);
2162 }
2163
2164 void ast_sip_publication_remove_datastore(struct ast_sip_publication *publication, const char *name)
2165 {
2166         ao2_callback(publication->datastores, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA, NULL, (void *) name);
2167 }
2168
2169 AST_RWLIST_HEAD_STATIC(publish_handlers, ast_sip_publish_handler);
2170
2171 static int publication_hash_fn(const void *obj, const int flags)
2172 {
2173         const struct ast_sip_publication *publication = obj;
2174         const int *entity_tag = obj;
2175
2176         return flags & OBJ_KEY ? *entity_tag : publication->entity_tag;
2177 }
2178
2179 static int publication_cmp_fn(void *obj, void *arg, int flags)
2180 {
2181         const struct ast_sip_publication *publication1 = obj;
2182         const struct ast_sip_publication *publication2 = arg;
2183         const int *entity_tag = arg;
2184
2185         return (publication1->entity_tag == (flags & OBJ_KEY ? *entity_tag : publication2->entity_tag) ?
2186                 CMP_MATCH | CMP_STOP : 0);
2187 }
2188
2189 static void publish_add_handler(struct ast_sip_publish_handler *handler)
2190 {
2191         SCOPED_LOCK(lock, &publish_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2192         AST_RWLIST_INSERT_TAIL(&publish_handlers, handler, next);
2193 }
2194
2195 int ast_sip_register_publish_handler(struct ast_sip_publish_handler *handler)
2196 {
2197         if (ast_strlen_zero(handler->event_name)) {
2198                 ast_log(LOG_ERROR, "No event package specified for publish handler. Cannot register\n");
2199                 return -1;
2200         }
2201
2202         if (!(handler->publications = ao2_container_alloc(PUBLICATIONS_BUCKETS,
2203                 publication_hash_fn, publication_cmp_fn))) {
2204                 ast_log(LOG_ERROR, "Could not allocate publications container for event '%s'\n",
2205                         handler->event_name);
2206                 return -1;
2207         }
2208
2209         publish_add_handler(handler);
2210
2211         ast_module_ref(ast_module_info->self);
2212
2213         return 0;
2214 }
2215
2216 void ast_sip_unregister_publish_handler(struct ast_sip_publish_handler *handler)
2217 {
2218         struct ast_sip_publish_handler *iter;
2219         SCOPED_LOCK(lock, &publish_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2220         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&publish_handlers, iter, next) {
2221                 if (handler == iter) {
2222                         AST_RWLIST_REMOVE_CURRENT(next);
2223                         ao2_cleanup(handler->publications);
2224                         ast_module_unref(ast_module_info->self);
2225                         break;
2226                 }
2227         }
2228         AST_RWLIST_TRAVERSE_SAFE_END;
2229 }
2230
2231 AST_RWLIST_HEAD_STATIC(subscription_handlers, ast_sip_subscription_handler);
2232
2233 static void sub_add_handler(struct ast_sip_subscription_handler *handler)
2234 {
2235         SCOPED_LOCK(lock, &subscription_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2236         AST_RWLIST_INSERT_TAIL(&subscription_handlers, handler, next);
2237         ast_module_ref(ast_module_info->self);
2238 }
2239
2240 static struct ast_sip_subscription_handler *find_sub_handler_for_event_name(const char *event_name)
2241 {
2242         struct ast_sip_subscription_handler *iter;
2243         SCOPED_LOCK(lock, &subscription_handlers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
2244
2245         AST_RWLIST_TRAVERSE(&subscription_handlers, iter, next) {
2246                 if (!strcmp(iter->event_name, event_name)) {
2247                         break;
2248                 }
2249         }
2250         return iter;
2251 }
2252
2253 int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
2254 {
2255         pj_str_t event;
2256         pj_str_t accept[AST_SIP_MAX_ACCEPT] = { {0, }, };
2257         struct ast_sip_subscription_handler *existing;
2258         int i = 0;
2259
2260         if (ast_strlen_zero(handler->event_name)) {
2261                 ast_log(LOG_ERROR, "No event package specified for subscription handler. Cannot register\n");
2262                 return -1;
2263         }
2264
2265         existing = find_sub_handler_for_event_name(handler->event_name);
2266         if (existing) {
2267                 ast_log(LOG_ERROR, "Unable to register subscription handler for event %s."
2268                                 "A handler is already registered\n", handler->event_name);
2269                 return -1;
2270         }
2271
2272         for (i = 0; i < AST_SIP_MAX_ACCEPT && !ast_strlen_zero(handler->accept[i]); ++i) {
2273                 pj_cstr(&accept[i], handler->accept[i]);
2274         }
2275
2276         pj_cstr(&event, handler->event_name);
2277
2278         pjsip_evsub_register_pkg(&pubsub_module, &event, DEFAULT_EXPIRES, i, accept);
2279
2280         sub_add_handler(handler);
2281
2282         return 0;
2283 }
2284
2285 void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler)
2286 {
2287         struct ast_sip_subscription_handler *iter;
2288         SCOPED_LOCK(lock, &subscription_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2289         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&subscription_handlers, iter, next) {
2290                 if (handler == iter) {
2291                         AST_RWLIST_REMOVE_CURRENT(next);
2292                         ast_module_unref(ast_module_info->self);
2293                         break;
2294                 }
2295         }
2296         AST_RWLIST_TRAVERSE_SAFE_END;
2297 }
2298
2299 static struct ast_sip_pubsub_body_generator *find_body_generator_type_subtype(const char *content_type,
2300                 const char *content_subtype)
2301 {
2302         struct ast_sip_pubsub_body_generator *iter;
2303         SCOPED_LOCK(lock, &body_generators, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
2304
2305         AST_LIST_TRAVERSE(&body_generators, iter, list) {
2306                 if (!strcmp(iter->type, content_type) &&
2307                                 !strcmp(iter->subtype, content_subtype)) {
2308                         break;
2309                 }
2310         };
2311
2312         return iter;
2313 }
2314
2315 static struct ast_sip_pubsub_body_generator *find_body_generator_accept(const char *accept)
2316 {
2317         char *accept_copy = ast_strdupa(accept);
2318         char *subtype = accept_copy;
2319         char *type = strsep(&subtype, "/");
2320
2321         if (ast_strlen_zero(type) || ast_strlen_zero(subtype)) {
2322                 return NULL;
2323         }
2324
2325         return find_body_generator_type_subtype(type, subtype);
2326 }
2327
2328 static struct ast_sip_pubsub_body_generator *find_body_generator(char accept[AST_SIP_MAX_ACCEPT][64],
2329                 size_t num_accept)
2330 {
2331         int i;
2332         struct ast_sip_pubsub_body_generator *generator = NULL;
2333
2334         for (i = 0; i < num_accept; ++i) {
2335                 generator = find_body_generator_accept(accept[i]);
2336                 if (generator) {
2337                         ast_debug(3, "Body generator %p found for accept type %s\n", generator, accept[i]);
2338                         break;
2339                 } else {
2340                         ast_debug(3, "No body generator found for accept type %s\n", accept[i]);
2341                 }
2342         }
2343
2344         return generator;
2345 }
2346
2347 static int generate_initial_notify(struct ast_sip_subscription *sub)
2348 {
2349         void *notify_data;
2350         int res;
2351
2352         if (AST_VECTOR_SIZE(&sub->children) > 0) {
2353                 int i;
2354
2355                 for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
2356                         if (generate_initial_notify(AST_VECTOR_GET(&sub->children, i))) {
2357                                 return -1;
2358                         }
2359                 }
2360
2361                 return 0;
2362         }
2363
2364         if (sub->handler->notifier->subscription_established(sub)) {
2365                 return -1;
2366         }
2367
2368         notify_data = sub->handler->notifier->get_notify_data(sub);
2369         if (!notify_data) {
2370                 return -1;
2371         }
2372
2373         res = ast_sip_pubsub_generate_body_content(ast_sip_subscription_get_body_type(sub),
2374                         ast_sip_subscription_get_body_subtype(sub), notify_data, &sub->body_text);
2375
2376         ao2_cleanup(notify_data);
2377
2378         return res;
2379 }
2380
2381 static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
2382 {
2383         pjsip_expires_hdr *expires_header;
2384         struct ast_sip_subscription_handler *handler;
2385         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2386         struct sip_subscription_tree *sub_tree;
2387         struct ast_sip_pubsub_body_generator *generator;
2388         char *resource;
2389         pjsip_uri *request_uri;
2390         pjsip_sip_uri *request_uri_sip;
2391         size_t resource_size;
2392         int resp;
2393         struct resource_tree tree;
2394
2395         endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2396         ast_assert(endpoint != NULL);
2397
2398         if (!endpoint->subscription.allow) {
2399                 ast_log(LOG_WARNING, "Subscriptions not permitted for endpoint %s.\n", ast_sorcery_object_get_id(endpoint));
2400                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 603, NULL, NULL, NULL);
2401                 return PJ_TRUE;
2402         }
2403
2404         request_uri = rdata->msg_info.msg->line.req.uri;
2405
2406         if (!PJSIP_URI_SCHEME_IS_SIP(request_uri) && !PJSIP_URI_SCHEME_IS_SIPS(request_uri)) {
2407                 char uri_str[PJSIP_MAX_URL_SIZE];
2408
2409                 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, request_uri, uri_str, sizeof(uri_str));
2410                 ast_log(LOG_WARNING, "Request URI '%s' is not a sip: or sips: URI.\n", uri_str);
2411                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
2412                 return PJ_TRUE;
2413         }
2414
2415         request_uri_sip = pjsip_uri_get_uri(request_uri);
2416         resource_size = pj_strlen(&request_uri_sip->user) + 1;
2417         resource = alloca(resource_size);
2418         ast_copy_pj_str(resource, &request_uri_sip->user, resource_size);
2419
2420         expires_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, rdata->msg_info.msg->hdr.next);
2421
2422         if (expires_header) {
2423                 if (expires_header->ivalue == 0) {
2424                         ast_log(LOG_WARNING, "Susbscription request from endpoint %s rejected. Expiration of 0 is invalid\n",
2425                                 ast_sorcery_object_get_id(endpoint));
2426                         pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 400, NULL, NULL, NULL);
2427                                 return PJ_TRUE;
2428                 }
2429                 if (expires_header->ivalue < endpoint->subscription.minexpiry) {
2430                         ast_log(LOG_WARNING, "Subscription expiration %d is too brief for endpoint %s. Minimum is %u\n",
2431                                 expires_header->ivalue, ast_sorcery_object_get_id(endpoint), endpoint->subscription.minexpiry);
2432                         pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 423, NULL, NULL, NULL);
2433                         return PJ_TRUE;
2434                 }
2435         }
2436
2437         handler = subscription_get_handler_from_rdata(rdata);
2438         if (!handler) {
2439                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2440                 return PJ_TRUE;
2441         }
2442
2443         generator = subscription_get_generator_from_rdata(rdata, handler);
2444         if (!generator) {
2445                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2446                 return PJ_TRUE;
2447         }
2448
2449         memset(&tree, 0, sizeof(tree));
2450         resp = build_resource_tree(endpoint, handler, resource, &tree);
2451         if (!PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
2452                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);
2453                 resource_tree_destroy(&tree);
2454                 return PJ_TRUE;
2455         }
2456
2457         sub_tree = create_subscription_tree(handler, endpoint, rdata, resource, generator, &tree);
2458         if (!sub_tree) {
2459                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
2460         } else {
2461                 sub_tree->persistence = subscription_persistence_create(sub_tree);
2462                 subscription_persistence_update(sub_tree, rdata);
2463                 sip_subscription_accept(sub_tree, rdata, resp);
2464                 if (generate_initial_notify(sub_tree->root)) {
2465                         pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
2466                 }
2467                 send_notify(sub_tree, 1);
2468         }
2469
2470         resource_tree_destroy(&tree);
2471         return PJ_TRUE;
2472 }
2473
2474 static struct ast_sip_publish_handler *find_pub_handler(const char *event)
2475 {
2476         struct ast_sip_publish_handler *iter = NULL;
2477         SCOPED_LOCK(lock, &publish_handlers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
2478
2479         AST_RWLIST_TRAVERSE(&publish_handlers, iter, next) {
2480                 if (strcmp(event, iter->event_name)) {
2481                         ast_debug(3, "Event %s does not match %s\n", event, iter->event_name);
2482                         continue;
2483                 }
2484                 ast_debug(3, "Event name match: %s = %s\n", event, iter->event_name);
2485                 break;
2486         }
2487
2488         return iter;
2489 }
2490
2491 static enum sip_publish_type determine_sip_publish_type(pjsip_rx_data *rdata,
2492         pjsip_generic_string_hdr *etag_hdr, int *expires, int *entity_id)
2493 {
2494         pjsip_expires_hdr *expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
2495
2496         if (etag_hdr) {
2497                 char etag[pj_strlen(&etag_hdr->hvalue) + 1];
2498
2499                 ast_copy_pj_str(etag, &etag_hdr->hvalue, sizeof(etag));
2500
2501                 if (sscanf(etag, "%30d", entity_id) != 1) {
2502                         return SIP_PUBLISH_UNKNOWN;
2503                 }
2504         }
2505
2506         *expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
2507
2508         if (!(*expires)) {
2509                 return SIP_PUBLISH_REMOVE;
2510         } else if (!etag_hdr && rdata->msg_info.msg->body) {
2511                 return SIP_PUBLISH_INITIAL;
2512         } else if (etag_hdr && !rdata->msg_info.msg->body) {
2513                 return SIP_PUBLISH_REFRESH;
2514         } else if (etag_hdr && rdata->msg_info.msg->body) {
2515                 return SIP_PUBLISH_MODIFY;
2516         }
2517
2518         return SIP_PUBLISH_UNKNOWN;
2519 }
2520
2521 /*! \brief Internal destructor for publications */
2522 static void publication_destroy_fn(void *obj)
2523 {
2524         struct ast_sip_publication *publication = obj;
2525
2526         ast_debug(3, "Destroying SIP publication\n");
2527
2528         ao2_cleanup(publication->datastores);
2529         ao2_cleanup(publication->endpoint);
2530 }
2531
2532 static struct ast_sip_publication *sip_create_publication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata,
2533         const char *resource, const char *event_configuration_name)
2534 {
2535         struct ast_sip_publication *publication;
2536         pjsip_expires_hdr *expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
2537         size_t resource_len = strlen(resource) + 1, event_configuration_name_len = strlen(event_configuration_name) + 1;
2538         char *dst;
2539
2540         ast_assert(endpoint != NULL);
2541
2542         if (!(publication = ao2_alloc(sizeof(*publication) + resource_len + event_configuration_name_len, publication_destroy_fn))) {
2543                 return NULL;
2544         }
2545
2546         if (!(publication->datastores = ao2_container_alloc(DATASTORE_BUCKETS, datastore_hash, datastore_cmp))) {
2547                 ao2_ref(publication, -1);
2548                 return NULL;
2549         }
2550
2551         publication->entity_tag = ast_atomic_fetchadd_int(&esc_etag_counter, +1);
2552         ao2_ref(endpoint, +1);
2553         publication->endpoint = endpoint;
2554         publication->expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
2555         publication->sched_id = -1;
2556         dst = publication->data;
2557         publication->resource = strcpy(dst, resource);
2558         dst += resource_len;
2559         publication->event_configuration_name = strcpy(dst, event_configuration_name);
2560
2561         return publication;
2562 }
2563
2564 static int sip_publication_respond(struct ast_sip_publication *pub, int status_code,
2565                 pjsip_rx_data *rdata)
2566 {
2567         pj_status_t status;
2568         pjsip_tx_data *tdata;
2569         pjsip_transaction *tsx;
2570
2571         if (pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, status_code, NULL, &tdata) != PJ_SUCCESS) {
2572                 return -1;
2573         }
2574
2575         if (PJSIP_IS_STATUS_IN_CLASS(status_code, 200)) {
2576                 RAII_VAR(char *, entity_tag, NULL, ast_free_ptr);
2577                 RAII_VAR(char *, expires, NULL, ast_free_ptr);
2578
2579                 if ((ast_asprintf(&entity_tag, "%d", pub->entity_tag) < 0) ||
2580                         (ast_asprintf(&expires, "%d", pub->expires) < 0)) {
2581                         pjsip_tx_data_dec_ref(tdata);
2582                         return -1;
2583                 }
2584
2585                 ast_sip_add_header(tdata, "SIP-ETag", entity_tag);
2586                 ast_sip_add_header(tdata, "Expires", expires);
2587         }
2588
2589         if ((status = pjsip_tsx_create_uas(&pubsub_module, rdata, &tsx)) != PJ_SUCCESS) {
2590                 return -1;
2591         }
2592
2593         pjsip_tsx_recv_msg(tsx, rdata);
2594
2595         if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
2596                 return -1;
2597         }
2598
2599         return 0;
2600 }
2601
2602 static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata,
2603         struct ast_sip_publish_handler *handler)
2604 {
2605         struct ast_sip_publication *publication;
2606         char *resource_name;
2607         size_t resource_size;
2608         RAII_VAR(struct ast_sip_publication_resource *, resource, NULL, ao2_cleanup);
2609         struct ast_variable *event_configuration_name = NULL;
2610         pjsip_uri *request_uri;
2611         pjsip_sip_uri *request_uri_sip;
2612         int resp;
2613
2614         request_uri = rdata->msg_info.msg->line.req.uri;
2615
2616         if (!PJSIP_URI_SCHEME_IS_SIP(request_uri) && !PJSIP_URI_SCHEME_IS_SIPS(request_uri)) {
2617                 char uri_str[PJSIP_MAX_URL_SIZE];
2618
2619                 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, request_uri, uri_str, sizeof(uri_str));
2620                 ast_log(LOG_WARNING, "Request URI '%s' is not a sip: or sips: URI.\n", uri_str);
2621                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
2622                 return NULL;
2623         }
2624
2625         request_uri_sip = pjsip_uri_get_uri(request_uri);
2626         resource_size = pj_strlen(&request_uri_sip->user) + 1;
2627         resource_name = alloca(resource_size);
2628         ast_copy_pj_str(resource_name, &request_uri_sip->user, resource_size);
2629
2630         resource = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "inbound-publication", resource_name);
2631         if (!resource) {
2632                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
2633                 return NULL;
2634         }
2635
2636         if (!ast_strlen_zero(resource->endpoint) && strcmp(resource->endpoint, ast_sorcery_object_get_id(endpoint))) {
2637                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
2638                 return NULL;
2639         }
2640
2641         for (event_configuration_name = resource->events; event_configuration_name; event_configuration_name = event_configuration_name->next) {
2642                 if (!strcmp(event_configuration_name->name, handler->event_name)) {
2643                         break;
2644                 }
2645         }
2646
2647         if (!event_configuration_name) {
2648                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
2649                 return NULL;
2650         }
2651
2652         resp = handler->new_publication(endpoint, resource_name, event_configuration_name->value);
2653
2654         if (!PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
2655                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);
2656                 return NULL;
2657         }
2658
2659         publication = sip_create_publication(endpoint, rdata, S_OR(resource_name, ""), event_configuration_name->value);
2660
2661         if (!publication) {
2662                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 503, NULL, NULL, NULL);
2663                 return NULL;
2664         }
2665
2666         publication->handler = handler;
2667         if (publication->handler->publication_state_change(publication, rdata->msg_info.msg->body,
2668                         AST_SIP_PUBLISH_STATE_INITIALIZED)) {
2669                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
2670                 ao2_cleanup(publication);
2671                 return NULL;
2672         }
2673
2674         sip_publication_respond(publication, resp, rdata);
2675
2676         return publication;
2677 }
2678
2679 static int publish_expire_callback(void *data)
2680 {
2681         RAII_VAR(struct ast_sip_publication *, publication, data, ao2_cleanup);
2682
2683         if (publication->handler->publish_expire) {
2684                 publication->handler->publish_expire(publication);
2685         }
2686
2687         return 0;
2688 }
2689
2690 static int publish_expire(const void *data)
2691 {
2692         struct ast_sip_publication *publication = (struct ast_sip_publication*)data;
2693
2694         ao2_unlink(publication->handler->publications, publication);
2695         publication->sched_id = -1;
2696
2697         if (ast_sip_push_task(NULL, publish_expire_callback, publication)) {
2698                 ao2_cleanup(publication);
2699         }
2700
2701         return 0;
2702 }
2703
2704 static pj_bool_t pubsub_on_rx_publish_request(pjsip_rx_data *rdata)
2705 {
2706         pjsip_event_hdr *event_header;
2707         struct ast_sip_publish_handler *handler;
2708         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2709         char event[32];
2710         static const pj_str_t str_sip_if_match = { "SIP-If-Match", 12 };
2711         pjsip_generic_string_hdr *etag_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_sip_if_match, NULL);
2712         enum sip_publish_type publish_type;
2713         RAII_VAR(struct ast_sip_publication *, publication, NULL, ao2_cleanup);
2714         int expires = 0, entity_id, response = 0;
2715
2716         endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2717         ast_assert(endpoint != NULL);
2718
2719         event_header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_event_name, rdata->msg_info.msg->hdr.next);
2720         if (!event_header) {
2721                 ast_log(LOG_WARNING, "Incoming PUBLISH request with no Event header\n");
2722                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2723                 return PJ_TRUE;
2724         }
2725         ast_copy_pj_str(event, &event_header->event_type, sizeof(event));
2726
2727         handler = find_pub_handler(event);
2728         if (!handler) {
2729                 ast_log(LOG_WARNING, "No registered publish handler for event %s\n", event);
2730                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2731                 return PJ_TRUE;
2732         }
2733
2734         publish_type = determine_sip_publish_type(rdata, etag_hdr, &expires, &entity_id);
2735
2736         /* If this is not an initial publish ensure that a publication is present */
2737         if ((publish_type != SIP_PUBLISH_INITIAL) && (publish_type != SIP_PUBLISH_UNKNOWN)) {
2738                 if (!(publication = ao2_find(handler->publications, &entity_id, OBJ_KEY | OBJ_UNLINK))) {
2739                         static const pj_str_t str_conditional_request_failed = { "Conditional Request Failed", 26 };
2740
2741                         pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 412, &str_conditional_request_failed,
2742                                 NULL, NULL);
2743                         return PJ_TRUE;
2744                 }
2745
2746                 /* Per the RFC every response has to have a new entity tag */
2747                 publication->entity_tag = ast_atomic_fetchadd_int(&esc_etag_counter, +1);
2748
2749                 /* Update the expires here so that the created responses will contain the correct value */
2750                 publication->expires = expires;
2751         }
2752
2753         switch (publish_type) {
2754                 case SIP_PUBLISH_INITIAL:
2755                         publication = publish_request_initial(endpoint, rdata, handler);
2756                         break;
2757                 case SIP_PUBLISH_REFRESH:
2758                 case SIP_PUBLISH_MODIFY:
2759                         if (handler->publication_state_change(publication, rdata->msg_info.msg->body,
2760                                                 AST_SIP_PUBLISH_STATE_ACTIVE)) {
2761                                 /* If an error occurs we want to terminate the publication */
2762                                 expires = 0;
2763                         }
2764                         response = 200;
2765                         break;
2766                 case SIP_PUBLISH_REMOVE:
2767                         handler->publication_state_change(publication, rdata->msg_info.msg->body,
2768                                         AST_SIP_PUBLISH_STATE_TERMINATED);
2769                         response = 200;
2770                         break;
2771                 case SIP_PUBLISH_UNKNOWN:
2772                 default:
2773                         pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 400, NULL, NULL, NULL);
2774                         break;
2775         }
2776
2777         if (publication) {
2778                 if (expires) {
2779                         ao2_link(handler->publications, publication);
2780
2781                         AST_SCHED_REPLACE_UNREF(publication->sched_id, sched, expires * 1000, publish_expire, publication,
2782                                                 ao2_ref(publication, -1), ao2_ref(publication, -1), ao2_ref(publication, +1));
2783                 } else {
2784                         AST_SCHED_DEL_UNREF(sched, publication->sched_id, ao2_ref(publication, -1));
2785                 }
2786         }
2787
2788         if (response) {
2789                 sip_publication_respond(publication, response, rdata);
2790         }
2791
2792         return PJ_TRUE;
2793 }
2794
2795 struct ast_sip_endpoint *ast_sip_publication_get_endpoint(struct ast_sip_publication *pub)
2796 {
2797         return pub->endpoint;
2798 }
2799
2800 const char *ast_sip_publication_get_resource(const struct ast_sip_publication *pub)
2801 {
2802         return pub->resource;
2803 }
2804
2805 const char *ast_sip_publication_get_event_configuration(const struct ast_sip_publication *pub)
2806 {
2807         return pub->event_configuration_name;
2808 }
2809
2810 int ast_sip_pubsub_register_body_generator(struct ast_sip_pubsub_body_generator *generator)
2811 {
2812         struct ast_sip_pubsub_body_generator *existing;
2813         pj_str_t accept;
2814         pj_size_t accept_len;
2815
2816         existing = find_body_generator_type_subtype(generator->type, generator->subtype);
2817         if (existing) {
2818                 ast_log(LOG_WARNING, "Cannot register body generator of %s/%s."
2819                                 "One is already registered.\n", generator->type, generator->subtype);
2820                 return -1;
2821         }
2822
2823         AST_RWLIST_WRLOCK(&body_generators);
2824         AST_LIST_INSERT_HEAD(&body_generators, generator, list);
2825         AST_RWLIST_UNLOCK(&body_generators);
2826
2827         /* Lengths of type and subtype plus space for a slash. pj_str_t is not
2828          * null-terminated, so there is no need to allocate for the extra null
2829          * byte
2830          */
2831         accept_len = strlen(generator->type) + strlen(generator->subtype) + 1;
2832
2833         accept.ptr = alloca(accept_len);
2834         accept.slen = accept_len;
2835         /* Safe use of sprintf */
2836         sprintf(accept.ptr, "%s/%s", generator->type, generator->subtype);
2837         pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), &pubsub_module,
2838                         PJSIP_H_ACCEPT, NULL, 1, &accept);
2839
2840         return 0;
2841 }
2842
2843 void ast_sip_pubsub_unregister_body_generator(struct ast_sip_pubsub_body_generator *generator)
2844 {
2845         struct ast_sip_pubsub_body_generator *iter;
2846         SCOPED_LOCK(lock, &body_generators, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2847
2848         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&body_generators, iter, list) {
2849                 if (iter == generator) {
2850                         AST_LIST_REMOVE_CURRENT(list);
2851                         break;
2852                 }
2853         }
2854         AST_RWLIST_TRAVERSE_SAFE_END;
2855 }
2856
2857 int ast_sip_pubsub_register_body_supplement(struct ast_sip_pubsub_body_supplement *supplement)
2858 {
2859         AST_RWLIST_WRLOCK(&body_supplements);
2860         AST_RWLIST_INSERT_TAIL(&body_supplements, supplement, list);
2861         AST_RWLIST_UNLOCK(&body_supplements);
2862
2863         return 0;
2864 }
2865
2866 void ast_sip_pubsub_unregister_body_supplement(struct ast_sip_pubsub_body_supplement *supplement)
2867 {
2868         struct ast_sip_pubsub_body_supplement *iter;
2869         SCOPED_LOCK(lock, &body_supplements, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2870
2871         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&body_supplements, iter, list) {
2872                 if (iter == supplement) {
2873                         AST_LIST_REMOVE_CURRENT(list);
2874                         break;
2875                 }
2876         }
2877         AST_RWLIST_TRAVERSE_SAFE_END;
2878 }
2879
2880 const char *ast_sip_subscription_get_body_type(struct ast_sip_subscription *sub)
2881 {
2882         return sub->body_generator->type;
2883 }
2884
2885 const char *ast_sip_subscription_get_body_subtype(struct ast_sip_subscription *sub)
2886 {
2887         return sub->body_generator->subtype;
2888 }
2889
2890 int ast_sip_pubsub_generate_body_content(const char *type, const char *subtype,
2891                 void *data, struct ast_str **str)
2892 {
2893         struct ast_sip_pubsub_body_supplement *supplement;
2894         struct ast_sip_pubsub_body_generator *generator;
2895         int res = 0;
2896         void *body;
2897
2898         generator = find_body_generator_type_subtype(type, subtype);
2899         if (!generator) {
2900                 ast_log(LOG_WARNING, "Unable to find a body generator for %s/%s\n",
2901                                 type, subtype);
2902                 return -1;
2903         }
2904
2905         body = generator->allocate_body(data);
2906         if (!body) {
2907                 ast_log(LOG_WARNING, "Unable to allocate a NOTIFY body of type %s/%s\n",
2908                                 type, subtype);
2909                 return -1;
2910         }
2911
2912         if (generator->generate_body_content(body, data)) {
2913                 res = -1;
2914                 goto end;
2915         }
2916
2917         AST_RWLIST_RDLOCK(&body_supplements);
2918         AST_RWLIST_TRAVERSE(&body_supplements, supplement, list) {
2919                 if (!strcmp(generator->type, supplement->type) &&
2920                                 !strcmp(generator->subtype, supplement->subtype)) {
2921                         res = supplement->supplement_body(body, data);
2922                         if (res) {
2923                                 break;
2924                         }
2925                 }
2926         }
2927         AST_RWLIST_UNLOCK(&body_supplements);
2928
2929         if (!res) {
2930                 generator->to_string(body, str);
2931         }
2932
2933 end:
2934         if (generator->destroy_body) {
2935                 generator->destroy_body(body);
2936         }
2937
2938         return res;
2939 }
2940
2941 static pj_bool_t pubsub_on_rx_request(pjsip_rx_data *rdata)
2942 {
2943         if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_subscribe_method())) {
2944                 return pubsub_on_rx_subscribe_request(rdata);
2945         } else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_publish_method)) {
2946                 return pubsub_on_rx_publish_request(rdata);
2947         }
2948
2949         return PJ_FALSE;
2950 }
2951
2952 static void pubsub_on_evsub_state(pjsip_evsub *evsub, pjsip_event *event)
2953 {
2954         struct sip_subscription_tree *sub_tree;
2955
2956         if (pjsip_evsub_get_state(evsub) != PJSIP_EVSUB_STATE_TERMINATED) {
2957                 return;
2958         }
2959
2960         sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
2961         if (!sub_tree) {
2962                 return;
2963         }
2964
2965         ao2_cleanup(sub_tree);
2966
2967         pjsip_evsub_set_mod_data(evsub, pubsub_module.id, NULL);
2968 }
2969
2970 static void set_state_terminated(struct ast_sip_subscription *sub)
2971 {
2972         int i;
2973
2974         sub->subscription_state = PJSIP_EVSUB_STATE_TERMINATED;
2975         for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
2976                 set_state_terminated(AST_VECTOR_GET(&sub->children, i));
2977         }
2978 }
2979
2980 static void pubsub_on_rx_refresh(pjsip_evsub *evsub, pjsip_rx_data *rdata,
2981                 int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body)
2982 {
2983         struct sip_subscription_tree *sub_tree;
2984
2985         sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
2986         if (!sub_tree) {
2987                 return;
2988         }
2989
2990         /* If sending a NOTIFY to terminate a subscription, then pubsub_on_evsub_state()
2991          * will be called when we send the NOTIFY, and that will result in dropping the
2992          * refcount of sub_tree by one, and possibly destroying the sub_tree. We need to
2993          * hold a reference to the sub_tree until this function returns so that we don't
2994          * try to read from or write to freed memory by accident
2995          */
2996         ao2_ref(sub_tree, +1);
2997
2998         if (pjsip_evsub_get_state(evsub) == PJSIP_EVSUB_STATE_TERMINATED) {
2999                 set_state_terminated(sub_tree->root);
3000         }
3001
3002         if (send_notify(sub_tree, 1)) {
3003                 *p_st_code = 500;
3004         }
3005
3006         if (sub_tree->is_list) {
3007                 pj_list_insert_before(res_hdr, create_require_eventlist(rdata->tp_info.pool));
3008         }
3009
3010         ao2_ref(sub_tree, -1);
3011 }
3012
3013 static void pubsub_on_rx_notify(pjsip_evsub *evsub, pjsip_rx_data *rdata, int *p_st_code,
3014                 pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body)
3015 {
3016         struct ast_sip_subscription *sub = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3017
3018         if (!sub) {
3019                 return;
3020         }
3021
3022         sub->handler->subscriber->state_change(sub, rdata->msg_info.msg->body,
3023                         pjsip_evsub_get_state(evsub));
3024 }
3025
3026 static int serialized_pubsub_on_client_refresh(void *userdata)
3027 {
3028         struct sip_subscription_tree *sub_tree = userdata;
3029         pjsip_tx_data *tdata;
3030
3031         if (pjsip_evsub_initiate(sub_tree->evsub, NULL, -1, &tdata) == PJ_SUCCESS) {
3032                 pjsip_evsub_send_request(sub_tree->evsub, tdata);
3033         } else {
3034                 pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
3035                 return 0;
3036         }
3037         ao2_cleanup(sub_tree);
3038         return 0;
3039 }
3040
3041 static void pubsub_on_client_refresh(pjsip_evsub *evsub)
3042 {
3043         struct sip_subscription_tree *sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3044
3045         ao2_ref(sub_tree, +1);
3046         ast_sip_push_task(sub_tree->serializer, serialized_pubsub_on_client_refresh, sub_tree);
3047 }
3048
3049 static int serialized_pubsub_on_server_timeout(void *userdata)
3050 {
3051         struct sip_subscription_tree *sub_tree = userdata;
3052
3053         set_state_terminated(sub_tree->root);
3054         send_notify(sub_tree, 1);
3055
3056         ao2_cleanup(sub_tree);
3057         return 0;
3058 }
3059
3060 static void pubsub_on_server_timeout(pjsip_evsub *evsub)
3061 {
3062         struct sip_subscription_tree *sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3063
3064         if (!sub_tree) {
3065                 /* if a subscription has been terminated and the subscription
3066                    timeout/expires is less than the time it takes for all pending
3067                    transactions to end then the subscription timer will not have
3068                    been canceled yet and sub will be null, so do nothing since
3069                    the subscription has already been terminated. */
3070                 return;
3071         }
3072
3073         ao2_ref(sub_tree, +1);
3074         ast_sip_push_task(sub_tree->serializer, serialized_pubsub_on_server_timeout, sub_tree);
3075 }
3076
3077 static int ami_subscription_detail(struct sip_subscription_tree *sub_tree,
3078                                    struct ast_sip_ami *ami,
3079                                    const char *event)
3080 {
3081         RAII_VAR(struct ast_str *, buf,
3082                  ast_sip_create_ami_event(event, ami), ast_free);
3083
3084         if (!buf) {
3085                 return -1;
3086         }
3087
3088         sip_subscription_to_ami(sub_tree, &buf);
3089         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
3090         return 0;
3091 }
3092
3093 static int ami_subscription_detail_inbound(struct sip_subscription_tree *sub_tree, void *arg)
3094 {
3095         return sub_tree->role == AST_SIP_NOTIFIER ? ami_subscription_detail(
3096                 sub_tree, arg, "InboundSubscriptionDetail") : 0;
3097 }
3098
3099 static int ami_subscription_detail_outbound(struct sip_subscription_tree *sub_tree, void *arg)
3100 {
3101         return sub_tree->role == AST_SIP_SUBSCRIBER ? ami_subscription_detail(
3102                 sub_tree, arg, "OutboundSubscriptionDetail") : 0;
3103 }
3104
3105 static int ami_show_subscriptions_inbound(struct mansession *s, const struct message *m)
3106 {
3107         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
3108         int num;
3109
3110         astman_send_listack(s, m, "Following are Events for "
3111                             "each inbound Subscription", "start");
3112
3113         num = for_each_subscription(ami_subscription_detail_inbound, &ami);
3114
3115         astman_append(s, "Event: InboundSubscriptionDetailComplete\r\n");
3116         if (!ast_strlen_zero(ami.action_id)) {
3117                 astman_append(s, "ActionID: %s\r\n", ami.action_id);
3118         }
3119         astman_append(s, "EventList: Complete\r\n"
3120                       "ListItems: %d\r\n\r\n", num);
3121         return 0;
3122 }
3123
3124 static int ami_show_subscriptions_outbound(struct mansession *s, const struct message *m)
3125 {
3126         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
3127         int num;
3128
3129         astman_send_listack(s, m, "Following are Events for "
3130                             "each outbound Subscription", "start");
3131
3132         num = for_each_subscription(ami_subscription_detail_outbound, &ami);
3133
3134         astman_append(s, "Event: OutboundSubscriptionDetailComplete\r\n");
3135         if (!ast_strlen_zero(ami.action_id)) {
3136                 astman_append(s, "ActionID: %s\r\n", ami.action_id);
3137         }
3138         astman_append(s, "EventList: Complete\r\n"
3139                       "ListItems: %d\r\n\r\n", num);
3140         return 0;
3141 }
3142
3143 static int format_ami_resource_lists(void *obj, void *arg, int flags)
3144 {
3145         struct resource_list *list = obj;
3146         struct ast_sip_ami *ami = arg;
3147         struct ast_str *buf;
3148
3149         buf = ast_sip_create_ami_event("ResourceListDetail", ami);
3150         if (!buf) {
3151                 return CMP_STOP;
3152         }
3153
3154         if (ast_sip_sorcery_object_to_ami(list, &buf)) {
3155                 ast_free(buf);
3156                 return CMP_STOP;
3157         }
3158         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
3159
3160         ast_free(buf);
3161         return 0;
3162 }
3163
3164 static int ami_show_resource_lists(struct mansession *s, const struct message *m)
3165 {
3166         struct ast_sip_ami ami = { .s = s, .m = m };
3167         int num;
3168         struct ao2_container *lists;
3169
3170         lists = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "resource_list",
3171                         AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
3172
3173         if (!lists || !(num = ao2_container_count(lists))) {
3174                 astman_send_error(s, m, "No resource lists found\n");
3175                 return 0;
3176         }
3177
3178         astman_send_listack(s, m, "A listing of resource lists follows, "
3179                             "presented as ResourceListDetail events", "start");
3180
3181         ao2_callback(lists, OBJ_NODATA, format_ami_resource_lists, &ami);
3182
3183         astman_append(s,
3184                       "Event: ResourceListDetailComplete\r\n"
3185                       "EventList: Complete\r\n"
3186                       "ListItems: %d\r\n\r\n", num);
3187         return 0;
3188 }
3189
3190 #define AMI_SHOW_SUBSCRIPTIONS_INBOUND "PJSIPShowSubscriptionsInbound"
3191 #define AMI_SHOW_SUBSCRIPTIONS_OUTBOUND "PJSIPShowSubscriptionsOutbound"
3192
3193 static int persistence_endpoint_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
3194 {
3195         struct subscription_persistence *persistence = obj;
3196
3197         persistence->endpoint = ast_strdup(var->value);
3198         return 0;
3199 }
3200
3201 static int persistence_endpoint_struct2str(const void *obj, const intptr_t *args, char **buf)
3202 {
3203         const struct subscription_persistence *persistence = obj;
3204
3205         *buf = ast_strdup(persistence->endpoint);
3206         return 0;
3207 }
3208
3209 static int persistence_tag_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
3210 {
3211         struct subscription_persistence *persistence = obj;
3212
3213         persistence->tag = ast_strdup(var->value);
3214         return 0;
3215 }
3216
3217 static int persistence_tag_struct2str(const void *obj, const intptr_t *args, char **buf)
3218 {
3219         const struct subscription_persistence *persistence = obj;
3220
3221         *buf = ast_strdup(persistence->tag);
3222         return 0;
3223 }
3224
3225 static int persistence_expires_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
3226 {
3227         struct subscription_persistence *persistence = obj;
3228         return ast_get_timeval(var->value, &persistence->expires, ast_tv(0, 0), NULL);
3229 }
3230
3231 static int persistence_expires_struct2str(const void *obj, const intptr_t *args, char **buf)
3232 {
3233         const struct subscription_persistence *persistence = obj;
3234         return (ast_asprintf(buf, "%ld", persistence->expires.tv_sec) < 0) ? -1 : 0;
3235 }
3236
3237 #define RESOURCE_LIST_INIT_SIZE 4
3238
3239 static void resource_list_destructor(void *obj)
3240 {
3241         struct resource_list *list = obj;
3242         int i;
3243
3244         for (i = 0; i < AST_VECTOR_SIZE(&list->items); ++i) {
3245                 ast_free((char *) AST_VECTOR_GET(&list->items, i));
3246         }
3247
3248         AST_VECTOR_FREE(&list->items);
3249 }
3250
3251 static void *resource_list_alloc(const char *name)
3252 {
3253         struct resource_list *list;
3254
3255         list = ast_sorcery_generic_alloc(sizeof(*list), resource_list_destructor);
3256         if (!list) {
3257                 return NULL;
3258         }
3259
3260         if (AST_VECTOR_INIT(&list->items, RESOURCE_LIST_INIT_SIZE)) {
3261                 ao2_cleanup(list);
3262                 return NULL;
3263         }
3264
3265         return list;
3266 }
3267
3268 static int item_in_vector(const struct resource_list *list, const char *item)
3269 {
3270         int i;
3271
3272         for (i = 0; i < AST_VECTOR_SIZE(&list->items); ++i) {
3273                 if (!strcmp(item, AST_VECTOR_GET(&list->items, i))) {
3274                         return 1;
3275                 }
3276         }
3277
3278         return 0;
3279 }
3280
3281 static int list_item_handler(const struct aco_option *opt,
3282                 struct ast_variable *var, void *obj)
3283 {
3284         struct resource_list *list = obj;
3285         char *items = ast_strdupa(var->value);
3286         char *item;
3287
3288         while ((item = strsep(&items, ","))) {
3289                 if (item_in_vector(list, item)) {
3290                         ast_log(LOG_WARNING, "Ignoring duplicated list item '%s'\n", item);
3291                         continue;
3292                 }
3293                 if (AST_VECTOR_APPEND(&list->items, ast_strdup(item))) {
3294                         return -1;
3295                 }
3296         }
3297
3298         return 0;
3299 }
3300
3301 static int list_item_to_str(const void *obj, const intptr_t *args, char **buf)
3302 {
3303         const struct resource_list *list = obj;
3304         int i;
3305         struct ast_str *str = ast_str_create(32);
3306
3307         for (i = 0; i < AST_VECTOR_SIZE(&list->items); ++i) {
3308                 ast_str_append(&str, 0, "%s,", AST_VECTOR_GET(&list->items, i));
3309         }
3310
3311         /* Chop off trailing comma */
3312         ast_str_truncate(str, -1);
3313         *buf = ast_strdup(ast_str_buffer(str));
3314         ast_free(str);
3315         return 0;
3316 }
3317
3318 static int resource_list_apply_handler(const struct ast_sorcery *sorcery, void *obj)
3319 {
3320         struct resource_list *list = obj;
3321
3322         if (ast_strlen_zero(list->event)) {
3323                 ast_log(LOG_WARNING, "Resource list '%s' has no event set\n",
3324                                 ast_sorcery_object_get_id(list));
3325                 return -1;
3326         }
3327
3328         if (AST_VECTOR_SIZE(&list->items) == 0) {
3329                 ast_log(LOG_WARNING, "Resource list '%s' has no list items\n",
3330                                 ast_sorcery_object_get_id(list));
3331                 return -1;
3332         }
3333
3334         return 0;
3335 }
3336
3337 static int apply_list_configuration(struct ast_sorcery *sorcery)
3338 {
3339         ast_sorcery_apply_default(sorcery, "resource_list", "config",
3340                         "pjsip.conf,criteria=type=resource_list");
3341         if (ast_sorcery_object_register(sorcery, "resource_list", resource_list_alloc,
3342                                 NULL, resource_list_apply_handler)) {
3343                 return -1;
3344         }
3345
3346         ast_sorcery_object_field_register(sorcery, "resource_list", "type", "",
3347                         OPT_NOOP_T, 0, 0);
3348         ast_sorcery_object_field_register(sorcery, "resource_list", "event", "",
3349                         OPT_CHAR_ARRAY_T, 1, CHARFLDSET(struct resource_list, event));
3350         ast_sorcery_object_field_register(sorcery, "resource_list", "full_state", "no",
3351                         OPT_BOOL_T, 1, FLDSET(struct resource_list, full_state));
3352         ast_sorcery_object_field_register(sorcery, "resource_list", "notification_batch_interval",
3353                         "0", OPT_UINT_T, 0, FLDSET(struct resource_list, notification_batch_interval));
3354         ast_sorcery_object_field_register_custom(sorcery, "resource_list", "list_item",
3355                         "", list_item_handler, list_item_to_str, NULL, 0, 0);
3356
3357         ast_sorcery_reload_object(sorcery, "resource_list");
3358
3359         return 0;
3360 }
3361
3362 #ifdef TEST_FRAMEWORK
3363
3364 /*!
3365  * \brief "bad" resources
3366  *
3367  * These are resources that the test handler will reject subscriptions to.
3368  */
3369 const char *bad_resources[] = {
3370         "coconut",
3371         "cilantro",
3372         "olive",
3373         "cheese",
3374 };
3375
3376 /*!
3377  * \brief new_subscribe callback for unit tests
3378  *
3379  * Will give a 200 OK response to any resource except the "bad" ones.
3380  */
3381 static int test_new_subscribe(struct ast_sip_endpoint *endpoint, const char *resource)
3382 {
3383         int i;
3384
3385         for (i = 0; i < ARRAY_LEN(bad_resources); ++i) {
3386                 if (!strcmp(resource, bad_resources[i])) {
3387                         return 400;
3388                 }
3389         }
3390
3391         return 200;
3392 }
3393
3394 /*!
3395  * \brief Subscription notifier for unit tests.
3396  *
3397  * Since unit tests are only concerned with building a resource tree,
3398  * only the new_subscribe callback needs to be defined.
3399  */
3400 struct ast_sip_notifier test_notifier = {
3401         .new_subscribe = test_new_subscribe,
3402 };
3403
3404 /*!
3405  * \brief Subscription handler for unit tests.
3406  */
3407 struct ast_sip_subscription_handler test_handler = {
3408         .event_name = "test",
3409         .notifier = &test_notifier,
3410 };
3411
3412 /*!
3413  * \brief Set properties on an allocated resource list
3414  *
3415  * \param list The list to set details on.
3416  * \param event The list's event.
3417  * \param resources Array of resources to add to the list.
3418  * \param num_resources Number of resources in the array.
3419  * \retval 0 Success
3420  * \retval non-zero Failure
3421  */
3422 static int populate_list(struct resource_list *list, const char *event, const char **resources, size_t num_resources)
3423 {
3424         int i;
3425
3426         ast_copy_string(list->event, event, sizeof(list->event));
3427
3428         for (i = 0; i < num_resources; ++i) {
3429                 if (AST_VECTOR_APPEND(&list->items, ast_strdup(resources[i]))) {
3430                         return -1;
3431                 }
3432         }
3433         return 0;
3434 }
3435
3436 /*!
3437  * \brief RAII callback to destroy a resource list
3438  */
3439 static void cleanup_resource_list(struct resource_list *list)
3440 {
3441         if (!list) {
3442                 return;
3443         }
3444
3445         ast_sorcery_delete(ast_sip_get_sorcery(), list);
3446         ao2_cleanup(list);
3447 }
3448
3449 /*!
3450  * \brief allocate a resource list, store it in sorcery, and set its details
3451  *
3452  * \param test The unit test. Used for logging status messages.
3453  * \param list_name The name of the list to create.
3454  * \param event The event the list services
3455  * \param resources Array of resources to apply to the list
3456  * \param num_resources The number of resources in the array
3457  * \retval NULL Failed to allocate or populate list
3458  * \retval non-NULL The created list
3459  */
3460 static struct resource_list *create_resource_list(struct ast_test *test,
3461                 const char *list_name, const char *event, const char **resources, size_t num_resources)
3462 {
3463         struct resource_list *list;
3464
3465         list = ast_sorcery_alloc(ast_sip_get_sorcery(), "resource_list", list_name);
3466         if (!list) {
3467                 ast_test_status_update(test, "Could not allocate resource list in sorcery\n");
3468                 return NULL;
3469         }
3470
3471         if (ast_sorcery_create(ast_sip_get_sorcery(), list)) {
3472                 ast_test_status_update(test, "Could not store the resource list in sorcery\n");
3473                 ao2_cleanup(list);
3474                 return NULL;
3475         }
3476
3477         if (populate_list(list, event, resources, num_resources)) {
3478                 ast_test_status_update(test, "Could not add resources to the resource list\n");
3479                 cleanup_resource_list(list);
3480                 return NULL;
3481         }
3482
3483         return list;
3484 }
3485
3486 /*!
3487  * \brief Check the integrity of a tree node against a set of resources.
3488  *
3489  * The tree node's resources must be in the same order as the resources in
3490  * the supplied resources array. Because of this constraint, tests can misrepresent
3491  * the size of the resources array as being smaller than it really is if resources
3492  * at the end of the array should not be present in the tree node.
3493  *
3494  * \param test The unit test. Used for printing status messages.
3495  * \param node The constructed tree node whose integrity is under question.
3496  * \param resources Array of expected resource values
3497  * \param num_resources The number of resources to check in the array.
3498  */
3499 static int check_node(struct ast_test *test, struct tree_node *node,
3500                 const char **resources, size_t num_resources)
3501 {
3502         int i;
3503
3504         if (AST_VECTOR_SIZE(&node->children) != num_resources) {
3505                 ast_test_status_update(test, "Unexpected number of resources in tree. Expected %zu, got %zu\n",
3506                                 num_resources, AST_VECTOR_SIZE(&node->children));
3507                 return -1;
3508         }
3509
3510         for (i = 0; i < num_resources; ++i) {
3511                 if (strcmp(resources[i], AST_VECTOR_GET(&node->children, i)->resource)) {
3512                         ast_test_status_update(test, "Mismatched resources. Expected '%s' but got '%s'\n",
3513                                         resources[i], AST_VECTOR_GET(&node->children, i)->resource);
3514                         return -1;
3515                 }
3516         }
3517
3518         return 0;
3519 }
3520
3521 /*!
3522  * \brief RAII_VAR callback to destroy an allocated resource tree
3523  */
3524 static void test_resource_tree_destroy(struct resource_tree *tree)
3525 {
3526         resource_tree_destroy(tree);
3527         ast_free(tree);
3528 }
3529
3530 static int ineligible_configuration(void)
3531 {
3532         struct ast_config *config;
3533         struct ast_flags flags = {0,};
3534         const char *value;
3535
3536         config = ast_config_load("sorcery.conf", flags);
3537         if (!config) {
3538                 return 1;
3539         }
3540
3541         value = ast_variable_retrieve(config, "res_pjsip_pubsub", "resource_list");
3542         if (ast_strlen_zero(value)) {
3543                 ast_config_destroy(config);
3544                 return 1;
3545         }
3546
3547         if (strcasecmp(value, "memory") && strcasecmp(value, "astdb")) {
3548                 ast_config_destroy(config);
3549                 return 1;
3550         }
3551
3552         return 0;
3553 }
3554
3555 AST_TEST_DEFINE(resource_tree)
3556 {
3557         RAII_VAR(struct resource_list *, list, NULL, cleanup_resource_list);
3558         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3559         const char *resources[] = {
3560                 "huey",
3561                 "dewey",
3562                 "louie",
3563         };
3564         int resp;
3565
3566         switch (cmd) {
3567         case TEST_INIT:
3568                 info->name = "resource_tree";
3569                 info->category = "/res/res_pjsip_pubsub/";
3570                 info->summary = "Basic resource tree integrity check";
3571                 info->description =
3572                         "Create a resource list and ensure that our attempt to build a tree works as expected.";
3573                 return AST_TEST_NOT_RUN;
3574         case TEST_EXECUTE:
3575                 break;
3576         }
3577
3578         if (ineligible_configuration()) {
3579                 ast_test_status_update(test, "Ineligible configuration for this test. Please add a "
3580                                 "'res_pjsip_pubsub' section to sorcery.conf, and set 'resource_list=memory'\n");
3581                 return AST_TEST_NOT_RUN;
3582         }
3583
3584         list = create_resource_list(test, "foo", "test", resources, ARRAY_LEN(resources));
3585         if (!list) {
3586                 return AST_TEST_FAIL;
3587         }
3588
3589         tree = ast_calloc(1, sizeof(*tree));
3590         resp = build_resource_tree(NULL, &test_handler, "foo", tree);
3591         if (resp != 200) {
3592                 ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
3593                 return AST_TEST_FAIL;
3594         }
3595
3596         if (!tree->root) {
3597                 ast_test_status_update(test, "Resource tree has no root\n");
3598                 return AST_TEST_FAIL;
3599         }
3600
3601         if (check_node(test, tree->root, resources, ARRAY_LEN(resources))) {
3602                 return AST_TEST_FAIL;
3603         }
3604
3605         return AST_TEST_PASS;
3606 }
3607
3608 AST_TEST_DEFINE(complex_resource_tree)
3609 {
3610         RAII_VAR(struct resource_list *, list_1, NULL, cleanup_resource_list);
3611         RAII_VAR(struct resource_list *, list_2, NULL, cleanup_resource_list);
3612         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3613         const char *resources_1[] = {
3614                 "huey",
3615                 "dewey",
3616                 "louie",
3617                 "dwarves",
3618         };
3619         const char *resources_2[] = {
3620                 "happy",
3621                 "grumpy",
3622                 "doc",
3623                 "bashful",
3624                 "dopey",
3625                 "sneezy",
3626                 "sleepy",
3627         };
3628         int resp;
3629         struct tree_node *node;
3630
3631         switch (cmd) {
3632         case TEST_INIT:
3633                 info->name = "complex_resource_tree";
3634                 info->category = "/res/res_pjsip_pubsub/";
3635                 info->summary = "Complex resource tree integrity check";
3636                 info->description =
3637                         "Create a complex resource list and ensure that our attempt to build a tree works as expected.";
3638                 return AST_TEST_NOT_RUN;
3639         case TEST_EXECUTE:
3640                 break;
3641         }
3642
3643         if (ineligible_configuration()) {
3644                 ast_test_status_update(test, "Ineligible configuration for this test. Please add a "
3645                                 "'res_pjsip_pubsub' section to sorcery.conf, and set 'resource_list=memory'\n");
3646                 return AST_TEST_NOT_RUN;
3647         }
3648
3649         list_1 = create_resource_list(test, "foo", "test", resources_1, ARRAY_LEN(resources_1));
3650         if (!list_1) {
3651                 return AST_TEST_FAIL;
3652         }
3653
3654         list_2 = create_resource_list(test, "dwarves", "test", resources_2, ARRAY_LEN(resources_2));
3655         if (!list_2) {
3656                 return AST_TEST_FAIL;
3657         }
3658
3659         tree = ast_calloc(1, sizeof(*tree));
3660         resp = build_resource_tree(NULL, &test_handler, "foo", tree);
3661         if (resp != 200) {
3662                 ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
3663                 return AST_TEST_FAIL;
3664         }
3665
3666         if (!tree->root) {
3667                 ast_test_status_update(test, "Resource tree has no root\n");
3668                 return AST_TEST_FAIL;
3669         }
3670
3671         node = tree->root;
3672         if (check_node(test, node, resources_1, ARRAY_LEN(resources_1))) {
3673                 return AST_TEST_FAIL;
3674         }
3675
3676         /* The embedded list is at index 3 in the root node's children */
3677         node = AST_VECTOR_GET(&node->children, 3);
3678         if (check_node(test, node, resources_2, ARRAY_LEN(resources_2))) {
3679                 return AST_TEST_FAIL;
3680         }
3681
3682         return AST_TEST_PASS;
3683 }
3684
3685 AST_TEST_DEFINE(bad_resource)
3686 {
3687         RAII_VAR(struct resource_list *, list, NULL, cleanup_resource_list);
3688         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3689         const char *resources[] = {
3690                 "huey",
3691                 "dewey",
3692                 "louie",
3693                 "coconut", /* A "bad" resource */
3694         };
3695         int resp;
3696
3697         switch (cmd) {
3698         case TEST_INIT:
3699                 info->name = "bad_resource";
3700                 info->category = "/res/res_pjsip_pubsub/";
3701                 info->summary = "Ensure bad resources do not end up in the tree";
3702                 info->description =
3703                         "Create a resource list with a single bad resource. Ensure the bad resource does not end up in the tree.";
3704                 return AST_TEST_NOT_RUN;
3705         case TEST_EXECUTE:
3706                 break;
3707         }
3708
3709         if (ineligible_configuration()) {
3710                 ast_test_status_update(test, "Ineligible configuration for this test. Please add a "
3711                                 "'res_pjsip_pubsub' section to sorcery.conf, and set 'resource_list=memory'\n");
3712                 return AST_TEST_NOT_RUN;
3713         }
3714
3715         list = create_resource_list(test, "foo", "test", resources, ARRAY_LEN(resources));
3716         if (!list) {
3717                 return AST_TEST_FAIL;
3718         }
3719
3720         tree = ast_calloc(1, sizeof(*tree));
3721         resp = build_resource_tree(NULL, &test_handler, "foo", tree);
3722         if (resp != 200) {
3723                 ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
3724                 return AST_TEST_FAIL;
3725         }
3726
3727         if (!tree->root) {
3728                 ast_test_status_update(test, "Resource tree has no root\n");
3729                 return AST_TEST_FAIL;
3730         }
3731
3732         /* We check against all but the final resource since we expect it not to be in the tree */
3733         if (check_node(test, tree->root, resources, ARRAY_LEN(resources) - 1)) {
3734                 return AST_TEST_FAIL;
3735         }
3736
3737         return AST_TEST_PASS;
3738
3739 }
3740
3741 AST_TEST_DEFINE(bad_branch)
3742 {
3743         RAII_VAR(struct resource_list *, list_1, NULL, cleanup_resource_list);
3744         RAII_VAR(struct resource_list *, list_2, NULL, cleanup_resource_list);
3745         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3746         const char *resources_1[] = {
3747                 "huey",
3748                 "dewey",
3749                 "louie",
3750                 "gross",
3751         };
3752         /* This list has nothing but bad resources */
3753         const char *resources_2[] = {
3754                 "coconut",
3755                 "cilantro",
3756                 "olive",
3757                 "cheese",
3758         };
3759         int resp;
3760
3761         switch (cmd) {
3762         case TEST_INIT:
3763                 info->name = "bad_branch";
3764                 info->category = "/res/res_pjsip_pubsub/";
3765                 info->summary = "Ensure bad branches are pruned from the tree";
3766                 info->description =
3767                         "Create a resource list that makes a tree with an entire branch of bad resources.\n"
3768                         "Ensure the bad branch is pruned from the tree.";
3769                 return AST_TEST_NOT_RUN;
3770         case TEST_EXECUTE:
3771                 break;
3772         }
3773
3774         if (ineligible_configuration()) {
3775                 ast_test_status_update(test, "Ineligible configuration for this test. Please add a "
3776                                 "'res_pjsip_pubsub' section to sorcery.conf, and set 'resource_list=memory'\n");
3777                 return AST_TEST_NOT_RUN;
3778         }
3779
3780         list_1 = create_resource_list(test, "foo", "test", resources_1, ARRAY_LEN(resources_1));
3781         if (!list_1) {
3782                 return AST_TEST_FAIL;
3783         }
3784         list_2 = create_resource_list(test, "gross", "test", resources_2, ARRAY_LEN(resources_2));
3785         if (!list_2) {
3786                 return AST_TEST_FAIL;
3787         }
3788
3789         tree = ast_calloc(1, sizeof(*tree));
3790         resp = build_resource_tree(NULL, &test_handler, "foo", tree);
3791         if (resp != 200) {
3792                 ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
3793                 return AST_TEST_FAIL;
3794         }
3795
3796         if (!tree->root) {
3797                 ast_test_status_update(test, "Resource tree has no root\n");
3798                 return AST_TEST_FAIL;
3799         }
3800
3801         /* We check against all but the final resource of the list since the entire branch should
3802          * be pruned from the tree
3803          */
3804         if (check_node(test, tree->root, resources_1, ARRAY_LEN(resources_1) - 1)) {
3805                 return AST_TEST_FAIL;
3806         }
3807
3808         return AST_TEST_PASS;
3809
3810 }
3811
3812 AST_TEST_DEFINE(duplicate_resource)
3813 {
3814         RAII_VAR(struct resource_list *, list_1, NULL, cleanup_resource_list);
3815         RAII_VAR(struct resource_list *, list_2, NULL, cleanup_resource_list);
3816         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3817         const char *resources_1[] = {
3818                 "huey",
3819                 "ducks",
3820                 "dewey",
3821                 "louie",
3822         };
3823         const char *resources_2[] = {
3824                 "donald",