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