Fix build in dev mode
[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                 return send_notify(sub->tree, 0);
2036         }
2037 }
2038
2039 void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
2040 {
2041         pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, sub->uri, buf, size);
2042 }
2043
2044 void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
2045 {
2046         pjsip_dialog *dlg = sub->tree->dlg;
2047         ast_copy_pj_str(buf, &dlg->remote.info_str, size);
2048 }
2049
2050 const char *ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
2051 {
2052         return sub->resource;
2053 }
2054
2055 static int sip_subscription_accept(struct sip_subscription_tree *sub_tree, pjsip_rx_data *rdata, int response)
2056 {
2057         pjsip_hdr res_hdr;
2058
2059         /* If this is a persistence recreation the subscription has already been accepted */
2060         if (ast_sip_mod_data_get(rdata->endpt_info.mod_data, pubsub_module.id, MOD_DATA_PERSISTENCE)) {
2061                 return 0;
2062         }
2063
2064         pj_list_init(&res_hdr);
2065         if (sub_tree->is_list) {
2066                 /* If subscribing to a list, our response has to have a Require: eventlist header in it */
2067                 pj_list_insert_before(&res_hdr, create_require_eventlist(rdata->tp_info.pool));
2068         }
2069
2070         return pjsip_evsub_accept(sub_tree->evsub, rdata, response, &res_hdr) == PJ_SUCCESS ? 0 : -1;
2071 }
2072
2073 static void subscription_datastore_destroy(void *obj)
2074 {
2075         struct ast_datastore *datastore = obj;
2076
2077         /* Using the destroy function (if present) destroy the data */
2078         if (datastore->info->destroy != NULL && datastore->data != NULL) {
2079                 datastore->info->destroy(datastore->data);
2080                 datastore->data = NULL;
2081         }
2082
2083         ast_free((void *) datastore->uid);
2084         datastore->uid = NULL;
2085 }
2086
2087 struct ast_datastore *ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
2088 {
2089         RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
2090         const char *uid_ptr = uid;
2091
2092         if (!info) {
2093                 return NULL;
2094         }
2095
2096         datastore = ao2_alloc(sizeof(*datastore), subscription_datastore_destroy);
2097         if (!datastore) {
2098                 return NULL;
2099         }
2100
2101         datastore->info = info;
2102         if (ast_strlen_zero(uid)) {
2103                 /* They didn't provide an ID so we'll provide one ourself */
2104                 struct ast_uuid *uuid = ast_uuid_generate();
2105                 char uuid_buf[AST_UUID_STR_LEN];
2106                 if (!uuid) {
2107                         return NULL;
2108                 }
2109                 uid_ptr = ast_uuid_to_str(uuid, uuid_buf, sizeof(uuid_buf));
2110                 ast_free(uuid);
2111         }
2112
2113         datastore->uid = ast_strdup(uid_ptr);
2114         if (!datastore->uid) {
2115                 return NULL;
2116         }
2117
2118         ao2_ref(datastore, +1);
2119         return datastore;
2120 }
2121
2122 int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore)
2123 {
2124         ast_assert(datastore != NULL);
2125         ast_assert(datastore->info != NULL);
2126         ast_assert(!ast_strlen_zero(datastore->uid));
2127
2128         if (!ao2_link(subscription->datastores, datastore)) {
2129                 return -1;
2130         }
2131         return 0;
2132 }
2133
2134 struct ast_datastore *ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
2135 {
2136         return ao2_find(subscription->datastores, name, OBJ_KEY);
2137 }
2138
2139 void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
2140 {
2141         ao2_find(subscription->datastores, name, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
2142 }
2143
2144 int ast_sip_publication_add_datastore(struct ast_sip_publication *publication, struct ast_datastore *datastore)
2145 {
2146         ast_assert(datastore != NULL);
2147         ast_assert(datastore->info != NULL);
2148         ast_assert(!ast_strlen_zero(datastore->uid));
2149
2150         if (!ao2_link(publication->datastores, datastore)) {
2151                 return -1;
2152         }
2153         return 0;
2154 }
2155
2156 struct ast_datastore *ast_sip_publication_get_datastore(struct ast_sip_publication *publication, const char *name)
2157 {
2158         return ao2_find(publication->datastores, name, OBJ_KEY);
2159 }
2160
2161 void ast_sip_publication_remove_datastore(struct ast_sip_publication *publication, const char *name)
2162 {
2163         ao2_callback(publication->datastores, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA, NULL, (void *) name);
2164 }
2165
2166 AST_RWLIST_HEAD_STATIC(publish_handlers, ast_sip_publish_handler);
2167
2168 static int publication_hash_fn(const void *obj, const int flags)
2169 {
2170         const struct ast_sip_publication *publication = obj;
2171         const int *entity_tag = obj;
2172
2173         return flags & OBJ_KEY ? *entity_tag : publication->entity_tag;
2174 }
2175
2176 static int publication_cmp_fn(void *obj, void *arg, int flags)
2177 {
2178         const struct ast_sip_publication *publication1 = obj;
2179         const struct ast_sip_publication *publication2 = arg;
2180         const int *entity_tag = arg;
2181
2182         return (publication1->entity_tag == (flags & OBJ_KEY ? *entity_tag : publication2->entity_tag) ?
2183                 CMP_MATCH | CMP_STOP : 0);
2184 }
2185
2186 static void publish_add_handler(struct ast_sip_publish_handler *handler)
2187 {
2188         SCOPED_LOCK(lock, &publish_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2189         AST_RWLIST_INSERT_TAIL(&publish_handlers, handler, next);
2190 }
2191
2192 int ast_sip_register_publish_handler(struct ast_sip_publish_handler *handler)
2193 {
2194         if (ast_strlen_zero(handler->event_name)) {
2195                 ast_log(LOG_ERROR, "No event package specified for publish handler. Cannot register\n");
2196                 return -1;
2197         }
2198
2199         if (!(handler->publications = ao2_container_alloc(PUBLICATIONS_BUCKETS,
2200                 publication_hash_fn, publication_cmp_fn))) {
2201                 ast_log(LOG_ERROR, "Could not allocate publications container for event '%s'\n",
2202                         handler->event_name);
2203                 return -1;
2204         }
2205
2206         publish_add_handler(handler);
2207
2208         ast_module_ref(ast_module_info->self);
2209
2210         return 0;
2211 }
2212
2213 void ast_sip_unregister_publish_handler(struct ast_sip_publish_handler *handler)
2214 {
2215         struct ast_sip_publish_handler *iter;
2216         SCOPED_LOCK(lock, &publish_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2217         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&publish_handlers, iter, next) {
2218                 if (handler == iter) {
2219                         AST_RWLIST_REMOVE_CURRENT(next);
2220                         ao2_cleanup(handler->publications);
2221                         ast_module_unref(ast_module_info->self);
2222                         break;
2223                 }
2224         }
2225         AST_RWLIST_TRAVERSE_SAFE_END;
2226 }
2227
2228 AST_RWLIST_HEAD_STATIC(subscription_handlers, ast_sip_subscription_handler);
2229
2230 static void sub_add_handler(struct ast_sip_subscription_handler *handler)
2231 {
2232         SCOPED_LOCK(lock, &subscription_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2233         AST_RWLIST_INSERT_TAIL(&subscription_handlers, handler, next);
2234         ast_module_ref(ast_module_info->self);
2235 }
2236
2237 static struct ast_sip_subscription_handler *find_sub_handler_for_event_name(const char *event_name)
2238 {
2239         struct ast_sip_subscription_handler *iter;
2240         SCOPED_LOCK(lock, &subscription_handlers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
2241
2242         AST_RWLIST_TRAVERSE(&subscription_handlers, iter, next) {
2243                 if (!strcmp(iter->event_name, event_name)) {
2244                         break;
2245                 }
2246         }
2247         return iter;
2248 }
2249
2250 int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
2251 {
2252         pj_str_t event;
2253         pj_str_t accept[AST_SIP_MAX_ACCEPT] = { {0, }, };
2254         struct ast_sip_subscription_handler *existing;
2255         int i = 0;
2256
2257         if (ast_strlen_zero(handler->event_name)) {
2258                 ast_log(LOG_ERROR, "No event package specified for subscription handler. Cannot register\n");
2259                 return -1;
2260         }
2261
2262         existing = find_sub_handler_for_event_name(handler->event_name);
2263         if (existing) {
2264                 ast_log(LOG_ERROR, "Unable to register subscription handler for event %s."
2265                                 "A handler is already registered\n", handler->event_name);
2266                 return -1;
2267         }
2268
2269         for (i = 0; i < AST_SIP_MAX_ACCEPT && !ast_strlen_zero(handler->accept[i]); ++i) {
2270                 pj_cstr(&accept[i], handler->accept[i]);
2271         }
2272
2273         pj_cstr(&event, handler->event_name);
2274
2275         pjsip_evsub_register_pkg(&pubsub_module, &event, DEFAULT_EXPIRES, i, accept);
2276
2277         sub_add_handler(handler);
2278
2279         return 0;
2280 }
2281
2282 void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler)
2283 {
2284         struct ast_sip_subscription_handler *iter;
2285         SCOPED_LOCK(lock, &subscription_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2286         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&subscription_handlers, iter, next) {
2287                 if (handler == iter) {
2288                         AST_RWLIST_REMOVE_CURRENT(next);
2289                         ast_module_unref(ast_module_info->self);
2290                         break;
2291                 }
2292         }
2293         AST_RWLIST_TRAVERSE_SAFE_END;
2294 }
2295
2296 static struct ast_sip_pubsub_body_generator *find_body_generator_type_subtype(const char *content_type,
2297                 const char *content_subtype)
2298 {
2299         struct ast_sip_pubsub_body_generator *iter;
2300         SCOPED_LOCK(lock, &body_generators, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
2301
2302         AST_LIST_TRAVERSE(&body_generators, iter, list) {
2303                 if (!strcmp(iter->type, content_type) &&
2304                                 !strcmp(iter->subtype, content_subtype)) {
2305                         break;
2306                 }
2307         };
2308
2309         return iter;
2310 }
2311
2312 static struct ast_sip_pubsub_body_generator *find_body_generator_accept(const char *accept)
2313 {
2314         char *accept_copy = ast_strdupa(accept);
2315         char *subtype = accept_copy;
2316         char *type = strsep(&subtype, "/");
2317
2318         if (ast_strlen_zero(type) || ast_strlen_zero(subtype)) {
2319                 return NULL;
2320         }
2321
2322         return find_body_generator_type_subtype(type, subtype);
2323 }
2324
2325 static struct ast_sip_pubsub_body_generator *find_body_generator(char accept[AST_SIP_MAX_ACCEPT][64],
2326                 size_t num_accept)
2327 {
2328         int i;
2329         struct ast_sip_pubsub_body_generator *generator = NULL;
2330
2331         for (i = 0; i < num_accept; ++i) {
2332                 generator = find_body_generator_accept(accept[i]);
2333                 if (generator) {
2334                         ast_debug(3, "Body generator %p found for accept type %s\n", generator, accept[i]);
2335                         break;
2336                 } else {
2337                         ast_debug(3, "No body generator found for accept type %s\n", accept[i]);
2338                 }
2339         }
2340
2341         return generator;
2342 }
2343
2344 static int generate_initial_notify(struct ast_sip_subscription *sub)
2345 {
2346         void *notify_data;
2347         int res;
2348
2349         if (AST_VECTOR_SIZE(&sub->children) > 0) {
2350                 int i;
2351
2352                 for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
2353                         if (generate_initial_notify(AST_VECTOR_GET(&sub->children, i))) {
2354                                 return -1;
2355                         }
2356                 }
2357
2358                 return 0;
2359         }
2360
2361         if (sub->handler->notifier->subscription_established(sub)) {
2362                 return -1;
2363         }
2364
2365         notify_data = sub->handler->notifier->get_notify_data(sub);
2366         if (!notify_data) {
2367                 return -1;
2368         }
2369
2370         res = ast_sip_pubsub_generate_body_content(ast_sip_subscription_get_body_type(sub),
2371                         ast_sip_subscription_get_body_subtype(sub), notify_data, &sub->body_text);
2372
2373         ao2_cleanup(notify_data);
2374
2375         return res;
2376 }
2377
2378 static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
2379 {
2380         pjsip_expires_hdr *expires_header;
2381         struct ast_sip_subscription_handler *handler;
2382         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2383         struct sip_subscription_tree *sub_tree;
2384         struct ast_sip_pubsub_body_generator *generator;
2385         char *resource;
2386         pjsip_uri *request_uri;
2387         pjsip_sip_uri *request_uri_sip;
2388         size_t resource_size;
2389         int resp;
2390         struct resource_tree tree;
2391
2392         endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2393         ast_assert(endpoint != NULL);
2394
2395         if (!endpoint->subscription.allow) {
2396                 ast_log(LOG_WARNING, "Subscriptions not permitted for endpoint %s.\n", ast_sorcery_object_get_id(endpoint));
2397                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 603, NULL, NULL, NULL);
2398                 return PJ_TRUE;
2399         }
2400
2401         request_uri = rdata->msg_info.msg->line.req.uri;
2402
2403         if (!PJSIP_URI_SCHEME_IS_SIP(request_uri) && !PJSIP_URI_SCHEME_IS_SIPS(request_uri)) {
2404                 char uri_str[PJSIP_MAX_URL_SIZE];
2405
2406                 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, request_uri, uri_str, sizeof(uri_str));
2407                 ast_log(LOG_WARNING, "Request URI '%s' is not a sip: or sips: URI.\n", uri_str);
2408                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
2409                 return PJ_TRUE;
2410         }
2411
2412         request_uri_sip = pjsip_uri_get_uri(request_uri);
2413         resource_size = pj_strlen(&request_uri_sip->user) + 1;
2414         resource = alloca(resource_size);
2415         ast_copy_pj_str(resource, &request_uri_sip->user, resource_size);
2416
2417         expires_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, rdata->msg_info.msg->hdr.next);
2418
2419         if (expires_header) {
2420                 if (expires_header->ivalue == 0) {
2421                         ast_log(LOG_WARNING, "Susbscription request from endpoint %s rejected. Expiration of 0 is invalid\n",
2422                                 ast_sorcery_object_get_id(endpoint));
2423                         pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 400, NULL, NULL, NULL);
2424                                 return PJ_TRUE;
2425                 }
2426                 if (expires_header->ivalue < endpoint->subscription.minexpiry) {
2427                         ast_log(LOG_WARNING, "Subscription expiration %d is too brief for endpoint %s. Minimum is %u\n",
2428                                 expires_header->ivalue, ast_sorcery_object_get_id(endpoint), endpoint->subscription.minexpiry);
2429                         pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 423, NULL, NULL, NULL);
2430                         return PJ_TRUE;
2431                 }
2432         }
2433
2434         handler = subscription_get_handler_from_rdata(rdata);
2435         if (!handler) {
2436                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2437                 return PJ_TRUE;
2438         }
2439
2440         generator = subscription_get_generator_from_rdata(rdata, handler);
2441         if (!generator) {
2442                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2443                 return PJ_TRUE;
2444         }
2445
2446         memset(&tree, 0, sizeof(tree));
2447         resp = build_resource_tree(endpoint, handler, resource, &tree);
2448         if (!PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
2449                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);
2450                 resource_tree_destroy(&tree);
2451                 return PJ_TRUE;
2452         }
2453
2454         sub_tree = create_subscription_tree(handler, endpoint, rdata, resource, generator, &tree);
2455         if (!sub_tree) {
2456                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
2457         } else {
2458                 sub_tree->persistence = subscription_persistence_create(sub_tree);
2459                 subscription_persistence_update(sub_tree, rdata);
2460                 sip_subscription_accept(sub_tree, rdata, resp);
2461                 if (generate_initial_notify(sub_tree->root)) {
2462                         pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
2463                 }
2464                 send_notify(sub_tree, 1);
2465         }
2466
2467         resource_tree_destroy(&tree);
2468         return PJ_TRUE;
2469 }
2470
2471 static struct ast_sip_publish_handler *find_pub_handler(const char *event)
2472 {
2473         struct ast_sip_publish_handler *iter = NULL;
2474         SCOPED_LOCK(lock, &publish_handlers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
2475
2476         AST_RWLIST_TRAVERSE(&publish_handlers, iter, next) {
2477                 if (strcmp(event, iter->event_name)) {
2478                         ast_debug(3, "Event %s does not match %s\n", event, iter->event_name);
2479                         continue;
2480                 }
2481                 ast_debug(3, "Event name match: %s = %s\n", event, iter->event_name);
2482                 break;
2483         }
2484
2485         return iter;
2486 }
2487
2488 static enum sip_publish_type determine_sip_publish_type(pjsip_rx_data *rdata,
2489         pjsip_generic_string_hdr *etag_hdr, int *expires, int *entity_id)
2490 {
2491         pjsip_expires_hdr *expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
2492
2493         if (etag_hdr) {
2494                 char etag[pj_strlen(&etag_hdr->hvalue) + 1];
2495
2496                 ast_copy_pj_str(etag, &etag_hdr->hvalue, sizeof(etag));
2497
2498                 if (sscanf(etag, "%30d", entity_id) != 1) {
2499                         return SIP_PUBLISH_UNKNOWN;
2500                 }
2501         }
2502
2503         *expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
2504
2505         if (!(*expires)) {
2506                 return SIP_PUBLISH_REMOVE;
2507         } else if (!etag_hdr && rdata->msg_info.msg->body) {
2508                 return SIP_PUBLISH_INITIAL;
2509         } else if (etag_hdr && !rdata->msg_info.msg->body) {
2510                 return SIP_PUBLISH_REFRESH;
2511         } else if (etag_hdr && rdata->msg_info.msg->body) {
2512                 return SIP_PUBLISH_MODIFY;
2513         }
2514
2515         return SIP_PUBLISH_UNKNOWN;
2516 }
2517
2518 /*! \brief Internal destructor for publications */
2519 static void publication_destroy_fn(void *obj)
2520 {
2521         struct ast_sip_publication *publication = obj;
2522
2523         ast_debug(3, "Destroying SIP publication\n");
2524
2525         ao2_cleanup(publication->datastores);
2526         ao2_cleanup(publication->endpoint);
2527 }
2528
2529 static struct ast_sip_publication *sip_create_publication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata,
2530         const char *resource, const char *event_configuration_name)
2531 {
2532         struct ast_sip_publication *publication;
2533         pjsip_expires_hdr *expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
2534         size_t resource_len = strlen(resource) + 1, event_configuration_name_len = strlen(event_configuration_name) + 1;
2535         char *dst;
2536
2537         ast_assert(endpoint != NULL);
2538
2539         if (!(publication = ao2_alloc(sizeof(*publication) + resource_len + event_configuration_name_len, publication_destroy_fn))) {
2540                 return NULL;
2541         }
2542
2543         if (!(publication->datastores = ao2_container_alloc(DATASTORE_BUCKETS, datastore_hash, datastore_cmp))) {
2544                 ao2_ref(publication, -1);
2545                 return NULL;
2546         }
2547
2548         publication->entity_tag = ast_atomic_fetchadd_int(&esc_etag_counter, +1);
2549         ao2_ref(endpoint, +1);
2550         publication->endpoint = endpoint;
2551         publication->expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
2552         publication->sched_id = -1;
2553         dst = publication->data;
2554         publication->resource = strcpy(dst, resource);
2555         dst += resource_len;
2556         publication->event_configuration_name = strcpy(dst, event_configuration_name);
2557
2558         return publication;
2559 }
2560
2561 static int sip_publication_respond(struct ast_sip_publication *pub, int status_code,
2562                 pjsip_rx_data *rdata)
2563 {
2564         pj_status_t status;
2565         pjsip_tx_data *tdata;
2566         pjsip_transaction *tsx;
2567
2568         if (pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, status_code, NULL, &tdata) != PJ_SUCCESS) {
2569                 return -1;
2570         }
2571
2572         if (PJSIP_IS_STATUS_IN_CLASS(status_code, 200)) {
2573                 RAII_VAR(char *, entity_tag, NULL, ast_free_ptr);
2574                 RAII_VAR(char *, expires, NULL, ast_free_ptr);
2575
2576                 if ((ast_asprintf(&entity_tag, "%d", pub->entity_tag) < 0) ||
2577                         (ast_asprintf(&expires, "%d", pub->expires) < 0)) {
2578                         pjsip_tx_data_dec_ref(tdata);
2579                         return -1;
2580                 }
2581
2582                 ast_sip_add_header(tdata, "SIP-ETag", entity_tag);
2583                 ast_sip_add_header(tdata, "Expires", expires);
2584         }
2585
2586         if ((status = pjsip_tsx_create_uas(&pubsub_module, rdata, &tsx)) != PJ_SUCCESS) {
2587                 return -1;
2588         }
2589
2590         pjsip_tsx_recv_msg(tsx, rdata);
2591
2592         if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
2593                 return -1;
2594         }
2595
2596         return 0;
2597 }
2598
2599 static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata,
2600         struct ast_sip_publish_handler *handler)
2601 {
2602         struct ast_sip_publication *publication;
2603         char *resource_name;
2604         size_t resource_size;
2605         RAII_VAR(struct ast_sip_publication_resource *, resource, NULL, ao2_cleanup);
2606         struct ast_variable *event_configuration_name = NULL;
2607         pjsip_uri *request_uri;
2608         pjsip_sip_uri *request_uri_sip;
2609         int resp;
2610
2611         request_uri = rdata->msg_info.msg->line.req.uri;
2612
2613         if (!PJSIP_URI_SCHEME_IS_SIP(request_uri) && !PJSIP_URI_SCHEME_IS_SIPS(request_uri)) {
2614                 char uri_str[PJSIP_MAX_URL_SIZE];
2615
2616                 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, request_uri, uri_str, sizeof(uri_str));
2617                 ast_log(LOG_WARNING, "Request URI '%s' is not a sip: or sips: URI.\n", uri_str);
2618                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
2619                 return NULL;
2620         }
2621
2622         request_uri_sip = pjsip_uri_get_uri(request_uri);
2623         resource_size = pj_strlen(&request_uri_sip->user) + 1;
2624         resource_name = alloca(resource_size);
2625         ast_copy_pj_str(resource_name, &request_uri_sip->user, resource_size);
2626
2627         resource = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "inbound-publication", resource_name);
2628         if (!resource) {
2629                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
2630                 return NULL;
2631         }
2632
2633         if (!ast_strlen_zero(resource->endpoint) && strcmp(resource->endpoint, ast_sorcery_object_get_id(endpoint))) {
2634                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
2635                 return NULL;
2636         }
2637
2638         for (event_configuration_name = resource->events; event_configuration_name; event_configuration_name = event_configuration_name->next) {
2639                 if (!strcmp(event_configuration_name->name, handler->event_name)) {
2640                         break;
2641                 }
2642         }
2643
2644         if (!event_configuration_name) {
2645                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
2646                 return NULL;
2647         }
2648
2649         resp = handler->new_publication(endpoint, resource_name, event_configuration_name->value);
2650
2651         if (!PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
2652                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);
2653                 return NULL;
2654         }
2655
2656         publication = sip_create_publication(endpoint, rdata, S_OR(resource_name, ""), event_configuration_name->value);
2657
2658         if (!publication) {
2659                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 503, NULL, NULL, NULL);
2660                 return NULL;
2661         }
2662
2663         publication->handler = handler;
2664         if (publication->handler->publication_state_change(publication, rdata->msg_info.msg->body,
2665                         AST_SIP_PUBLISH_STATE_INITIALIZED)) {
2666                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
2667                 ao2_cleanup(publication);
2668                 return NULL;
2669         }
2670
2671         sip_publication_respond(publication, resp, rdata);
2672
2673         return publication;
2674 }
2675
2676 static int publish_expire_callback(void *data)
2677 {
2678         RAII_VAR(struct ast_sip_publication *, publication, data, ao2_cleanup);
2679
2680         if (publication->handler->publish_expire) {
2681                 publication->handler->publish_expire(publication);
2682         }
2683
2684         return 0;
2685 }
2686
2687 static int publish_expire(const void *data)
2688 {
2689         struct ast_sip_publication *publication = (struct ast_sip_publication*)data;
2690
2691         ao2_unlink(publication->handler->publications, publication);
2692         publication->sched_id = -1;
2693
2694         if (ast_sip_push_task(NULL, publish_expire_callback, publication)) {
2695                 ao2_cleanup(publication);
2696         }
2697
2698         return 0;
2699 }
2700
2701 static pj_bool_t pubsub_on_rx_publish_request(pjsip_rx_data *rdata)
2702 {
2703         pjsip_event_hdr *event_header;
2704         struct ast_sip_publish_handler *handler;
2705         RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2706         char event[32];
2707         static const pj_str_t str_sip_if_match = { "SIP-If-Match", 12 };
2708         pjsip_generic_string_hdr *etag_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_sip_if_match, NULL);
2709         enum sip_publish_type publish_type;
2710         RAII_VAR(struct ast_sip_publication *, publication, NULL, ao2_cleanup);
2711         int expires = 0, entity_id, response = 0;
2712
2713         endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2714         ast_assert(endpoint != NULL);
2715
2716         event_header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_event_name, rdata->msg_info.msg->hdr.next);
2717         if (!event_header) {
2718                 ast_log(LOG_WARNING, "Incoming PUBLISH request with no Event header\n");
2719                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2720                 return PJ_TRUE;
2721         }
2722         ast_copy_pj_str(event, &event_header->event_type, sizeof(event));
2723
2724         handler = find_pub_handler(event);
2725         if (!handler) {
2726                 ast_log(LOG_WARNING, "No registered publish handler for event %s\n", event);
2727                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 489, NULL, NULL, NULL);
2728                 return PJ_TRUE;
2729         }
2730
2731         publish_type = determine_sip_publish_type(rdata, etag_hdr, &expires, &entity_id);
2732
2733         /* If this is not an initial publish ensure that a publication is present */
2734         if ((publish_type != SIP_PUBLISH_INITIAL) && (publish_type != SIP_PUBLISH_UNKNOWN)) {
2735                 if (!(publication = ao2_find(handler->publications, &entity_id, OBJ_KEY | OBJ_UNLINK))) {
2736                         static const pj_str_t str_conditional_request_failed = { "Conditional Request Failed", 26 };
2737
2738                         pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 412, &str_conditional_request_failed,
2739                                 NULL, NULL);
2740                         return PJ_TRUE;
2741                 }
2742
2743                 /* Per the RFC every response has to have a new entity tag */
2744                 publication->entity_tag = ast_atomic_fetchadd_int(&esc_etag_counter, +1);
2745
2746                 /* Update the expires here so that the created responses will contain the correct value */
2747                 publication->expires = expires;
2748         }
2749
2750         switch (publish_type) {
2751                 case SIP_PUBLISH_INITIAL:
2752                         publication = publish_request_initial(endpoint, rdata, handler);
2753                         break;
2754                 case SIP_PUBLISH_REFRESH:
2755                 case SIP_PUBLISH_MODIFY:
2756                         if (handler->publication_state_change(publication, rdata->msg_info.msg->body,
2757                                                 AST_SIP_PUBLISH_STATE_ACTIVE)) {
2758                                 /* If an error occurs we want to terminate the publication */
2759                                 expires = 0;
2760                         }
2761                         response = 200;
2762                         break;
2763                 case SIP_PUBLISH_REMOVE:
2764                         handler->publication_state_change(publication, rdata->msg_info.msg->body,
2765                                         AST_SIP_PUBLISH_STATE_TERMINATED);
2766                         response = 200;
2767                         break;
2768                 case SIP_PUBLISH_UNKNOWN:
2769                 default:
2770                         pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 400, NULL, NULL, NULL);
2771                         break;
2772         }
2773
2774         if (publication) {
2775                 if (expires) {
2776                         ao2_link(handler->publications, publication);
2777
2778                         AST_SCHED_REPLACE_UNREF(publication->sched_id, sched, expires * 1000, publish_expire, publication,
2779                                                 ao2_ref(publication, -1), ao2_ref(publication, -1), ao2_ref(publication, +1));
2780                 } else {
2781                         AST_SCHED_DEL_UNREF(sched, publication->sched_id, ao2_ref(publication, -1));
2782                 }
2783         }
2784
2785         if (response) {
2786                 sip_publication_respond(publication, response, rdata);
2787         }
2788
2789         return PJ_TRUE;
2790 }
2791
2792 struct ast_sip_endpoint *ast_sip_publication_get_endpoint(struct ast_sip_publication *pub)
2793 {
2794         return pub->endpoint;
2795 }
2796
2797 const char *ast_sip_publication_get_resource(const struct ast_sip_publication *pub)
2798 {
2799         return pub->resource;
2800 }
2801
2802 const char *ast_sip_publication_get_event_configuration(const struct ast_sip_publication *pub)
2803 {
2804         return pub->event_configuration_name;
2805 }
2806
2807 int ast_sip_pubsub_register_body_generator(struct ast_sip_pubsub_body_generator *generator)
2808 {
2809         struct ast_sip_pubsub_body_generator *existing;
2810         pj_str_t accept;
2811         pj_size_t accept_len;
2812
2813         existing = find_body_generator_type_subtype(generator->type, generator->subtype);
2814         if (existing) {
2815                 ast_log(LOG_WARNING, "Cannot register body generator of %s/%s."
2816                                 "One is already registered.\n", generator->type, generator->subtype);
2817                 return -1;
2818         }
2819
2820         AST_RWLIST_WRLOCK(&body_generators);
2821         AST_LIST_INSERT_HEAD(&body_generators, generator, list);
2822         AST_RWLIST_UNLOCK(&body_generators);
2823
2824         /* Lengths of type and subtype plus space for a slash. pj_str_t is not
2825          * null-terminated, so there is no need to allocate for the extra null
2826          * byte
2827          */
2828         accept_len = strlen(generator->type) + strlen(generator->subtype) + 1;
2829
2830         accept.ptr = alloca(accept_len);
2831         accept.slen = accept_len;
2832         /* Safe use of sprintf */
2833         sprintf(accept.ptr, "%s/%s", generator->type, generator->subtype);
2834         pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), &pubsub_module,
2835                         PJSIP_H_ACCEPT, NULL, 1, &accept);
2836
2837         return 0;
2838 }
2839
2840 void ast_sip_pubsub_unregister_body_generator(struct ast_sip_pubsub_body_generator *generator)
2841 {
2842         struct ast_sip_pubsub_body_generator *iter;
2843         SCOPED_LOCK(lock, &body_generators, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2844
2845         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&body_generators, iter, list) {
2846                 if (iter == generator) {
2847                         AST_LIST_REMOVE_CURRENT(list);
2848                         break;
2849                 }
2850         }
2851         AST_RWLIST_TRAVERSE_SAFE_END;
2852 }
2853
2854 int ast_sip_pubsub_register_body_supplement(struct ast_sip_pubsub_body_supplement *supplement)
2855 {
2856         AST_RWLIST_WRLOCK(&body_supplements);
2857         AST_RWLIST_INSERT_TAIL(&body_supplements, supplement, list);
2858         AST_RWLIST_UNLOCK(&body_supplements);
2859
2860         return 0;
2861 }
2862
2863 void ast_sip_pubsub_unregister_body_supplement(struct ast_sip_pubsub_body_supplement *supplement)
2864 {
2865         struct ast_sip_pubsub_body_supplement *iter;
2866         SCOPED_LOCK(lock, &body_supplements, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
2867
2868         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&body_supplements, iter, list) {
2869                 if (iter == supplement) {
2870                         AST_LIST_REMOVE_CURRENT(list);
2871                         break;
2872                 }
2873         }
2874         AST_RWLIST_TRAVERSE_SAFE_END;
2875 }
2876
2877 const char *ast_sip_subscription_get_body_type(struct ast_sip_subscription *sub)
2878 {
2879         return sub->body_generator->type;
2880 }
2881
2882 const char *ast_sip_subscription_get_body_subtype(struct ast_sip_subscription *sub)
2883 {
2884         return sub->body_generator->subtype;
2885 }
2886
2887 int ast_sip_pubsub_generate_body_content(const char *type, const char *subtype,
2888                 void *data, struct ast_str **str)
2889 {
2890         struct ast_sip_pubsub_body_supplement *supplement;
2891         struct ast_sip_pubsub_body_generator *generator;
2892         int res = 0;
2893         void *body;
2894
2895         generator = find_body_generator_type_subtype(type, subtype);
2896         if (!generator) {
2897                 ast_log(LOG_WARNING, "Unable to find a body generator for %s/%s\n",
2898                                 type, subtype);
2899                 return -1;
2900         }
2901
2902         body = generator->allocate_body(data);
2903         if (!body) {
2904                 ast_log(LOG_WARNING, "Unable to allocate a NOTIFY body of type %s/%s\n",
2905                                 type, subtype);
2906                 return -1;
2907         }
2908
2909         if (generator->generate_body_content(body, data)) {
2910                 res = -1;
2911                 goto end;
2912         }
2913
2914         AST_RWLIST_RDLOCK(&body_supplements);
2915         AST_RWLIST_TRAVERSE(&body_supplements, supplement, list) {
2916                 if (!strcmp(generator->type, supplement->type) &&
2917                                 !strcmp(generator->subtype, supplement->subtype)) {
2918                         res = supplement->supplement_body(body, data);
2919                         if (res) {
2920                                 break;
2921                         }
2922                 }
2923         }
2924         AST_RWLIST_UNLOCK(&body_supplements);
2925
2926         if (!res) {
2927                 generator->to_string(body, str);
2928         }
2929
2930 end:
2931         if (generator->destroy_body) {
2932                 generator->destroy_body(body);
2933         }
2934
2935         return res;
2936 }
2937
2938 static pj_bool_t pubsub_on_rx_request(pjsip_rx_data *rdata)
2939 {
2940         if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_subscribe_method())) {
2941                 return pubsub_on_rx_subscribe_request(rdata);
2942         } else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_publish_method)) {
2943                 return pubsub_on_rx_publish_request(rdata);
2944         }
2945
2946         return PJ_FALSE;
2947 }
2948
2949 static void pubsub_on_evsub_state(pjsip_evsub *evsub, pjsip_event *event)
2950 {
2951         struct sip_subscription_tree *sub_tree;
2952
2953         if (pjsip_evsub_get_state(evsub) != PJSIP_EVSUB_STATE_TERMINATED) {
2954                 return;
2955         }
2956
2957         sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
2958         if (!sub_tree) {
2959                 return;
2960         }
2961
2962         ao2_cleanup(sub_tree);
2963
2964         pjsip_evsub_set_mod_data(evsub, pubsub_module.id, NULL);
2965 }
2966
2967 static void set_state_terminated(struct ast_sip_subscription *sub)
2968 {
2969         int i;
2970
2971         sub->subscription_state = PJSIP_EVSUB_STATE_TERMINATED;
2972         for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {
2973                 set_state_terminated(AST_VECTOR_GET(&sub->children, i));
2974         }
2975 }
2976
2977 static void pubsub_on_rx_refresh(pjsip_evsub *evsub, pjsip_rx_data *rdata,
2978                 int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body)
2979 {
2980         struct sip_subscription_tree *sub_tree;
2981
2982         sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
2983         if (!sub_tree) {
2984                 return;
2985         }
2986
2987         /* If sending a NOTIFY to terminate a subscription, then pubsub_on_evsub_state()
2988          * will be called when we send the NOTIFY, and that will result in dropping the
2989          * refcount of sub_tree by one, and possibly destroying the sub_tree. We need to
2990          * hold a reference to the sub_tree until this function returns so that we don't
2991          * try to read from or write to freed memory by accident
2992          */
2993         ao2_ref(sub_tree, +1);
2994
2995         if (pjsip_evsub_get_state(evsub) == PJSIP_EVSUB_STATE_TERMINATED) {
2996                 set_state_terminated(sub_tree->root);
2997         }
2998
2999         if (send_notify(sub_tree, 1)) {
3000                 *p_st_code = 500;
3001         }
3002
3003         if (sub_tree->is_list) {
3004                 pj_list_insert_before(res_hdr, create_require_eventlist(rdata->tp_info.pool));
3005         }
3006
3007         ao2_ref(sub_tree, -1);
3008 }
3009
3010 static void pubsub_on_rx_notify(pjsip_evsub *evsub, pjsip_rx_data *rdata, int *p_st_code,
3011                 pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body)
3012 {
3013         struct ast_sip_subscription *sub = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3014
3015         if (!sub) {
3016                 return;
3017         }
3018
3019         sub->handler->subscriber->state_change(sub, rdata->msg_info.msg->body,
3020                         pjsip_evsub_get_state(evsub));
3021 }
3022
3023 static int serialized_pubsub_on_client_refresh(void *userdata)
3024 {
3025         struct sip_subscription_tree *sub_tree = userdata;
3026         pjsip_tx_data *tdata;
3027
3028         if (pjsip_evsub_initiate(sub_tree->evsub, NULL, -1, &tdata) == PJ_SUCCESS) {
3029                 pjsip_evsub_send_request(sub_tree->evsub, tdata);
3030         } else {
3031                 pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
3032                 return 0;
3033         }
3034         ao2_cleanup(sub_tree);
3035         return 0;
3036 }
3037
3038 static void pubsub_on_client_refresh(pjsip_evsub *evsub)
3039 {
3040         struct sip_subscription_tree *sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3041
3042         ao2_ref(sub_tree, +1);
3043         ast_sip_push_task(sub_tree->serializer, serialized_pubsub_on_client_refresh, sub_tree);
3044 }
3045
3046 static int serialized_pubsub_on_server_timeout(void *userdata)
3047 {
3048         struct sip_subscription_tree *sub_tree = userdata;
3049
3050         set_state_terminated(sub_tree->root);
3051         send_notify(sub_tree, 1);
3052
3053         ao2_cleanup(sub_tree);
3054         return 0;
3055 }
3056
3057 static void pubsub_on_server_timeout(pjsip_evsub *evsub)
3058 {
3059         struct sip_subscription_tree *sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
3060
3061         if (!sub_tree) {
3062                 /* if a subscription has been terminated and the subscription
3063                    timeout/expires is less than the time it takes for all pending
3064                    transactions to end then the subscription timer will not have
3065                    been canceled yet and sub will be null, so do nothing since
3066                    the subscription has already been terminated. */
3067                 return;
3068         }
3069
3070         ao2_ref(sub_tree, +1);
3071         ast_sip_push_task(sub_tree->serializer, serialized_pubsub_on_server_timeout, sub_tree);
3072 }
3073
3074 static int ami_subscription_detail(struct sip_subscription_tree *sub_tree,
3075                                    struct ast_sip_ami *ami,
3076                                    const char *event)
3077 {
3078         RAII_VAR(struct ast_str *, buf,
3079                  ast_sip_create_ami_event(event, ami), ast_free);
3080
3081         if (!buf) {
3082                 return -1;
3083         }
3084
3085         sip_subscription_to_ami(sub_tree, &buf);
3086         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
3087         return 0;
3088 }
3089
3090 static int ami_subscription_detail_inbound(struct sip_subscription_tree *sub_tree, void *arg)
3091 {
3092         return sub_tree->role == AST_SIP_NOTIFIER ? ami_subscription_detail(
3093                 sub_tree, arg, "InboundSubscriptionDetail") : 0;
3094 }
3095
3096 static int ami_subscription_detail_outbound(struct sip_subscription_tree *sub_tree, void *arg)
3097 {
3098         return sub_tree->role == AST_SIP_SUBSCRIBER ? ami_subscription_detail(
3099                 sub_tree, arg, "OutboundSubscriptionDetail") : 0;
3100 }
3101
3102 static int ami_show_subscriptions_inbound(struct mansession *s, const struct message *m)
3103 {
3104         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
3105         int num;
3106
3107         astman_send_listack(s, m, "Following are Events for "
3108                             "each inbound Subscription", "start");
3109
3110         num = for_each_subscription(ami_subscription_detail_inbound, &ami);
3111
3112         astman_append(s, "Event: InboundSubscriptionDetailComplete\r\n");
3113         if (!ast_strlen_zero(ami.action_id)) {
3114                 astman_append(s, "ActionID: %s\r\n", ami.action_id);
3115         }
3116         astman_append(s, "EventList: Complete\r\n"
3117                       "ListItems: %d\r\n\r\n", num);
3118         return 0;
3119 }
3120
3121 static int ami_show_subscriptions_outbound(struct mansession *s, const struct message *m)
3122 {
3123         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
3124         int num;
3125
3126         astman_send_listack(s, m, "Following are Events for "
3127                             "each outbound Subscription", "start");
3128
3129         num = for_each_subscription(ami_subscription_detail_outbound, &ami);
3130
3131         astman_append(s, "Event: OutboundSubscriptionDetailComplete\r\n");
3132         if (!ast_strlen_zero(ami.action_id)) {
3133                 astman_append(s, "ActionID: %s\r\n", ami.action_id);
3134         }
3135         astman_append(s, "EventList: Complete\r\n"
3136                       "ListItems: %d\r\n\r\n", num);
3137         return 0;
3138 }
3139
3140 static int format_ami_resource_lists(void *obj, void *arg, int flags)
3141 {
3142         struct resource_list *list = obj;
3143         struct ast_sip_ami *ami = arg;
3144         struct ast_str *buf;
3145
3146         buf = ast_sip_create_ami_event("ResourceListDetail", ami);
3147         if (!buf) {
3148                 return CMP_STOP;
3149         }
3150
3151         if (ast_sip_sorcery_object_to_ami(list, &buf)) {
3152                 ast_free(buf);
3153                 return CMP_STOP;
3154         }
3155         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
3156
3157         ast_free(buf);
3158         return 0;
3159 }
3160
3161 static int ami_show_resource_lists(struct mansession *s, const struct message *m)
3162 {
3163         struct ast_sip_ami ami = { .s = s, .m = m };
3164         int num;
3165         struct ao2_container *lists;
3166
3167         lists = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "resource_list",
3168                         AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
3169
3170         if (!lists || !(num = ao2_container_count(lists))) {
3171                 astman_send_error(s, m, "No resource lists found\n");
3172                 return 0;
3173         }
3174
3175         astman_send_listack(s, m, "A listing of resource lists follows, "
3176                             "presented as ResourceListDetail events", "start");
3177
3178         ao2_callback(lists, OBJ_NODATA, format_ami_resource_lists, &ami);
3179
3180         astman_append(s,
3181                       "Event: ResourceListDetailComplete\r\n"
3182                       "EventList: Complete\r\n"
3183                       "ListItems: %d\r\n\r\n", num);
3184         return 0;
3185 }
3186
3187 #define AMI_SHOW_SUBSCRIPTIONS_INBOUND "PJSIPShowSubscriptionsInbound"
3188 #define AMI_SHOW_SUBSCRIPTIONS_OUTBOUND "PJSIPShowSubscriptionsOutbound"
3189
3190 static int persistence_endpoint_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
3191 {
3192         struct subscription_persistence *persistence = obj;
3193
3194         persistence->endpoint = ast_strdup(var->value);
3195         return 0;
3196 }
3197
3198 static int persistence_endpoint_struct2str(const void *obj, const intptr_t *args, char **buf)
3199 {
3200         const struct subscription_persistence *persistence = obj;
3201
3202         *buf = ast_strdup(persistence->endpoint);
3203         return 0;
3204 }
3205
3206 static int persistence_tag_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
3207 {
3208         struct subscription_persistence *persistence = obj;
3209
3210         persistence->tag = ast_strdup(var->value);
3211         return 0;
3212 }
3213
3214 static int persistence_tag_struct2str(const void *obj, const intptr_t *args, char **buf)
3215 {
3216         const struct subscription_persistence *persistence = obj;
3217
3218         *buf = ast_strdup(persistence->tag);
3219         return 0;
3220 }
3221
3222 static int persistence_expires_str2struct(const struct aco_option *opt, struct ast_variable *var, void *obj)
3223 {
3224         struct subscription_persistence *persistence = obj;
3225         return ast_get_timeval(var->value, &persistence->expires, ast_tv(0, 0), NULL);
3226 }
3227
3228 static int persistence_expires_struct2str(const void *obj, const intptr_t *args, char **buf)
3229 {
3230         const struct subscription_persistence *persistence = obj;
3231         return (ast_asprintf(buf, "%ld", persistence->expires.tv_sec) < 0) ? -1 : 0;
3232 }
3233
3234 #define RESOURCE_LIST_INIT_SIZE 4
3235
3236 static void resource_list_destructor(void *obj)
3237 {
3238         struct resource_list *list = obj;
3239         int i;
3240
3241         for (i = 0; i < AST_VECTOR_SIZE(&list->items); ++i) {
3242                 ast_free((char *) AST_VECTOR_GET(&list->items, i));
3243         }
3244
3245         AST_VECTOR_FREE(&list->items);
3246 }
3247
3248 static void *resource_list_alloc(const char *name)
3249 {
3250         struct resource_list *list;
3251
3252         list = ast_sorcery_generic_alloc(sizeof(*list), resource_list_destructor);
3253         if (!list) {
3254                 return NULL;
3255         }
3256
3257         if (AST_VECTOR_INIT(&list->items, RESOURCE_LIST_INIT_SIZE)) {
3258                 ao2_cleanup(list);
3259                 return NULL;
3260         }
3261
3262         return list;
3263 }
3264
3265 static int item_in_vector(const struct resource_list *list, const char *item)
3266 {
3267         int i;
3268
3269         for (i = 0; i < AST_VECTOR_SIZE(&list->items); ++i) {
3270                 if (!strcmp(item, AST_VECTOR_GET(&list->items, i))) {
3271                         return 1;
3272                 }
3273         }
3274
3275         return 0;
3276 }
3277
3278 static int list_item_handler(const struct aco_option *opt,
3279                 struct ast_variable *var, void *obj)
3280 {
3281         struct resource_list *list = obj;
3282         char *items = ast_strdupa(var->value);
3283         char *item;
3284
3285         while ((item = strsep(&items, ","))) {
3286                 if (item_in_vector(list, item)) {
3287                         ast_log(LOG_WARNING, "Ignoring duplicated list item '%s'\n", item);
3288                         continue;
3289                 }
3290                 if (AST_VECTOR_APPEND(&list->items, ast_strdup(item))) {
3291                         return -1;
3292                 }
3293         }
3294
3295         return 0;
3296 }
3297
3298 static int list_item_to_str(const void *obj, const intptr_t *args, char **buf)
3299 {
3300         const struct resource_list *list = obj;
3301         int i;
3302         struct ast_str *str = ast_str_create(32);
3303
3304         for (i = 0; i < AST_VECTOR_SIZE(&list->items); ++i) {
3305                 ast_str_append(&str, 0, "%s,", AST_VECTOR_GET(&list->items, i));
3306         }
3307
3308         /* Chop off trailing comma */
3309         ast_str_truncate(str, -1);
3310         *buf = ast_strdup(ast_str_buffer(str));
3311         ast_free(str);
3312         return 0;
3313 }
3314
3315 static int resource_list_apply_handler(const struct ast_sorcery *sorcery, void *obj)
3316 {
3317         struct resource_list *list = obj;
3318
3319         if (ast_strlen_zero(list->event)) {
3320                 ast_log(LOG_WARNING, "Resource list '%s' has no event set\n",
3321                                 ast_sorcery_object_get_id(list));
3322                 return -1;
3323         }
3324
3325         if (AST_VECTOR_SIZE(&list->items) == 0) {
3326                 ast_log(LOG_WARNING, "Resource list '%s' has no list items\n",
3327                                 ast_sorcery_object_get_id(list));
3328                 return -1;
3329         }
3330
3331         return 0;
3332 }
3333
3334 static int apply_list_configuration(struct ast_sorcery *sorcery)
3335 {
3336         ast_sorcery_apply_default(sorcery, "resource_list", "config",
3337                         "pjsip.conf,criteria=type=resource_list");
3338         if (ast_sorcery_object_register(sorcery, "resource_list", resource_list_alloc,
3339                                 NULL, resource_list_apply_handler)) {
3340                 return -1;
3341         }
3342
3343         ast_sorcery_object_field_register(sorcery, "resource_list", "type", "",
3344                         OPT_NOOP_T, 0, 0);
3345         ast_sorcery_object_field_register(sorcery, "resource_list", "event", "",
3346                         OPT_CHAR_ARRAY_T, 1, CHARFLDSET(struct resource_list, event));
3347         ast_sorcery_object_field_register(sorcery, "resource_list", "full_state", "no",
3348                         OPT_BOOL_T, 1, FLDSET(struct resource_list, full_state));
3349         ast_sorcery_object_field_register(sorcery, "resource_list", "notification_batch_interval",
3350                         "0", OPT_UINT_T, 0, FLDSET(struct resource_list, notification_batch_interval));
3351         ast_sorcery_object_field_register_custom(sorcery, "resource_list", "list_item",
3352                         "", list_item_handler, list_item_to_str, NULL, 0, 0);
3353
3354         ast_sorcery_reload_object(sorcery, "resource_list");
3355
3356         return 0;
3357 }
3358
3359 #ifdef TEST_FRAMEWORK
3360
3361 /*!
3362  * \brief "bad" resources
3363  *
3364  * These are resources that the test handler will reject subscriptions to.
3365  */
3366 const char *bad_resources[] = {
3367         "coconut",
3368         "cilantro",
3369         "olive",
3370         "cheese",
3371 };
3372
3373 /*!
3374  * \brief new_subscribe callback for unit tests
3375  *
3376  * Will give a 200 OK response to any resource except the "bad" ones.
3377  */
3378 static int test_new_subscribe(struct ast_sip_endpoint *endpoint, const char *resource)
3379 {
3380         int i;
3381
3382         for (i = 0; i < ARRAY_LEN(bad_resources); ++i) {
3383                 if (!strcmp(resource, bad_resources[i])) {
3384                         return 400;
3385                 }
3386         }
3387
3388         return 200;
3389 }
3390
3391 /*!
3392  * \brief Subscription notifier for unit tests.
3393  *
3394  * Since unit tests are only concerned with building a resource tree,
3395  * only the new_subscribe callback needs to be defined.
3396  */
3397 struct ast_sip_notifier test_notifier = {
3398         .new_subscribe = test_new_subscribe,
3399 };
3400
3401 /*!
3402  * \brief Subscription handler for unit tests.
3403  */
3404 struct ast_sip_subscription_handler test_handler = {
3405         .event_name = "test",
3406         .notifier = &test_notifier,
3407 };
3408
3409 /*!
3410  * \brief Set properties on an allocated resource list
3411  *
3412  * \param list The list to set details on.
3413  * \param event The list's event.
3414  * \param resources Array of resources to add to the list.
3415  * \param num_resources Number of resources in the array.
3416  * \retval 0 Success
3417  * \retval non-zero Failure
3418  */
3419 static int populate_list(struct resource_list *list, const char *event, const char **resources, size_t num_resources)
3420 {
3421         int i;
3422
3423         ast_copy_string(list->event, event, sizeof(list->event));
3424
3425         for (i = 0; i < num_resources; ++i) {
3426                 if (AST_VECTOR_APPEND(&list->items, ast_strdup(resources[i]))) {
3427                         return -1;
3428                 }
3429         }
3430         return 0;
3431 }
3432
3433 /*!
3434  * \brief RAII callback to destroy a resource list
3435  */
3436 static void cleanup_resource_list(struct resource_list *list)
3437 {
3438         if (!list) {
3439                 return;
3440         }
3441
3442         ast_sorcery_delete(ast_sip_get_sorcery(), list);
3443         ao2_cleanup(list);
3444 }
3445
3446 /*!
3447  * \brief allocate a resource list, store it in sorcery, and set its details
3448  *
3449  * \param test The unit test. Used for logging status messages.
3450  * \param list_name The name of the list to create.
3451  * \param event The event the list services
3452  * \param resources Array of resources to apply to the list
3453  * \param num_resources The number of resources in the array
3454  * \retval NULL Failed to allocate or populate list
3455  * \retval non-NULL The created list
3456  */
3457 static struct resource_list *create_resource_list(struct ast_test *test,
3458                 const char *list_name, const char *event, const char **resources, size_t num_resources)
3459 {
3460         struct resource_list *list;
3461
3462         list = ast_sorcery_alloc(ast_sip_get_sorcery(), "resource_list", list_name);
3463         if (!list) {
3464                 ast_test_status_update(test, "Could not allocate resource list in sorcery\n");
3465                 return NULL;
3466         }
3467
3468         if (ast_sorcery_create(ast_sip_get_sorcery(), list)) {
3469                 ast_test_status_update(test, "Could not store the resource list in sorcery\n");
3470                 ao2_cleanup(list);
3471                 return NULL;
3472         }
3473
3474         if (populate_list(list, event, resources, num_resources)) {
3475                 ast_test_status_update(test, "Could not add resources to the resource list\n");
3476                 cleanup_resource_list(list);
3477                 return NULL;
3478         }
3479
3480         return list;
3481 }
3482
3483 /*!
3484  * \brief Check the integrity of a tree node against a set of resources.
3485  *
3486  * The tree node's resources must be in the same order as the resources in
3487  * the supplied resources array. Because of this constraint, tests can misrepresent
3488  * the size of the resources array as being smaller than it really is if resources
3489  * at the end of the array should not be present in the tree node.
3490  *
3491  * \param test The unit test. Used for printing status messages.
3492  * \param node The constructed tree node whose integrity is under question.
3493  * \param resources Array of expected resource values
3494  * \param num_resources The number of resources to check in the array.
3495  */
3496 static int check_node(struct ast_test *test, struct tree_node *node,
3497                 const char **resources, size_t num_resources)
3498 {
3499         int i;
3500
3501         if (AST_VECTOR_SIZE(&node->children) != num_resources) {
3502                 ast_test_status_update(test, "Unexpected number of resources in tree. Expected %zu, got %zu\n",
3503                                 num_resources, AST_VECTOR_SIZE(&node->children));
3504                 return -1;
3505         }
3506
3507         for (i = 0; i < num_resources; ++i) {
3508                 if (strcmp(resources[i], AST_VECTOR_GET(&node->children, i)->resource)) {
3509                         ast_test_status_update(test, "Mismatched resources. Expected '%s' but got '%s'\n",
3510                                         resources[i], AST_VECTOR_GET(&node->children, i)->resource);
3511                         return -1;
3512                 }
3513         }
3514
3515         return 0;
3516 }
3517
3518 /*!
3519  * \brief RAII_VAR callback to destroy an allocated resource tree
3520  */
3521 static void test_resource_tree_destroy(struct resource_tree *tree)
3522 {
3523         resource_tree_destroy(tree);
3524         ast_free(tree);
3525 }
3526
3527 AST_TEST_DEFINE(resource_tree)
3528 {
3529         RAII_VAR(struct resource_list *, list, NULL, cleanup_resource_list);
3530         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3531         const char *resources[] = {
3532                 "huey",
3533                 "dewey",
3534                 "louie",
3535         };
3536         int resp;
3537
3538         switch (cmd) {
3539         case TEST_INIT:
3540                 info->name = "resource_tree";
3541                 info->category = "/res/res_pjsip_pubsub/";
3542                 info->summary = "Basic resource tree integrity check";
3543                 info->description =
3544                         "Create a resource list and ensure that our attempt to build a tree works as expected.";
3545                 return AST_TEST_NOT_RUN;
3546         case TEST_EXECUTE:
3547                 break;
3548         }
3549
3550         list = create_resource_list(test, "foo", "test", resources, ARRAY_LEN(resources));
3551         if (!list) {
3552                 return AST_TEST_FAIL;
3553         }
3554
3555         tree = ast_calloc(1, sizeof(*tree));
3556         resp = build_resource_tree(NULL, &test_handler, "foo", tree);
3557         if (resp != 200) {
3558                 ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
3559                 return AST_TEST_FAIL;
3560         }
3561
3562         if (!tree->root) {
3563                 ast_test_status_update(test, "Resource tree has no root\n");
3564                 return AST_TEST_FAIL;
3565         }
3566
3567         if (check_node(test, tree->root, resources, ARRAY_LEN(resources))) {
3568                 return AST_TEST_FAIL;
3569         }
3570
3571         return AST_TEST_PASS;
3572 }
3573
3574 AST_TEST_DEFINE(complex_resource_tree)
3575 {
3576         RAII_VAR(struct resource_list *, list_1, NULL, cleanup_resource_list);
3577         RAII_VAR(struct resource_list *, list_2, NULL, cleanup_resource_list);
3578         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3579         const char *resources_1[] = {
3580                 "huey",
3581                 "dewey",
3582                 "louie",
3583                 "dwarves",
3584         };
3585         const char *resources_2[] = {
3586                 "happy",
3587                 "grumpy",
3588                 "doc",
3589                 "bashful",
3590                 "dopey",
3591                 "sneezy",
3592                 "sleepy",
3593         };
3594         int resp;
3595         struct tree_node *node;
3596
3597         switch (cmd) {
3598         case TEST_INIT:
3599                 info->name = "complex_resource_tree";
3600                 info->category = "/res/res_pjsip_pubsub/";
3601                 info->summary = "Complex resource tree integrity check";
3602                 info->description =
3603                         "Create a complex resource list and ensure that our attempt to build a tree works as expected.";
3604                 return AST_TEST_NOT_RUN;
3605         case TEST_EXECUTE:
3606                 break;
3607         }
3608
3609         list_1 = create_resource_list(test, "foo", "test", resources_1, ARRAY_LEN(resources_1));
3610         if (!list_1) {
3611                 return AST_TEST_FAIL;
3612         }
3613
3614         list_2 = create_resource_list(test, "dwarves", "test", resources_2, ARRAY_LEN(resources_2));
3615         if (!list_2) {
3616                 return AST_TEST_FAIL;
3617         }
3618
3619         tree = ast_calloc(1, sizeof(*tree));
3620         resp = build_resource_tree(NULL, &test_handler, "foo", tree);
3621         if (resp != 200) {
3622                 ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
3623                 return AST_TEST_FAIL;
3624         }
3625
3626         if (!tree->root) {
3627                 ast_test_status_update(test, "Resource tree has no root\n");
3628                 return AST_TEST_FAIL;
3629         }
3630
3631         node = tree->root;
3632         if (check_node(test, node, resources_1, ARRAY_LEN(resources_1))) {
3633                 return AST_TEST_FAIL;
3634         }
3635
3636         /* The embedded list is at index 3 in the root node's children */
3637         node = AST_VECTOR_GET(&node->children, 3);
3638         if (check_node(test, node, resources_2, ARRAY_LEN(resources_2))) {
3639                 return AST_TEST_FAIL;
3640         }
3641
3642         return AST_TEST_PASS;
3643 }
3644
3645 AST_TEST_DEFINE(bad_resource)
3646 {
3647         RAII_VAR(struct resource_list *, list, NULL, cleanup_resource_list);
3648         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3649         const char *resources[] = {
3650                 "huey",
3651                 "dewey",
3652                 "louie",
3653                 "coconut", /* A "bad" resource */
3654         };
3655         int resp;
3656
3657         switch (cmd) {
3658         case TEST_INIT:
3659                 info->name = "bad_resource";
3660                 info->category = "/res/res_pjsip_pubsub/";
3661                 info->summary = "Ensure bad resources do not end up in the tree";
3662                 info->description =
3663                         "Create a resource list with a single bad resource. Ensure the bad resource does not end up in the tree.";
3664                 return AST_TEST_NOT_RUN;
3665         case TEST_EXECUTE:
3666                 break;
3667         }
3668
3669         list = create_resource_list(test, "foo", "test", resources, ARRAY_LEN(resources));
3670         if (!list) {
3671                 return AST_TEST_FAIL;
3672         }
3673
3674         tree = ast_calloc(1, sizeof(*tree));
3675         resp = build_resource_tree(NULL, &test_handler, "foo", tree);
3676         if (resp != 200) {
3677                 ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
3678                 return AST_TEST_FAIL;
3679         }
3680
3681         if (!tree->root) {
3682                 ast_test_status_update(test, "Resource tree has no root\n");
3683                 return AST_TEST_FAIL;
3684         }
3685
3686         /* We check against all but the final resource since we expect it not to be in the tree */
3687         if (check_node(test, tree->root, resources, ARRAY_LEN(resources) - 1)) {
3688                 return AST_TEST_FAIL;
3689         }
3690
3691         return AST_TEST_PASS;
3692
3693 }
3694
3695 AST_TEST_DEFINE(bad_branch)
3696 {
3697         RAII_VAR(struct resource_list *, list_1, NULL, cleanup_resource_list);
3698         RAII_VAR(struct resource_list *, list_2, NULL, cleanup_resource_list);
3699         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3700         const char *resources_1[] = {
3701                 "huey",
3702                 "dewey",
3703                 "louie",
3704                 "gross",
3705         };
3706         /* This list has nothing but bad resources */
3707         const char *resources_2[] = {
3708                 "coconut",
3709                 "cilantro",
3710                 "olive",
3711                 "cheese",
3712         };
3713         int resp;
3714
3715         switch (cmd) {
3716         case TEST_INIT:
3717                 info->name = "bad_branch";
3718                 info->category = "/res/res_pjsip_pubsub/";
3719                 info->summary = "Ensure bad branches are pruned from the tree";
3720                 info->description =
3721                         "Create a resource list that makes a tree with an entire branch of bad resources.\n"
3722                         "Ensure the bad branch is pruned from the tree.";
3723                 return AST_TEST_NOT_RUN;
3724         case TEST_EXECUTE:
3725                 break;
3726         }
3727
3728         list_1 = create_resource_list(test, "foo", "test", resources_1, ARRAY_LEN(resources_1));
3729         if (!list_1) {
3730                 return AST_TEST_FAIL;
3731         }
3732         list_2 = create_resource_list(test, "gross", "test", resources_2, ARRAY_LEN(resources_2));
3733         if (!list_2) {
3734                 return AST_TEST_FAIL;
3735         }
3736
3737         tree = ast_calloc(1, sizeof(*tree));
3738         resp = build_resource_tree(NULL, &test_handler, "foo", tree);
3739         if (resp != 200) {
3740                 ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
3741                 return AST_TEST_FAIL;
3742         }
3743
3744         if (!tree->root) {
3745                 ast_test_status_update(test, "Resource tree has no root\n");
3746                 return AST_TEST_FAIL;
3747         }
3748
3749         /* We check against all but the final resource of the list since the entire branch should
3750          * be pruned from the tree
3751          */
3752         if (check_node(test, tree->root, resources_1, ARRAY_LEN(resources_1) - 1)) {
3753                 return AST_TEST_FAIL;
3754         }
3755
3756         return AST_TEST_PASS;
3757
3758 }
3759
3760 AST_TEST_DEFINE(duplicate_resource)
3761 {
3762         RAII_VAR(struct resource_list *, list_1, NULL, cleanup_resource_list);
3763         RAII_VAR(struct resource_list *, list_2, NULL, cleanup_resource_list);
3764         RAII_VAR(struct resource_tree *, tree, NULL, test_resource_tree_destroy);
3765         const char *resources_1[] = {
3766                 "huey",
3767                 "ducks",
3768                 "dewey",
3769                 "louie",
3770         };
3771         const char *resources_2[] = {
3772                 "donald",
3773                 "daisy",
3774                 "scrooge",
3775                 "dewey",
3776                 "louie",
3777                 "huey",
3778         };
3779         int resp;
3780         struct tree_node *node;
3781
3782         switch (cmd) {
3783         case TEST_INIT:
3784                 info->name = "duplicate_resource";
3785                 info->category = "/res/res_pjsip_pubsub/";
3786                 info->summary = "Ensure duplicated resources do not end up in the tree";
3787                 info->description =
3788                         "Create a resource list with a single duplicated resource. Ensure the duplicated resource does not end up in the tree.";
3789                 return AST_TEST_NOT_RUN;
3790         case TEST_EXECUTE:
3791                 break;
3792         }
3793
3794         list_1 = create_resource_list(test, "foo", "test", resources_1, ARRAY_LEN(resources_1));
3795         if (!list_1) {
3796                 return AST_TEST_FAIL;
3797         }
3798
3799         list_2 = create_resource_list(test, "ducks", "test", resources_2, ARRAY_LEN(resources_2));
3800         if (!list_2) {
3801                 return AST_TEST_FAIL;
3802         }
3803
3804         tree = ast_calloc(1, sizeof(*tree));
3805         resp = build_resource_tree(NULL, &test_handler, "foo", tree);
3806         if (resp != 200) {
3807                 ast_test_status_update(test, "Unexpected response %d when building resource tree\n", r