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