build: Update config.guess and config.sub
[asterisk/asterisk.git] / res / res_pjsip_outbound_publish.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2014, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@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 /*** MODULEINFO
20         <depend>pjproject</depend>
21         <depend>res_pjproject</depend>
22         <depend>res_pjsip</depend>
23         <support_level>core</support_level>
24  ***/
25
26 #include "asterisk.h"
27
28 #include <pjsip.h>
29 #include <pjsip_simple.h>
30
31 #include "asterisk/res_pjproject.h"
32 #include "asterisk/res_pjsip.h"
33 #include "asterisk/res_pjsip_outbound_publish.h"
34 #include "asterisk/module.h"
35 #include "asterisk/taskprocessor.h"
36 #include "asterisk/threadpool.h"
37 #include "asterisk/datastore.h"
38 #include "res_pjsip/include/res_pjsip_private.h"
39
40 /*** DOCUMENTATION
41         <configInfo name="res_pjsip_outbound_publish" language="en_US">
42                 <synopsis>SIP resource for outbound publish</synopsis>
43                 <description><para>
44                         <emphasis>Outbound Publish</emphasis>
45                         </para>
46                         <para>This module allows <literal>res_pjsip</literal> to publish to other SIP servers.</para>
47                 </description>
48                 <configFile name="pjsip.conf">
49                         <configObject name="outbound-publish">
50                                 <synopsis>The configuration for outbound publish</synopsis>
51                                 <description><para>
52                                         Publish is <emphasis>COMPLETELY</emphasis> separate from the rest of
53                                         <literal>pjsip.conf</literal>. A minimal configuration consists of
54                                         setting a <literal>server_uri</literal> and <literal>event</literal>.
55                                 </para></description>
56                                 <configOption name="expiration" default="3600">
57                                         <synopsis>Expiration time for publications in seconds</synopsis>
58                                 </configOption>
59                                 <configOption name="outbound_auth" default="">
60                                         <synopsis>Authentication object(s) to be used for outbound publishes.</synopsis>
61                                         <description><para>
62                                                 This is a comma-delimited list of <replaceable>auth</replaceable>
63                                                 sections defined in <filename>pjsip.conf</filename> used to respond
64                                                 to outbound authentication challenges.</para>
65                                                 <note><para>
66                                                 Using the same auth section for inbound and outbound
67                                                 authentication is not recommended.  There is a difference in
68                                                 meaning for an empty realm setting between inbound and outbound
69                                                 authentication uses.  See the auth realm description for details.
70                                                 </para></note>
71                                         </description>
72                                 </configOption>
73                                 <configOption name="outbound_proxy" default="">
74                                         <synopsis>Full SIP URI of the outbound proxy used to send publishes</synopsis>
75                                 </configOption>
76                                 <configOption name="server_uri">
77                                         <synopsis>SIP URI of the server and entity to publish to</synopsis>
78                                         <description><para>
79                                                 This is the URI at which to find the entity and server to send the outbound PUBLISH to.
80                                                 This URI is used as the request URI of the outbound PUBLISH request from Asterisk.
81                                         </para></description>
82                                 </configOption>
83                                 <configOption name="from_uri">
84                                         <synopsis>SIP URI to use in the From header</synopsis>
85                                         <description><para>
86                                                 This is the URI that will be placed into the From header of outgoing PUBLISH
87                                                 messages. If no URI is specified then the URI provided in <literal>server_uri</literal>
88                                                 will be used.
89                                         </para></description>
90                                 </configOption>
91                                 <configOption name="to_uri">
92                                         <synopsis>SIP URI to use in the To header</synopsis>
93                                         <description><para>
94                                                 This is the URI that will be placed into the To header of outgoing PUBLISH
95                                                 messages. If no URI is specified then the URI provided in <literal>server_uri</literal>
96                                                 will be used.
97                                         </para></description>
98                                 </configOption>
99                                 <configOption name="event" default="">
100                                         <synopsis>Event type of the PUBLISH.</synopsis>
101                                 </configOption>
102                                 <configOption name="max_auth_attempts" default="5">
103                                         <synopsis>Maximum number of authentication attempts before stopping the publication.</synopsis>
104                                 </configOption>
105                                 <configOption name="transport">
106                                         <synopsis>Transport used for outbound publish</synopsis>
107                                         <description>
108                                                 <note><para>A <replaceable>transport</replaceable> configured in
109                                                 <literal>pjsip.conf</literal>. As with other <literal>res_pjsip</literal> modules, this will use the first available transport of the appropriate type if unconfigured.</para></note>
110                                         </description>
111                                 </configOption>
112                                 <configOption name="multi_user" default="no">
113                                         <synopsis>Enable multi-user support</synopsis>
114                                         <description><para>When enabled the user portion of the server uri is replaced by a dynamically created user</para></description>
115                                 </configOption>
116                                 <configOption name="type">
117                                         <synopsis>Must be of type 'outbound-publish'.</synopsis>
118                                 </configOption>
119                         </configObject>
120                 </configFile>
121         </configInfo>
122  ***/
123
124 static int pjsip_max_url_size = PJSIP_MAX_URL_SIZE;
125
126 /*! \brief Queued outbound publish message */
127 struct sip_outbound_publish_message {
128         /*! \brief Optional body */
129         struct ast_sip_body body;
130         /*! \brief Linked list information */
131         AST_LIST_ENTRY(sip_outbound_publish_message) entry;
132         /*! \brief Extra space for body contents */
133         char body_contents[0];
134 };
135
136 /*
137  * A note about some of the object types used in this module:
138  *
139  * The reason we currently have 4 separate object types that relate to configuration,
140  * publishing, state, and client information is due to object lifetimes and order of
141  * destruction dependencies.
142  *
143  * Separation of concerns is a good thing and of course it makes sense to have a
144  * configuration object type as well as an object type wrapper around pjsip's publishing
145  * client class. There also may be run time state data that needs to be tracked, so
146  * again having something to handle that is prudent. However, it may be tempting to think
147  * "why not combine the state and client object types?" Especially seeing as how they have
148  * a one-to-one relationship. The answer is, it's possible, but it'd make the code a bit
149  * more awkward.
150  *
151  * Currently this module maintains a global container of current state objects. When this
152  * states container is replaced, or deleted, it un-references all contained objects. Any
153  * state with a reference left have probably been carried over from a reload/realtime fetch.
154  * States not carried over are destructed and the associated client (and all its publishers)
155  * get unpublished.
156  *
157  * This "unpublishing" goes through a careful process of unpublishing the client, all its
158  * publishers, and making sure all the appropriate references are removed in a sane order.
159  * This process is essentially kicked off with the destruction of the state. If the state
160  * and client objects were to be merged, where clients became the globally tracked object
161  * type, this "unpublishing" process would never start because of the multiple references
162  * held to the client object over it's lifetime. Meaning the global tracking container
163  * would remove its reference to the client object when done with it, but other sources
164  * would still be holding a reference to it (namely the datastore and publisher(s)).
165  *
166  * Thus at this time it is easier to keep them separate.
167  */
168
169 /*! \brief Outbound publish information */
170 struct ast_sip_outbound_publish {
171         /*! \brief Sorcery object details */
172         SORCERY_OBJECT(details);
173         /*! \brief Stringfields */
174         AST_DECLARE_STRING_FIELDS(
175                 /*! \brief URI for the entity and server */
176                 AST_STRING_FIELD(server_uri);
177                 /*! \brief URI for the From header */
178                 AST_STRING_FIELD(from_uri);
179                 /*! \brief URI for the To header */
180                 AST_STRING_FIELD(to_uri);
181                 /*! \brief Explicit transport to use for publish */
182                 AST_STRING_FIELD(transport);
183                 /*! \brief Outbound proxy to use */
184                 AST_STRING_FIELD(outbound_proxy);
185                 /*! \brief The event type to publish */
186                 AST_STRING_FIELD(event);
187         );
188         /*! \brief Requested expiration time */
189         unsigned int expiration;
190         /*! \brief Maximum number of auth attempts before stopping the publish client */
191         unsigned int max_auth_attempts;
192         /*! \brief Configured authentication credentials */
193         struct ast_sip_auth_vector outbound_auths;
194         /*! \brief The publishing client is used for multiple users when true */
195         unsigned int multi_user;
196 };
197
198 struct sip_outbound_publisher {
199         /*! \brief The client object that 'owns' this client
200
201              \note any potential circular reference problems are accounted
202              for (see publisher alloc for more information)
203         */
204         struct ast_sip_outbound_publish_client *owner;
205         /*! \brief Underlying publish client */
206         pjsip_publishc *client;
207         /*! \brief The From URI for this specific publisher */
208         char *from_uri;
209         /*! \brief The To URI for this specific publisher */
210         char *to_uri;
211         /*! \brief Timer entry for refreshing publish */
212         pj_timer_entry timer;
213         /*! \brief The number of auth attempts done */
214         unsigned int auth_attempts;
215         /*! \brief Queue of outgoing publish messages to send*/
216         AST_LIST_HEAD_NOLOCK(, sip_outbound_publish_message) queue;
217         /*! \brief The message currently being sent */
218         struct sip_outbound_publish_message *sending;
219         /*! \brief Publish client should be destroyed */
220         unsigned int destroy;
221         /*! \brief Serializer for stuff and things */
222         struct ast_taskprocessor *serializer;
223         /*! \brief User, if any, associated with the publisher */
224         char user[0];
225 };
226
227 /*! \brief Outbound publish client state information (persists for lifetime of a publish) */
228 struct ast_sip_outbound_publish_client {
229         /*! \brief Outbound publish information */
230         struct ast_sip_outbound_publish *publish;
231         /*! \brief Publisher datastores set up by handlers */
232         struct ao2_container *datastores;
233         /*! \brief Container of all the client publishing objects */
234         struct ao2_container *publishers;
235         /*! \brief Publishing has been fully started and event type informed */
236         unsigned int started;
237 };
238
239 /*! \brief Outbound publish state information (persists for lifetime of a publish) */
240 struct ast_sip_outbound_publish_state {
241         /*! \brief Outbound publish client */
242         struct ast_sip_outbound_publish_client *client;
243         /* publish state id lookup key - same as publish configuration id */
244         char id[0];
245 };
246
247 /*!
248  * \brief Used for locking while loading/reloading
249  *
250  * Mutli-user configurations make it so publishers can be dynamically added and
251  * removed. Publishers should not be added or removed during a [re]load since
252  * it could cause the current_clients container to be out of sync. Thus the
253  * reason for this lock.
254  */
255 AST_RWLOCK_DEFINE_STATIC(load_lock);
256
257 #define DEFAULT_PUBLISHER_BUCKETS 119
258 AO2_STRING_FIELD_HASH_FN(sip_outbound_publisher, user);
259 AO2_STRING_FIELD_CMP_FN(sip_outbound_publisher, user);
260
261 /*! Time needs to be long enough for a transaction to timeout if nothing replies. */
262 #define MAX_UNLOAD_TIMEOUT_TIME         35      /* Seconds */
263
264 /*! Shutdown group to monitor sip_outbound_registration_client_state serializers. */
265 static struct ast_serializer_shutdown_group *shutdown_group;
266
267 /*! \brief Default number of client state container buckets */
268 #define DEFAULT_STATE_BUCKETS 31
269 static AO2_GLOBAL_OBJ_STATIC(current_states);
270 /*! \brief Used on [re]loads to hold new state data */
271 static struct ao2_container *new_states;
272
273 /*! \brief hashing function for state objects */
274 static int outbound_publish_state_hash(const void *obj, const int flags)
275 {
276         const struct ast_sip_outbound_publish_state *object;
277         const char *key;
278
279         switch (flags & OBJ_SEARCH_MASK) {
280         case OBJ_SEARCH_KEY:
281                 key = obj;
282                 break;
283         case OBJ_SEARCH_OBJECT:
284                 object = obj;
285                 key = object->id;
286                 break;
287         default:
288                 ast_assert(0);
289                 return 0;
290         }
291         return ast_str_hash(key);
292 }
293
294 /*! \brief comparator function for client objects */
295 static int outbound_publish_state_cmp(void *obj, void *arg, int flags)
296 {
297         const struct ast_sip_outbound_publish_state *object_left = obj;
298         const struct ast_sip_outbound_publish_state *object_right = arg;
299         const char *right_key = arg;
300         int cmp;
301
302         switch (flags & OBJ_SEARCH_MASK) {
303         case OBJ_SEARCH_OBJECT:
304                 right_key = object_right->id;
305                 /* Fall through */
306         case OBJ_SEARCH_KEY:
307                 cmp = strcmp(object_left->id, right_key);
308                 break;
309         case OBJ_SEARCH_PARTIAL_KEY:
310                 /* Not supported by container. */
311                 ast_assert(0);
312                 return 0;
313         default:
314                 cmp = 0;
315                 break;
316         }
317         if (cmp) {
318                 return 0;
319         }
320         return CMP_MATCH;
321 }
322
323 static struct ao2_container *get_publishes_and_update_state(void)
324 {
325         struct ao2_container *container;
326         SCOPED_WRLOCK(lock, &load_lock);
327
328         container = ast_sorcery_retrieve_by_fields(
329                 ast_sip_get_sorcery(), "outbound-publish",
330                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
331
332         if (!new_states) {
333                 return container;
334         }
335
336         ao2_global_obj_replace_unref(current_states, new_states);
337         ao2_cleanup(new_states);
338         new_states = NULL;
339
340         return container;
341 }
342
343 AST_RWLIST_HEAD_STATIC(publisher_handlers, ast_sip_event_publisher_handler);
344
345 static void sub_add_handler(struct ast_sip_event_publisher_handler *handler)
346 {
347         AST_RWLIST_INSERT_TAIL(&publisher_handlers, handler, next);
348 }
349
350 static struct ast_sip_event_publisher_handler *find_publisher_handler_for_event_name(const char *event_name)
351 {
352         struct ast_sip_event_publisher_handler *iter;
353
354         AST_RWLIST_TRAVERSE(&publisher_handlers, iter, next) {
355                 if (!strcmp(iter->event_name, event_name)) {
356                         break;
357                 }
358         }
359         return iter;
360 }
361
362 /*! \brief Helper function which cancels the refresh timer on a publisher */
363 static void cancel_publish_refresh(struct sip_outbound_publisher *publisher)
364 {
365         if (pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
366                 &publisher->timer, 0)) {
367                 /* The timer was successfully cancelled, drop the refcount of the publisher */
368                 ao2_ref(publisher, -1);
369         }
370 }
371
372 /*! \brief Helper function which sets up the timer to send publication */
373 static void schedule_publish_refresh(struct sip_outbound_publisher *publisher, int expiration)
374 {
375         struct ast_sip_outbound_publish *publish = ao2_bump(publisher->owner->publish);
376         pj_time_val delay = { .sec = 0, };
377
378         cancel_publish_refresh(publisher);
379
380         if (expiration > 0) {
381                 delay.sec = expiration - PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH;
382         }
383         if (publish->expiration && ((delay.sec > publish->expiration) || !delay.sec)) {
384                 delay.sec = publish->expiration;
385         }
386         if (delay.sec < PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH) {
387                 delay.sec = PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH;
388         }
389
390         ao2_ref(publisher, +1);
391         if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &publisher->timer, &delay) != PJ_SUCCESS) {
392                 ast_log(LOG_WARNING, "Failed to pass timed publish refresh to scheduler\n");
393                 ao2_ref(publisher, -1);
394         }
395         ao2_ref(publish, -1);
396 }
397
398 static int publisher_client_send(void *obj, void *arg, void *data, int flags);
399
400 /*! \brief Publish client timer callback function */
401 static void sip_outbound_publish_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
402 {
403         struct sip_outbound_publisher *publisher = entry->user_data;
404
405         ao2_lock(publisher);
406         if (AST_LIST_EMPTY(&publisher->queue)) {
407                 int res;
408                 /* If there are no outstanding messages send an empty PUBLISH message so our publication doesn't expire */
409                 publisher_client_send(publisher, NULL, &res, 0);
410         }
411         ao2_unlock(publisher);
412
413         ao2_ref(publisher, -1);
414 }
415
416 /*! \brief Task for cancelling a refresh timer */
417 static int cancel_refresh_timer_task(void *data)
418 {
419         struct sip_outbound_publisher *publisher = data;
420
421         cancel_publish_refresh(publisher);
422         ao2_ref(publisher, -1);
423
424         return 0;
425 }
426
427 static void set_transport(struct sip_outbound_publisher *publisher, pjsip_tx_data *tdata)
428 {
429         if (!ast_strlen_zero(publisher->owner->publish->transport)) {
430                 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
431
432                 ast_sip_set_tpselector_from_transport_name(
433                         publisher->owner->publish->transport, &selector);
434                 pjsip_tx_data_set_transport(tdata, &selector);
435                 ast_sip_tpselector_unref(&selector);
436         }
437 }
438
439 /*! \brief Task for sending an unpublish */
440 static int send_unpublish_task(void *data)
441 {
442         struct sip_outbound_publisher *publisher = data;
443         pjsip_tx_data *tdata;
444
445         if (pjsip_publishc_unpublish(publisher->client, &tdata) == PJ_SUCCESS) {
446                 set_transport(publisher, tdata);
447                 pjsip_publishc_send(publisher->client, tdata);
448         }
449
450         ao2_ref(publisher, -1);
451
452         return 0;
453 }
454
455 static void stop_publishing(struct ast_sip_outbound_publish_client *client,
456                             struct ast_sip_event_publisher_handler *handler)
457 {
458         if (!handler) {
459                 handler = find_publisher_handler_for_event_name(client->publish->event);
460         }
461
462         if (handler) {
463                 handler->stop_publishing(client);
464         }
465 }
466
467 static int cancel_and_unpublish(void *obj, void *arg, int flags);
468
469 /*! \brief Helper function which starts or stops publish clients when applicable */
470 static void sip_outbound_publish_synchronize(struct ast_sip_event_publisher_handler *removed)
471 {
472         RAII_VAR(struct ao2_container *, publishes, get_publishes_and_update_state(), ao2_cleanup);
473         struct ao2_container *states;
474         struct ao2_iterator i;
475         struct ast_sip_outbound_publish_state *state;
476
477         if (!publishes) {
478                 return;
479         }
480
481         states = ao2_global_obj_ref(current_states);
482         if (!states) {
483                 return;
484         }
485
486         i = ao2_iterator_init(states, 0);
487         while ((state = ao2_iterator_next(&i))) {
488                 struct ast_sip_outbound_publish *publish = ao2_bump(state->client->publish);
489                 struct ast_sip_event_publisher_handler *handler = find_publisher_handler_for_event_name(publish->event);
490
491                 if (!state->client->started) {
492                         /* If the publisher client has not yet been started try to start it */
493                         if (!handler) {
494                                 ast_debug(2, "Could not find handler for event '%s' for outbound publish client '%s'\n",
495                                           publish->event, ast_sorcery_object_get_id(publish));
496                         } else if (handler->start_publishing(publish, state->client)) {
497                                 ast_log(LOG_ERROR, "Failed to start outbound publish with event '%s' for client '%s'\n",
498                                         publish->event, ast_sorcery_object_get_id(publish));
499                         } else {
500                                 state->client->started = 1;
501                         }
502                 } else if (state->client->started && !handler && removed && !strcmp(publish->event, removed->event_name)) {
503                         stop_publishing(state->client, removed);
504                         ao2_callback(state->client->publishers, OBJ_NODATA, cancel_and_unpublish, NULL);
505                         state->client->started = 0;
506                 }
507                 ao2_ref(publish, -1);
508                 ao2_ref(state, -1);
509         }
510         ao2_iterator_destroy(&i);
511         ao2_ref(states, -1);
512 }
513
514 static struct ast_sip_outbound_publish_state *sip_publish_state_get(const char *id)
515 {
516         struct ao2_container *states = ao2_global_obj_ref(current_states);
517         struct ast_sip_outbound_publish_state *res;
518
519         if (!states) {
520                 return NULL;
521         }
522
523         res = ao2_find(states, id, OBJ_SEARCH_KEY);
524         ao2_ref(states, -1);
525         return res;
526 }
527
528 struct ast_sip_outbound_publish_client *ast_sip_publish_client_get(const char *name)
529 {
530         struct ast_sip_outbound_publish_state *state = sip_publish_state_get(name);
531
532         if (!state) {
533                 return NULL;
534         }
535
536         ao2_ref(state->client, +1);
537         ao2_ref(state, -1);
538         return state->client;
539 }
540
541 const char *ast_sip_publish_client_get_from_uri(struct ast_sip_outbound_publish_client *client)
542 {
543         struct ast_sip_outbound_publish *publish = client->publish;
544
545         return S_OR(publish->from_uri, S_OR(publish->server_uri, ""));
546 }
547
548 static struct sip_outbound_publisher *sip_outbound_publish_client_add_publisher(
549         struct ast_sip_outbound_publish_client *client, const char *user);
550
551 static struct sip_outbound_publisher *sip_outbound_publish_client_get_publisher(
552         struct ast_sip_outbound_publish_client *client, const char *user)
553 {
554         struct sip_outbound_publisher *publisher;
555
556         /*
557          * Lock before searching since there could be a race between searching and adding.
558          * Just use the load_lock since we might need to lock it anyway (if adding) and
559          * also it simplifies the code (otherwise we'd have to lock the publishers, no-
560          * lock the search and pass a flag to 'add publisher to no-lock the potential link).
561          */
562         ast_rwlock_wrlock(&load_lock);
563         publisher = ao2_find(client->publishers, user, OBJ_SEARCH_KEY);
564         if (!publisher) {
565                 if (!(publisher = sip_outbound_publish_client_add_publisher(client, user))) {
566                         ast_rwlock_unlock(&load_lock);
567                         return NULL;
568                 }
569         }
570         ast_rwlock_unlock(&load_lock);
571
572         return publisher;
573 }
574
575 const char *ast_sip_publish_client_get_user_from_uri(struct ast_sip_outbound_publish_client *client, const char *user,
576         char *uri, size_t size)
577 {
578         struct sip_outbound_publisher *publisher;
579
580         publisher = sip_outbound_publish_client_get_publisher(client, user);
581         if (!publisher) {
582                 return NULL;
583         }
584
585         ast_copy_string(uri, publisher->from_uri, size);
586         ao2_ref(publisher, -1);
587
588         return uri;
589 }
590
591 const char *ast_sip_publish_client_get_to_uri(struct ast_sip_outbound_publish_client *client)
592 {
593         struct ast_sip_outbound_publish *publish = client->publish;
594
595         return S_OR(publish->to_uri, S_OR(publish->server_uri, ""));
596 }
597
598 const char *ast_sip_publish_client_get_user_to_uri(struct ast_sip_outbound_publish_client *client, const char *user,
599         char *uri, size_t size)
600 {
601         struct sip_outbound_publisher *publisher;
602
603         publisher = sip_outbound_publish_client_get_publisher(client, user);
604         if (!publisher) {
605                 return NULL;
606         }
607
608         ast_copy_string(uri, publisher->to_uri, size);
609         ao2_ref(publisher, -1);
610
611         return uri;
612 }
613
614 int ast_sip_register_event_publisher_handler(struct ast_sip_event_publisher_handler *handler)
615 {
616         struct ast_sip_event_publisher_handler *existing;
617         SCOPED_LOCK(lock, &publisher_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
618
619         if (!handler->start_publishing || !handler->stop_publishing) {
620                 ast_log(LOG_ERROR, "Handler does not implement required callbacks. Cannot register\n");
621                 return -1;
622         } else if (ast_strlen_zero(handler->event_name)) {
623                 ast_log(LOG_ERROR, "No event package specified for event publisher handler. Cannot register\n");
624                 return -1;
625         }
626
627         existing = find_publisher_handler_for_event_name(handler->event_name);
628         if (existing) {
629                 ast_log(LOG_ERROR, "Unable to register event publisher handler for event %s. "
630                                 "A handler is already registered\n", handler->event_name);
631                 return -1;
632         }
633
634         sub_add_handler(handler);
635
636         sip_outbound_publish_synchronize(NULL);
637
638         return 0;
639 }
640
641 void ast_sip_unregister_event_publisher_handler(struct ast_sip_event_publisher_handler *handler)
642 {
643         struct ast_sip_event_publisher_handler *iter;
644         SCOPED_LOCK(lock, &publisher_handlers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
645         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&publisher_handlers, iter, next) {
646                 if (handler == iter) {
647                         AST_RWLIST_REMOVE_CURRENT(next);
648                         break;
649                 }
650         }
651         AST_RWLIST_TRAVERSE_SAFE_END;
652
653         sip_outbound_publish_synchronize(handler);
654 }
655
656 /*! \brief Destructor function for publish information */
657 static void sip_outbound_publish_destroy(void *obj)
658 {
659         struct ast_sip_outbound_publish *publish = obj;
660
661         ast_sip_auth_vector_destroy(&publish->outbound_auths);
662
663         ast_string_field_free_memory(publish);
664 }
665
666 /*! \brief Allocator function for publish information */
667 static void *sip_outbound_publish_alloc(const char *name)
668 {
669         struct ast_sip_outbound_publish *publish = ast_sorcery_generic_alloc(sizeof(*publish),
670                 sip_outbound_publish_destroy);
671
672         if (!publish || ast_string_field_init(publish, 256)) {
673                 ao2_cleanup(publish);
674                 return NULL;
675         }
676
677         return publish;
678 }
679
680 static void sip_outbound_publish_datastore_destroy(void *obj)
681 {
682         struct ast_datastore *datastore = obj;
683
684         /* Using the destroy function (if present) destroy the data */
685         if (datastore->info->destroy != NULL && datastore->data != NULL) {
686                 datastore->info->destroy(datastore->data);
687                 datastore->data = NULL;
688         }
689
690         ast_free((void *) datastore->uid);
691         datastore->uid = NULL;
692 }
693
694 struct ast_datastore *ast_sip_publish_client_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
695 {
696         RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
697         const char *uid_ptr = uid;
698         char uuid_buf[AST_UUID_STR_LEN];
699
700         if (!info) {
701                 return NULL;
702         }
703
704         datastore = ao2_alloc(sizeof(*datastore), sip_outbound_publish_datastore_destroy);
705         if (!datastore) {
706                 return NULL;
707         }
708
709         datastore->info = info;
710         if (ast_strlen_zero(uid)) {
711                 /* They didn't provide an ID so we'll provide one ourself */
712                 uid_ptr = ast_uuid_generate_str(uuid_buf, sizeof(uuid_buf));
713         }
714
715         datastore->uid = ast_strdup(uid_ptr);
716         if (!datastore->uid) {
717                 return NULL;
718         }
719
720         ao2_ref(datastore, +1);
721         return datastore;
722 }
723
724 int ast_sip_publish_client_add_datastore(struct ast_sip_outbound_publish_client *client,
725         struct ast_datastore *datastore)
726 {
727         ast_assert(datastore != NULL);
728         ast_assert(datastore->info != NULL);
729         ast_assert(!ast_strlen_zero(datastore->uid));
730
731         if (!ao2_link(client->datastores, datastore)) {
732                 return -1;
733         }
734         return 0;
735 }
736
737 struct ast_datastore *ast_sip_publish_client_get_datastore(struct ast_sip_outbound_publish_client *client,
738         const char *name)
739 {
740         return ao2_find(client->datastores, name, OBJ_SEARCH_KEY);
741 }
742
743 void ast_sip_publish_client_remove_datastore(struct ast_sip_outbound_publish_client *client,
744         const char *name)
745 {
746         ao2_find(client->datastores, name, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
747 }
748
749 static int sip_publisher_service_queue(void *data)
750 {
751         RAII_VAR(struct sip_outbound_publisher *, publisher, data, ao2_cleanup);
752         SCOPED_AO2LOCK(lock, publisher);
753         struct sip_outbound_publish_message *message;
754         pjsip_tx_data *tdata;
755         pj_status_t status;
756
757         if (publisher->destroy || publisher->sending || !(message = AST_LIST_FIRST(&publisher->queue))) {
758                 return 0;
759         }
760
761         if (pjsip_publishc_publish(publisher->client, PJ_FALSE, &tdata) != PJ_SUCCESS) {
762                 goto fatal;
763         }
764
765         if (!ast_strlen_zero(message->body.type) && !ast_strlen_zero(message->body.subtype) &&
766                 ast_sip_add_body(tdata, &message->body)) {
767                 pjsip_tx_data_dec_ref(tdata);
768                 goto fatal;
769         }
770
771         set_transport(publisher, tdata);
772
773         status = pjsip_publishc_send(publisher->client, tdata);
774         if (status == PJ_EBUSY) {
775                 /* We attempted to send the message but something else got there first */
776                 goto service;
777         } else if (status != PJ_SUCCESS) {
778                 goto fatal;
779         }
780
781         publisher->sending = message;
782
783         return 0;
784
785 fatal:
786         AST_LIST_REMOVE_HEAD(&publisher->queue, entry);
787         ast_free(message);
788
789 service:
790         if (ast_sip_push_task(publisher->serializer, sip_publisher_service_queue, ao2_bump(publisher))) {
791                 ao2_ref(publisher, -1);
792         }
793         return -1;
794 }
795
796 static int publisher_client_send(void *obj, void *arg, void *data, int flags)
797 {
798         struct sip_outbound_publisher *publisher = obj;
799         const struct ast_sip_body *body = arg;
800         struct sip_outbound_publish_message *message;
801         size_t type_len = 0, subtype_len = 0, body_text_len = 0;
802         int *res = data;
803         SCOPED_AO2LOCK(lock, publisher);
804
805         *res = -1;
806         if (!publisher->client) {
807                 return -1;
808         }
809
810         /* If a body is present we need more space for the contents of it */
811         if (body) {
812                 type_len = strlen(body->type) + 1;
813                 subtype_len = strlen(body->subtype) + 1;
814                 body_text_len = strlen(body->body_text) + 1;
815         }
816
817         message = ast_calloc(1, sizeof(*message) + type_len + subtype_len + body_text_len);
818         if (!message) {
819                 return -1;
820         }
821
822         if (body) {
823                 char *dst = message->body_contents;
824
825                 message->body.type = strcpy(dst, body->type);
826                 dst += type_len;
827                 message->body.subtype = strcpy(dst, body->subtype);
828                 dst += subtype_len;
829                 message->body.body_text = strcpy(dst, body->body_text);
830         }
831
832         AST_LIST_INSERT_TAIL(&publisher->queue, message, entry);
833
834         *res = ast_sip_push_task(publisher->serializer, sip_publisher_service_queue, ao2_bump(publisher));
835         if (*res) {
836                 ao2_ref(publisher, -1);
837         }
838
839         return *res;
840 }
841
842 int ast_sip_publish_client_send(struct ast_sip_outbound_publish_client *client,
843         const struct ast_sip_body *body)
844 {
845         SCOPED_AO2LOCK(lock, client);
846         int res = 0;
847
848         ao2_callback_data(client->publishers, OBJ_NODATA,
849                           publisher_client_send, (void *)body, &res);
850         return res;
851 }
852
853 static int sip_outbound_publisher_set_uri(
854         pj_pool_t *pool, const char *uri, const char *user, pj_str_t *res_uri)
855 {
856         pj_str_t tmp;
857         pjsip_uri *parsed;
858         pjsip_sip_uri *parsed_uri;
859         int size;
860
861         pj_strdup2_with_null(pool, &tmp, uri);
862         if (!(parsed = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0))) {
863                 return -1;
864         }
865
866         if (!(parsed_uri = pjsip_uri_get_uri(parsed))) {
867                 return -1;
868         }
869
870         if (!ast_strlen_zero(user)) {
871                 pj_strdup2(pool, &parsed_uri->user, user);
872         }
873
874         res_uri->ptr = (char*) pj_pool_alloc(pool, pjsip_max_url_size);
875         if (!res_uri->ptr) {
876                 return -1;
877         }
878
879         if ((size = pjsip_uri_print(PJSIP_URI_IN_OTHER, parsed_uri, res_uri->ptr,
880                                     pjsip_max_url_size - 1)) <= 0) {
881                 return -1;
882         }
883         res_uri->ptr[size] = '\0';
884         res_uri->slen = size;
885
886         return 0;
887 }
888
889 static int sip_outbound_publisher_set_uris(
890         pj_pool_t *pool, struct sip_outbound_publisher *publisher,
891         pj_str_t *server_uri, pj_str_t *to_uri, pj_str_t *from_uri)
892 {
893         struct ast_sip_outbound_publish *publish = publisher->owner->publish;
894
895         if (sip_outbound_publisher_set_uri(pool, publish->server_uri, publisher->user, server_uri)) {
896                 ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound publish '%s'\n",
897                         publish->server_uri, ast_sorcery_object_get_id(publish));
898                 return -1;
899         }
900
901         if (ast_strlen_zero(publish->to_uri)) {
902                 to_uri->ptr = server_uri->ptr;
903                 to_uri->slen = server_uri->slen;
904         } else if (sip_outbound_publisher_set_uri(pool, publish->to_uri, publisher->user, to_uri)) {
905                 ast_log(LOG_ERROR, "Invalid to URI '%s' specified on outbound publish '%s'\n",
906                         publish->to_uri, ast_sorcery_object_get_id(publish));
907                 return -1;
908         }
909
910         publisher->to_uri = ast_strdup(to_uri->ptr);
911         if (!publisher->to_uri) {
912                 return -1;
913         }
914
915         if (ast_strlen_zero(publish->from_uri)) {
916                 from_uri->ptr = server_uri->ptr;
917                 from_uri->slen = server_uri->slen;
918         } else if (sip_outbound_publisher_set_uri(pool, publish->from_uri, publisher->user, from_uri)) {
919                 ast_log(LOG_ERROR, "Invalid from URI '%s' specified on outbound publish '%s'\n",
920                         publish->from_uri, ast_sorcery_object_get_id(publish));
921                 return -1;
922         }
923
924         publisher->from_uri = ast_strdup(from_uri->ptr);
925         if (!publisher->from_uri) {
926                 return -1;
927         }
928
929         return 0;
930 }
931
932 static void sip_outbound_publish_callback(struct pjsip_publishc_cbparam *param);
933
934 /*! \brief Helper function that allocates a pjsip publish client and configures it */
935 static int sip_outbound_publisher_init(void *data)
936 {
937         struct sip_outbound_publisher *publisher = data;
938         RAII_VAR(struct ast_sip_outbound_publish *, publish, NULL, ao2_cleanup);
939         pjsip_publishc_opt opt = {
940                 .queue_request = PJ_FALSE,
941         };
942         pj_pool_t *pool;
943         pj_str_t event, server_uri, to_uri, from_uri;
944
945         if (publisher->client) {
946                 return 0;
947         }
948
949         if (pjsip_publishc_create(ast_sip_get_pjsip_endpoint(), &opt,
950                                   ao2_bump(publisher), sip_outbound_publish_callback,
951                 &publisher->client) != PJ_SUCCESS) {
952                 ao2_ref(publisher, -1);
953                 return -1;
954         }
955
956         publish = ao2_bump(publisher->owner->publish);
957
958         if (!ast_strlen_zero(publish->outbound_proxy)) {
959                 pjsip_route_hdr route_set, *route;
960                 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
961
962                 pj_list_init(&route_set);
963
964                 if (!(route = pjsip_parse_hdr(pjsip_publishc_get_pool(publisher->client), &ROUTE_HNAME,
965                         (char*)publish->outbound_proxy, strlen(publish->outbound_proxy), NULL))) {
966                         pjsip_publishc_destroy(publisher->client);
967                         return -1;
968                 }
969                 pj_list_insert_nodes_before(&route_set, route);
970
971                 pjsip_publishc_set_route_set(publisher->client, &route_set);
972         }
973
974         pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation",
975                                        pjsip_max_url_size, pjsip_max_url_size);
976         if (!pool) {
977                 ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound publish '%s'\n",
978                         ast_sorcery_object_get_id(publish));
979                 pjsip_publishc_destroy(publisher->client);
980                 return -1;
981         }
982
983         if (sip_outbound_publisher_set_uris(pool, publisher, &server_uri, &from_uri, &to_uri)) {
984                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
985                 pjsip_publishc_destroy(publisher->client);
986                 return -1;
987         }
988
989         pj_cstr(&event, publish->event);
990         if (pjsip_publishc_init(publisher->client, &event, &server_uri, &from_uri, &to_uri,
991                         publish->expiration) != PJ_SUCCESS) {
992                 ast_log(LOG_ERROR, "Failed to initialize publishing client on outbound publish '%s'\n",
993                         ast_sorcery_object_get_id(publish));
994                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
995                 pjsip_publishc_destroy(publisher->client);
996                 return -1;
997         }
998
999         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1000         return 0;
1001 }
1002
1003 static int sip_outbound_publisher_reinit(void *obj, void *arg, int flags)
1004 {
1005         return sip_outbound_publisher_init(obj);
1006 }
1007
1008 static int sip_outbound_publisher_reinit_all(void *data)
1009 {
1010         ao2_callback(data, OBJ_NODATA, sip_outbound_publisher_reinit, NULL);
1011         return 0;
1012 }
1013
1014 /*! \brief Destructor function for publish client */
1015 static void sip_outbound_publisher_destroy(void *obj)
1016 {
1017         struct sip_outbound_publisher *publisher = obj;
1018         struct sip_outbound_publish_message *message;
1019
1020         /* You might be tempted to think "the publish client isn't being destroyed" but it actually is - just elsewhere */
1021
1022         while ((message = AST_LIST_REMOVE_HEAD(&publisher->queue, entry))) {
1023                 ast_free(message);
1024         }
1025
1026         ao2_cleanup(publisher->owner);
1027         ast_free(publisher->from_uri);
1028         ast_free(publisher->to_uri);
1029
1030         ast_taskprocessor_unreference(publisher->serializer);
1031 }
1032
1033 static struct sip_outbound_publisher *sip_outbound_publisher_alloc(
1034         struct ast_sip_outbound_publish_client *client, const char *user)
1035 {
1036         struct sip_outbound_publisher *publisher;
1037         char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
1038
1039         publisher = ao2_alloc(sizeof(*publisher) + (user ? strlen(user) : 0) + 1,
1040                               sip_outbound_publisher_destroy);
1041         if (!publisher) {
1042                 return NULL;
1043         }
1044
1045         /*
1046          * Bump the ref to the client. This essentially creates a circular reference,
1047          * but it is needed in order to make sure the client object doesn't get pulled
1048          * out from under us when the publisher stops publishing.
1049          *
1050          * The circular reference is alleviated by calling cancel_and_unpublish for
1051          * each client, from the state's destructor. By calling it there all references
1052          * to the publishers should go to zero, thus calling the publisher's destructor.
1053          * This in turn removes the client reference we added here. The state then removes
1054          * its reference to the client, which should take it to zero.
1055          */
1056         publisher->owner = ao2_bump(client);
1057         publisher->timer.user_data = publisher;
1058         publisher->timer.cb = sip_outbound_publish_timer_cb;
1059         if (user) {
1060                 strcpy(publisher->user, user);
1061         } else {
1062                 *publisher->user = '\0';
1063         }
1064
1065         ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/outpub/%s",
1066                 ast_sorcery_object_get_id(client->publish));
1067
1068         publisher->serializer = ast_sip_create_serializer_group(tps_name,
1069                 shutdown_group);
1070         if (!publisher->serializer) {
1071                 ao2_ref(publisher, -1);
1072                 return NULL;
1073         }
1074
1075         if (ast_sip_push_task_wait_servant(NULL, sip_outbound_publisher_init, publisher)) {
1076                 ast_log(LOG_ERROR, "Unable to create publisher for outbound publish '%s'\n",
1077                         ast_sorcery_object_get_id(client->publish));
1078                 ao2_ref(publisher, -1);
1079                 return NULL;
1080         }
1081
1082         return publisher;
1083 }
1084
1085 static struct sip_outbound_publisher *sip_outbound_publish_client_add_publisher(
1086         struct ast_sip_outbound_publish_client *client, const char *user)
1087 {
1088         struct sip_outbound_publisher *publisher =
1089                 sip_outbound_publisher_alloc(client, user);
1090
1091         if (!publisher) {
1092                 return NULL;
1093         }
1094
1095         if (!ao2_link(client->publishers, publisher)) {
1096                 /*
1097                  * No need to bump the reference here. The task will take care of
1098                  * removing the reference.
1099                  */
1100                 if (ast_sip_push_task(publisher->serializer, cancel_refresh_timer_task, publisher)) {
1101                         ao2_ref(publisher, -1);
1102                 }
1103                 return NULL;
1104         }
1105
1106         return publisher;
1107 }
1108
1109 int ast_sip_publish_client_user_send(struct ast_sip_outbound_publish_client *client,
1110                                      const char *user, const struct ast_sip_body *body)
1111 {
1112         struct sip_outbound_publisher *publisher;
1113         int res;
1114
1115         publisher = sip_outbound_publish_client_get_publisher(client, user);
1116         if (!publisher) {
1117                 return -1;
1118         }
1119
1120         publisher_client_send(publisher, (void *)body, &res, 0);
1121         ao2_ref(publisher, -1);
1122         return res;
1123 }
1124
1125 void ast_sip_publish_client_remove(struct ast_sip_outbound_publish_client *client,
1126                                    const char *user)
1127 {
1128         SCOPED_WRLOCK(lock, &load_lock);
1129         ao2_find(client->publishers, user, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
1130 }
1131
1132 static int explicit_publish_destroy(void *data)
1133 {
1134         struct sip_outbound_publisher *publisher = data;
1135
1136         /*
1137          * If there is no pjsip publishing client then we obviously don't need
1138          * to destroy it. Also, the ref for the Asterisk publishing client that
1139          * pjsip had would not exist or should already be gone as well.
1140          */
1141         if (publisher->client) {
1142                 pjsip_publishc_destroy(publisher->client);
1143                 ao2_ref(publisher, -1);
1144         }
1145
1146         ao2_ref(publisher, -1);
1147
1148         return 0;
1149 }
1150
1151 /*! \brief Helper function which cancels and un-publishes a no longer used client */
1152 static int cancel_and_unpublish(void *obj, void *arg, int flags)
1153 {
1154         struct sip_outbound_publisher *publisher = obj;
1155         struct ast_sip_outbound_publish_client *client = publisher->owner;
1156
1157         SCOPED_AO2LOCK(lock, publisher);
1158
1159         if (!client->started) {
1160                 /* If the publisher was never started, there's nothing to unpublish, so just
1161                  * destroy the publication and remove its reference to the publisher.
1162                  */
1163                 if (ast_sip_push_task(publisher->serializer, explicit_publish_destroy, ao2_bump(publisher))) {
1164                         ao2_ref(publisher, -1);
1165                 }
1166                 return 0;
1167         }
1168
1169         if (ast_sip_push_task(publisher->serializer, cancel_refresh_timer_task, ao2_bump(publisher))) {
1170                 ast_log(LOG_WARNING, "Could not stop refresh timer on outbound publish '%s'\n",
1171                         ast_sorcery_object_get_id(client->publish));
1172                 ao2_ref(publisher, -1);
1173         }
1174
1175         /* If nothing is being sent right now send the unpublish - the destroy will happen in the subsequent callback */
1176         if (!publisher->sending) {
1177                 if (ast_sip_push_task(publisher->serializer, send_unpublish_task, ao2_bump(publisher))) {
1178                         ast_log(LOG_WARNING, "Could not send unpublish message on outbound publish '%s'\n",
1179                                 ast_sorcery_object_get_id(client->publish));
1180                         ao2_ref(publisher, -1);
1181                 }
1182         }
1183         publisher->destroy = 1;
1184         return 0;
1185 }
1186
1187 /*! \brief Destructor function for publish client */
1188 static void sip_outbound_publish_client_destroy(void *obj)
1189 {
1190         struct ast_sip_outbound_publish_client *client = obj;
1191
1192         ao2_cleanup(client->datastores);
1193
1194         /*
1195          * The client's publishers have already been unpublished and destroyed
1196          * by this point, so it is safe to finally remove the reference to the
1197          * publish object. The client needed to hold a reference to it until
1198          * the publishers were done with it.
1199          */
1200         ao2_cleanup(client->publish);
1201 }
1202
1203 /*! \brief Destructor function for publish state */
1204 static void sip_outbound_publish_state_destroy(void *obj)
1205 {
1206         struct ast_sip_outbound_publish_state *state = obj;
1207
1208         stop_publishing(state->client, NULL);
1209         /*
1210          * Since the state is being destroyed the associated client needs to also
1211          * be destroyed. However simply removing the reference to the client will
1212          * not initiate client destruction since the client's publisher(s) hold a
1213          * reference to the client object as well. So we need to unpublish the
1214          * the client's publishers here, which will remove the publisher's client
1215          * reference during that process.
1216          *
1217          * That being said we don't want to remove the client's reference to the
1218          * publish object just yet. We'll hold off on that until client destruction
1219          * itself. This is because the publishers need access to the client's
1220          * publish object while they are unpublishing.
1221          */
1222         ao2_callback(state->client->publishers, OBJ_NODATA | OBJ_UNLINK, cancel_and_unpublish, NULL);
1223         ao2_cleanup(state->client->publishers);
1224
1225         state->client->started = 0;
1226         ao2_cleanup(state->client);
1227 }
1228
1229 /*!
1230  * \internal
1231  * \brief Check if a publish can be reused
1232  *
1233  * This checks if the existing outbound publish's configuration differs from a newly-applied
1234  * outbound publish.
1235  *
1236  * \param existing The pre-existing outbound publish
1237  * \param applied The newly-created publish
1238  */
1239 static int can_reuse_publish(struct ast_sip_outbound_publish *existing, struct ast_sip_outbound_publish *applied)
1240 {
1241         int i;
1242
1243         if (strcmp(existing->server_uri, applied->server_uri) || strcmp(existing->from_uri, applied->from_uri) ||
1244                 strcmp(existing->to_uri, applied->to_uri) || strcmp(existing->outbound_proxy, applied->outbound_proxy) ||
1245                 strcmp(existing->event, applied->event) ||
1246                 AST_VECTOR_SIZE(&existing->outbound_auths) != AST_VECTOR_SIZE(&applied->outbound_auths)) {
1247                 return 0;
1248         }
1249
1250         for (i = 0; i < AST_VECTOR_SIZE(&existing->outbound_auths); ++i) {
1251                 if (strcmp(AST_VECTOR_GET(&existing->outbound_auths, i), AST_VECTOR_GET(&applied->outbound_auths, i))) {
1252                         return 0;
1253                 }
1254         }
1255
1256         return 1;
1257 }
1258
1259 /*! \brief Callback function for publish client responses */
1260 static void sip_outbound_publish_callback(struct pjsip_publishc_cbparam *param)
1261 {
1262 #define DESTROY_CLIENT() do {                      \
1263         pjsip_publishc_destroy(publisher->client); \
1264         publisher->client = NULL; \
1265         ao2_ref(publisher, -1); } while (0)
1266
1267         RAII_VAR(struct sip_outbound_publisher *, publisher, ao2_bump(param->token), ao2_cleanup);
1268         RAII_VAR(struct ast_sip_outbound_publish *, publish, ao2_bump(publisher->owner->publish), ao2_cleanup);
1269         SCOPED_AO2LOCK(lock, publisher);
1270         pjsip_tx_data *tdata;
1271
1272         if (publisher->destroy) {
1273                 if (publisher->sending) {
1274                         publisher->sending = NULL;
1275
1276                         if (!ast_sip_push_task(publisher->serializer, send_unpublish_task, ao2_bump(publisher))) {
1277                                 return;
1278                         }
1279                         ast_log(LOG_WARNING, "Could not send unpublish message on outbound publish '%s'\n",
1280                                 ast_sorcery_object_get_id(publish));
1281                         ao2_ref(publisher, -1);
1282                 }
1283                 /* Once the destroy is called this callback will not get called any longer, so drop the publisher ref */
1284                 DESTROY_CLIENT();
1285                 return;
1286         }
1287
1288         if (param->code == 401 || param->code == 407) {
1289                 pjsip_transaction *tsx = pjsip_rdata_get_tsx(param->rdata);
1290
1291                 if (!ast_sip_create_request_with_auth(&publish->outbound_auths,
1292                                 param->rdata, tsx->last_tx, &tdata)) {
1293                         set_transport(publisher, tdata);
1294                         pjsip_publishc_send(publisher->client, tdata);
1295                 }
1296                 publisher->auth_attempts++;
1297
1298                 if (publisher->auth_attempts == publish->max_auth_attempts) {
1299                         DESTROY_CLIENT();
1300                         ast_log(LOG_ERROR, "Reached maximum number of PUBLISH authentication attempts on outbound publish '%s'\n",
1301                                 ast_sorcery_object_get_id(publish));
1302
1303                         goto end;
1304                 }
1305                 return;
1306         }
1307
1308         publisher->auth_attempts = 0;
1309
1310         if (param->code == 412) {
1311                 DESTROY_CLIENT();
1312                 if (sip_outbound_publisher_init(publisher)) {
1313                         ast_log(LOG_ERROR, "Failed to create a new outbound publish client for '%s' on 412 response\n",
1314                                 ast_sorcery_object_get_id(publish));
1315                         goto end;
1316                 }
1317
1318                 /* Setting this to NULL will cause a new PUBLISH to get created and sent for the same underlying body */
1319                 publisher->sending = NULL;
1320         } else if (param->code == 423) {
1321                 /* Update the expiration with the new expiration time if available */
1322                 pjsip_expires_hdr *expires;
1323
1324                 expires = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_MIN_EXPIRES, NULL);
1325                 if (!expires || !expires->ivalue) {
1326                         DESTROY_CLIENT();
1327                         ast_log(LOG_ERROR, "Received 423 response on outbound publish '%s' without a Min-Expires header\n",
1328                                 ast_sorcery_object_get_id(publish));
1329                         goto end;
1330                 }
1331
1332                 pjsip_publishc_update_expires(publisher->client, expires->ivalue);
1333                 publisher->sending = NULL;
1334         } else if (publisher->sending) {
1335                 /* Remove the message currently being sent so that when the queue is serviced another will get sent */
1336                 AST_LIST_REMOVE_HEAD(&publisher->queue, entry);
1337                 ast_free(publisher->sending);
1338                 publisher->sending = NULL;
1339                 if (!param->rdata) {
1340                         ast_log(LOG_NOTICE, "No response received for outbound publish '%s'\n",
1341                                 ast_sorcery_object_get_id(publish));
1342                 }
1343         }
1344
1345         if (AST_LIST_EMPTY(&publisher->queue)) {
1346                 schedule_publish_refresh(publisher, param->expiration);
1347         }
1348
1349 end:
1350         if (!publisher->client) {
1351                 struct sip_outbound_publish_message *message;
1352
1353                 while ((message = AST_LIST_REMOVE_HEAD(&publisher->queue, entry))) {
1354                         ast_free(message);
1355                 }
1356         } else {
1357                 if (ast_sip_push_task(publisher->serializer, sip_publisher_service_queue, ao2_bump(publisher))) {
1358                         ao2_ref(publisher, -1);
1359                 }
1360         }
1361 }
1362
1363 #define DATASTORE_BUCKETS 53
1364
1365 static int datastore_hash(const void *obj, int flags)
1366 {
1367         const struct ast_datastore *datastore;
1368         const char *uid;
1369
1370         switch (flags & OBJ_SEARCH_MASK) {
1371         case OBJ_SEARCH_KEY:
1372                 uid = obj;
1373                 break;
1374         case OBJ_SEARCH_OBJECT:
1375                 datastore = obj;
1376                 uid = datastore->uid;
1377                 break;
1378         default:
1379                 /* Hash can only work on something with a full key. */
1380                 ast_assert(0);
1381                 return 0;
1382         }
1383
1384         return ast_str_hash(uid);
1385 }
1386
1387 static int datastore_cmp(void *obj, void *arg, int flags)
1388 {
1389         const struct ast_datastore *object_left = obj;
1390         const struct ast_datastore *object_right = arg;
1391         const char *right_key = arg;
1392         int cmp;
1393
1394         switch (flags & OBJ_SEARCH_MASK) {
1395         case OBJ_SEARCH_OBJECT:
1396                 right_key = object_right->uid;
1397                 /* Fall through */
1398         case OBJ_SEARCH_KEY:
1399                 cmp = strcmp(object_left->uid, right_key);
1400                 break;
1401         case OBJ_SEARCH_PARTIAL_KEY:
1402         cmp = strncmp(object_left->uid, right_key, strlen(right_key));
1403                 break;
1404         default:
1405                 /*
1406                  * What arg points to is specific to this traversal callback
1407                  * and has no special meaning to astobj2.
1408                  */
1409                 cmp = 0;
1410                 break;
1411         }
1412         if (cmp) {
1413                 return 0;
1414         }
1415         /*
1416          * At this point the traversal callback is identical to a sorted
1417          * container.
1418          */
1419         return CMP_MATCH;
1420 }
1421
1422 /*! \brief Allocator function for publish client */
1423 static struct ast_sip_outbound_publish_state *sip_outbound_publish_state_alloc(
1424         struct ast_sip_outbound_publish *publish)
1425 {
1426         const char *id = ast_sorcery_object_get_id(publish);
1427         struct ast_sip_outbound_publish_state *state =
1428                 ao2_alloc(sizeof(*state) + strlen(id) + 1, sip_outbound_publish_state_destroy);
1429
1430         if (!state) {
1431                 return NULL;
1432         }
1433
1434         state->client = ao2_alloc(sizeof(*state->client), sip_outbound_publish_client_destroy);
1435         if (!state->client) {
1436                 ao2_ref(state, -1);
1437                 return NULL;
1438         }
1439
1440         state->client->datastores = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
1441                 DATASTORE_BUCKETS, datastore_hash, NULL, datastore_cmp);
1442         if (!state->client->datastores) {
1443                 ao2_ref(state, -1);
1444                 return NULL;
1445         }
1446
1447         state->client->publishers = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
1448                 DATASTORE_BUCKETS,
1449                 sip_outbound_publisher_hash_fn, NULL, sip_outbound_publisher_cmp_fn);
1450         if (!state->client->publishers) {
1451                 ao2_ref(state, -1);
1452                 return NULL;
1453         }
1454
1455         state->client->publish = ao2_bump(publish);
1456
1457         strcpy(state->id, id);
1458         return state;
1459 }
1460
1461 static int validate_publish_config(struct ast_sip_outbound_publish *publish)
1462 {
1463         if (ast_strlen_zero(publish->server_uri)) {
1464                 ast_log(LOG_ERROR, "No server URI specified on outbound publish '%s'\n",
1465                         ast_sorcery_object_get_id(publish));
1466                 return -1;
1467         } else if (ast_sip_validate_uri_length(publish->server_uri)) {
1468                 ast_log(LOG_ERROR, "Server URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s' on outbound publish '%s'\n",
1469                         publish->server_uri,
1470                         ast_sorcery_object_get_id(publish));
1471                 return -1;
1472         } else if (ast_strlen_zero(publish->event)) {
1473                 ast_log(LOG_ERROR, "No event type specified for outbound publish '%s'\n",
1474                         ast_sorcery_object_get_id(publish));
1475                 return -1;
1476         } else if (!ast_strlen_zero(publish->from_uri)
1477                 && ast_sip_validate_uri_length(publish->from_uri)) {
1478                 ast_log(LOG_ERROR, "From URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s' on outbound publish '%s'\n",
1479                         publish->from_uri,
1480                         ast_sorcery_object_get_id(publish));
1481                 return -1;
1482         } else if (!ast_strlen_zero(publish->to_uri)
1483                 && ast_sip_validate_uri_length(publish->to_uri)) {
1484                 ast_log(LOG_ERROR, "To URI or hostname length exceeds pjproject limit or is not a sip(s) uri: '%s' on outbound publish '%s'\n",
1485                         publish->to_uri,
1486                         ast_sorcery_object_get_id(publish));
1487                 return -1;
1488         }
1489         return 0;
1490 }
1491
1492 static int current_state_reusable(struct ast_sip_outbound_publish *publish,
1493                                   struct ast_sip_outbound_publish_state *current_state)
1494 {
1495         struct ast_sip_outbound_publish *old_publish;
1496
1497         /*
1498          * Don't maintain the old state/client objects if the multi_user option changed.
1499          */
1500         if ((!publish->multi_user && current_state->client->publish->multi_user) ||
1501             (publish->multi_user && !current_state->client->publish->multi_user)) {
1502                 return 0;
1503         }
1504
1505
1506         if (!can_reuse_publish(current_state->client->publish, publish)) {
1507                 /*
1508                  * Something significant has changed in the configuration, so we are
1509                  * unable to use the old state object. The current state needs to go
1510                  * away and a new one needs to be created.
1511                  */
1512                 return 0;
1513         }
1514
1515         /*
1516          * We can reuse the current state object so keep it, but swap out the
1517          * underlying publish object with the new one.
1518          */
1519         old_publish = current_state->client->publish;
1520         current_state->client->publish = publish;
1521         if (ast_sip_push_task_wait_servant(NULL, sip_outbound_publisher_reinit_all,
1522                 current_state->client->publishers)) {
1523                 /*
1524                  * If the state object fails to re-initialize then swap
1525                  * the old publish info back in.
1526                  */
1527                 current_state->client->publish = publish;
1528                 ast_log(LOG_ERROR, "Unable to reinitialize client(s) for outbound publish '%s'\n",
1529                         ast_sorcery_object_get_id(current_state->client->publish));
1530                 return -1;
1531         }
1532
1533         /*
1534          * Since we swapped out the publish object the new one needs a ref
1535          * while the old one needs to go away.
1536          */
1537         ao2_ref(current_state->client->publish, +1);
1538         ao2_cleanup(old_publish);
1539
1540         /* Tell the caller that the current state object should be used */
1541         return 1;
1542 }
1543
1544 /*! \brief Apply function which finds or allocates a state structure */
1545 static int sip_outbound_publish_apply(const struct ast_sorcery *sorcery, void *obj)
1546 {
1547 #define ADD_TO_NEW_STATES(__obj) \
1548         do { if (__obj) { \
1549              ao2_link(new_states, __obj); \
1550              ao2_ref(__obj, -1); } } while (0)
1551
1552         struct ast_sip_outbound_publish *applied = obj;
1553         struct ast_sip_outbound_publish_state *current_state, *new_state;
1554         struct sip_outbound_publisher *publisher = NULL;
1555         int res;
1556
1557         /*
1558          * New states are being loaded or reloaded. We'll need to add the new
1559          * object if created/updated, or keep the old object if an error occurs.
1560          */
1561         if (!new_states) {
1562                 new_states = ao2_container_alloc_hash(
1563                         AO2_ALLOC_OPT_LOCK_NOLOCK, 0, DEFAULT_STATE_BUCKETS,
1564                         outbound_publish_state_hash, NULL, outbound_publish_state_cmp);
1565
1566                 if (!new_states) {
1567                         ast_log(LOG_ERROR, "Unable to allocate new states container\n");
1568                         return -1;
1569                 }
1570         }
1571
1572         /* If there is current state we'll want to maintain it if any errors occur */
1573         current_state = sip_publish_state_get(ast_sorcery_object_get_id(applied));
1574
1575         if ((res = validate_publish_config(applied))) {
1576                 ADD_TO_NEW_STATES(current_state);
1577                 return res;
1578         }
1579
1580         if (current_state && (res = current_state_reusable(applied, current_state))) {
1581                 /*
1582                  * The current state object was able to be reused, or an error
1583                  * occurred. Either way we keep the current state and be done.
1584                  */
1585                 ADD_TO_NEW_STATES(current_state);
1586                 return res == 1 ? 0 : -1;
1587         }
1588
1589         /*
1590          * No current state was found or it was unable to be reused. Either way
1591          * we'll need to create a new state object.
1592          */
1593         new_state = sip_outbound_publish_state_alloc(applied);
1594         if (!new_state) {
1595                 ast_log(LOG_ERROR, "Unable to create state for outbound publish '%s'\n",
1596                         ast_sorcery_object_get_id(applied));
1597                 ADD_TO_NEW_STATES(current_state);
1598                 return -1;
1599         };
1600
1601         if (!applied->multi_user &&
1602             !(publisher = sip_outbound_publish_client_add_publisher(new_state->client, NULL))) {
1603                 ADD_TO_NEW_STATES(current_state);
1604                 ao2_ref(new_state, -1);
1605                 return -1;
1606         }
1607         ao2_cleanup(publisher);
1608
1609         ADD_TO_NEW_STATES(new_state);
1610         ao2_cleanup(current_state);
1611         return res;
1612 }
1613
1614 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1615 {
1616         struct ast_sip_outbound_publish *publish = obj;
1617
1618         return ast_sip_auth_vector_init(&publish->outbound_auths, var->value);
1619 }
1620
1621
1622 static int unload_module(void)
1623 {
1624         int remaining;
1625
1626         ast_sorcery_object_unregister(ast_sip_get_sorcery(), "outbound-publish");
1627
1628         ao2_global_obj_release(current_states);
1629
1630         /* Wait for publication serializers to get destroyed. */
1631         ast_debug(2, "Waiting for publication to complete for unload.\n");
1632         remaining = ast_serializer_shutdown_group_join(shutdown_group, MAX_UNLOAD_TIMEOUT_TIME);
1633         if (remaining) {
1634                 ast_log(LOG_WARNING, "Unload incomplete.  Could not stop %d outbound publications.  Try again later.\n",
1635                         remaining);
1636                 return -1;
1637         }
1638
1639         ast_debug(2, "Successful shutdown.\n");
1640
1641         ao2_cleanup(shutdown_group);
1642         shutdown_group = NULL;
1643
1644         return 0;
1645 }
1646
1647 static int load_module(void)
1648 {
1649         /* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
1650         ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
1651
1652         shutdown_group = ast_serializer_shutdown_group_alloc();
1653         if (!shutdown_group) {
1654                 return AST_MODULE_LOAD_DECLINE;
1655         }
1656
1657         ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_publish");
1658         ast_sorcery_apply_default(ast_sip_get_sorcery(), "outbound-publish", "config", "pjsip.conf,criteria=type=outbound-publish");
1659
1660         if (ast_sorcery_object_register(ast_sip_get_sorcery(), "outbound-publish", sip_outbound_publish_alloc, NULL,
1661                 sip_outbound_publish_apply)) {
1662                 ast_log(LOG_ERROR, "Unable to register 'outbound-publish' type with sorcery\n");
1663                 unload_module();
1664                 return AST_MODULE_LOAD_DECLINE;
1665         }
1666
1667         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "type", "", OPT_NOOP_T, 0, 0);
1668         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "server_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, server_uri));
1669         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "from_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, from_uri));
1670         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "event", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, event));
1671         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "to_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, to_uri));
1672         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, outbound_proxy));
1673         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct ast_sip_outbound_publish, expiration));
1674         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "max_auth_attempts", "5", OPT_UINT_T, 0, FLDSET(struct ast_sip_outbound_publish, max_auth_attempts));
1675         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_outbound_publish, transport));
1676         ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "outbound-publish", "outbound_auth", "", outbound_auth_handler, NULL, NULL, 0, 0);
1677         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "outbound-publish", "multi_user", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_outbound_publish, multi_user));
1678
1679         ast_sorcery_reload_object(ast_sip_get_sorcery(), "outbound-publish");
1680
1681         AST_RWLIST_RDLOCK(&publisher_handlers);
1682         sip_outbound_publish_synchronize(NULL);
1683         AST_RWLIST_UNLOCK(&publisher_handlers);
1684
1685         pjsip_publishc_init_module(ast_sip_get_pjsip_endpoint());
1686
1687         return AST_MODULE_LOAD_SUCCESS;
1688 }
1689
1690 static int reload_module(void)
1691 {
1692         ast_sorcery_reload_object(ast_sip_get_sorcery(), "outbound-publish");
1693
1694         AST_RWLIST_RDLOCK(&publisher_handlers);
1695         sip_outbound_publish_synchronize(NULL);
1696         AST_RWLIST_UNLOCK(&publisher_handlers);
1697         return 0;
1698 }
1699
1700 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Publish Support",
1701         .support_level = AST_MODULE_SUPPORT_CORE,
1702         .load = load_module,
1703         .reload = reload_module,
1704         .unload = unload_module,
1705         .load_pri = AST_MODPRI_CHANNEL_DEPEND,
1706         .requires = "res_pjproject,res_pjsip",
1707 );