security_events: Fix error caused by DTD validation error
[asterisk/asterisk.git] / res / res_pjsip_mwi.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Mark Michelson <mmichelson@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*** MODULEINFO
20         <depend>pjproject</depend>
21         <depend>res_pjsip</depend>
22         <depend>res_pjsip_pubsub</depend>
23         <support_level>core</support_level>
24  ***/
25
26 #include "asterisk.h"
27
28 #include <pjsip.h>
29 #include <pjsip_simple.h>
30 #include <pjlib.h>
31
32 #include "asterisk/res_pjsip.h"
33 #include "asterisk/res_pjsip_pubsub.h"
34 #include "asterisk/res_pjsip_body_generator_types.h"
35 #include "asterisk/module.h"
36 #include "asterisk/logger.h"
37 #include "asterisk/astobj2.h"
38 #include "asterisk/sorcery.h"
39 #include "asterisk/stasis.h"
40 #include "asterisk/app.h"
41
42 struct mwi_subscription;
43 AO2_GLOBAL_OBJ_STATIC(unsolicited_mwi);
44
45 #define STASIS_BUCKETS 13
46 #define MWI_BUCKETS 53
47
48 #define MWI_TYPE "application"
49 #define MWI_SUBTYPE "simple-message-summary"
50
51 static void mwi_subscription_shutdown(struct ast_sip_subscription *sub);
52 static struct ast_sip_subscription *mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
53                 pjsip_rx_data *rdata);
54 static void mwi_resubscribe(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
55                 struct ast_sip_subscription_response_data *response_data);
56 static void mwi_subscription_timeout(struct ast_sip_subscription *sub);
57 static void mwi_subscription_terminated(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
58 static void mwi_notify_response(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
59 static void mwi_notify_request(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
60                 struct ast_sip_subscription_response_data *response_data);
61 static int mwi_refresh_subscription(struct ast_sip_subscription *sub);
62 static void mwi_to_ami(struct ast_sip_subscription *sub, struct ast_str **buf);
63
64 static struct ast_sip_subscription_handler mwi_handler = {
65         .event_name = "message-summary",
66         .accept = { MWI_TYPE"/"MWI_SUBTYPE, },
67         .default_accept =  MWI_TYPE"/"MWI_SUBTYPE,
68         .subscription_shutdown = mwi_subscription_shutdown,
69         .new_subscribe = mwi_new_subscribe,
70         .resubscribe = mwi_resubscribe,
71         .subscription_timeout = mwi_subscription_timeout,
72         .subscription_terminated = mwi_subscription_terminated,
73         .notify_response = mwi_notify_response,
74         .notify_request = mwi_notify_request,
75         .refresh_subscription = mwi_refresh_subscription,
76         .to_ami = mwi_to_ami,
77 };
78
79 /*!
80  * \brief Wrapper for stasis subscription
81  *
82  * An MWI subscription has a container of these. This
83  * represents a stasis subscription for MWI state.
84  */
85 struct mwi_stasis_subscription {
86         /*! The MWI stasis subscription */
87         struct stasis_subscription *stasis_sub;
88         /*! The mailbox corresponding with the MWI subscription. Used as a hash key */
89         char mailbox[1];
90 };
91
92 /*!
93  * \brief A subscription for MWI
94  *
95  * This subscription is the basis for MWI for an endpoint. Each
96  * endpoint that uses MWI will have a corresponding mwi_subscription.
97  *
98  * This structure acts as the owner for the underlying SIP subscription.
99  * When the mwi_subscription is destroyed, the SIP subscription dies, too.
100  * The mwi_subscription's lifetime is governed by its underlying stasis
101  * subscriptions. When all stasis subscriptions are destroyed, the
102  * mwi_subscription is destroyed as well.
103  */
104 struct mwi_subscription {
105         /*! Container of \ref mwi_stasis_subscription structures.
106          * A single MWI subscription may be fore multiple mailboxes, thus
107          * requiring multiple stasis subscriptions
108          */
109         struct ao2_container *stasis_subs;
110         /*! The SIP subscription. Unsolicited MWI does not use this */
111         struct ast_sip_subscription *sip_sub;
112         /*! Is the MWI solicited (i.e. Initiated with an external SUBSCRIBE) ? */
113         unsigned int is_solicited;
114         /*! Identifier for the subscription.
115          * The identifier is the same as the corresponding endpoint's stasis ID.
116          * Used as a hash key
117          */
118         char id[1];
119 };
120
121 static void mwi_stasis_cb(void *userdata, struct stasis_subscription *sub,
122                 struct stasis_message *msg);
123
124 static struct mwi_stasis_subscription *mwi_stasis_subscription_alloc(const char *mailbox, struct mwi_subscription *mwi_sub)
125 {
126         struct mwi_stasis_subscription *mwi_stasis_sub;
127         struct stasis_topic *topic;
128
129         if (!mwi_sub) {
130                 return NULL;
131         }
132
133         mwi_stasis_sub = ao2_alloc(sizeof(*mwi_stasis_sub) + strlen(mailbox), NULL);
134         if (!mwi_stasis_sub) {
135                 return NULL;
136         }
137
138         topic = ast_mwi_topic(mailbox);
139
140         /* Safe strcpy */
141         strcpy(mwi_stasis_sub->mailbox, mailbox);
142         ao2_ref(mwi_sub, +1);
143         ast_debug(3, "Creating stasis MWI subscription to mailbox %s for endpoint %s\n", mailbox, mwi_sub->id);
144         mwi_stasis_sub->stasis_sub = stasis_subscribe(topic, mwi_stasis_cb, mwi_sub);
145         return mwi_stasis_sub;
146 }
147
148 static int stasis_sub_hash(const void *obj, int flags)
149 {
150         const struct mwi_stasis_subscription *mwi_stasis = obj;
151
152         return ast_str_hash(mwi_stasis->mailbox);
153 }
154
155 static int stasis_sub_cmp(void *obj, void *arg, int flags)
156 {
157         struct mwi_stasis_subscription *mwi_stasis1 = obj;
158         struct mwi_stasis_subscription *mwi_stasis2 = arg;
159
160         return strcmp(mwi_stasis1->mailbox, mwi_stasis2->mailbox) ? 0 : CMP_MATCH;
161 }
162
163 static void mwi_subscription_destructor(void *obj)
164 {
165         struct mwi_subscription *sub = obj;
166
167         ast_debug(3, "Destroying MWI subscription for endpoint %s\n", sub->id);
168         ao2_cleanup(sub->sip_sub);
169         ao2_cleanup(sub->stasis_subs);
170 }
171
172 static struct mwi_subscription *mwi_subscription_alloc(struct ast_sip_endpoint *endpoint,
173                 enum ast_sip_subscription_role role, unsigned int is_solicited, pjsip_rx_data *rdata)
174 {
175         struct mwi_subscription *sub;
176         const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
177
178         sub = ao2_alloc(sizeof(*sub) + strlen(endpoint_id),
179                         mwi_subscription_destructor);
180
181         if (!sub) {
182                 return NULL;
183         }
184
185         /* Safe strcpy */
186         strcpy(sub->id, endpoint_id);
187         /* Unsolicited MWI doesn't actually result in a SIP subscription being
188          * created. This is because a SIP subscription associates with a dialog.
189          * Most devices expect unsolicited MWI NOTIFYs to appear out of dialog. If
190          * they receive an in-dialog MWI NOTIFY (i.e. with a to-tag), then they
191          * will reject the NOTIFY with a 481, thus resulting in message-waiting
192          * state not being updated on the device
193          */
194         if (is_solicited) {
195                 sub->sip_sub = ast_sip_create_subscription(&mwi_handler,
196                                 role, endpoint, rdata);
197                 if (!sub->sip_sub) {
198                         ast_log(LOG_WARNING, "Unable to create MWI SIP subscription for endpoint %s\n", sub->id);
199                         ao2_cleanup(sub);
200                         return NULL;
201                 }
202         }
203
204         sub->stasis_subs = ao2_container_alloc(STASIS_BUCKETS, stasis_sub_hash, stasis_sub_cmp);
205         if (!sub->stasis_subs) {
206                 ao2_cleanup(sub);
207                 return NULL;
208         }
209         sub->is_solicited = is_solicited;
210
211         ast_debug(3, "Created %s MWI subscription for endpoint %s\n", is_solicited ? "solicited" : "unsolicited", sub->id);
212
213         return sub;
214 }
215
216 static int mwi_sub_hash(const void *obj, int flags)
217 {
218         const struct mwi_subscription *mwi_sub = obj;
219
220         return ast_str_hash(mwi_sub->id);
221 }
222
223 static int mwi_sub_cmp(void *obj, void *arg, int flags)
224 {
225         struct mwi_subscription *mwi_sub1 = obj;
226         struct mwi_subscription *mwi_sub2 = arg;
227
228         return strcmp(mwi_sub1->id, mwi_sub2->id) ? 0 : CMP_MATCH;
229 }
230
231 static int get_message_count(void *obj, void *arg, int flags)
232 {
233         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
234         struct mwi_stasis_subscription *mwi_stasis = obj;
235         struct ast_sip_message_accumulator *counter = arg;
236         struct ast_mwi_state *mwi_state;
237
238         msg = stasis_cache_get(ast_mwi_state_cache(), ast_mwi_state_type(), mwi_stasis->mailbox);
239         if (!msg) {
240                 return 0;
241         }
242
243         mwi_state = stasis_message_data(msg);
244         counter->old_msgs += mwi_state->old_msgs;
245         counter->new_msgs += mwi_state->new_msgs;
246         return 0;
247 }
248
249 struct unsolicited_mwi_data {
250         struct mwi_subscription *sub;
251         struct ast_sip_endpoint *endpoint;
252         pjsip_evsub_state state;
253         const char *reason;
254         const pjsip_media_type *mwi_type;
255         const pj_str_t *body_text;
256 };
257
258 static int send_unsolicited_mwi_notify_to_contact(void *obj, void *arg, int flags)
259 {
260         struct unsolicited_mwi_data *mwi_data = arg;
261         struct mwi_subscription *sub = mwi_data->sub;
262         struct ast_sip_endpoint *endpoint = mwi_data->endpoint;
263         pjsip_evsub_state state = mwi_data->state;
264         const char *reason = mwi_data->reason;
265         const pjsip_media_type *mwi_type = mwi_data->mwi_type;
266         const pj_str_t *body_text = mwi_data->body_text;
267         struct ast_sip_contact *contact = obj;
268         const char *state_name;
269         pjsip_tx_data *tdata;
270         pjsip_msg_body *msg_body;
271         pjsip_sub_state_hdr *sub_state;
272         pjsip_event_hdr *event;
273         const pjsip_hdr *allow_events = pjsip_evsub_get_allow_events_hdr(NULL);
274
275         if (ast_sip_create_request("NOTIFY", NULL, endpoint, NULL, contact, &tdata)) {
276                 ast_log(LOG_WARNING, "Unable to create unsolicited NOTIFY request to endpoint %s URI %s\n", sub->id, contact->uri);
277                 return 0;
278         }
279
280         if (!ast_strlen_zero(endpoint->subscription.mwi.fromuser)) {
281                 pjsip_fromto_hdr *from = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_FROM, NULL);
282                 pjsip_name_addr *from_name_addr = (pjsip_name_addr *) from->uri;
283                 pjsip_sip_uri *from_uri = pjsip_uri_get_uri(from_name_addr->uri);
284
285                 pj_strdup2(tdata->pool, &from_uri->user, endpoint->subscription.mwi.fromuser);
286         }
287
288         switch (state) {
289         case PJSIP_EVSUB_STATE_ACTIVE:
290                 state_name = "active";
291                 break;
292         case PJSIP_EVSUB_STATE_TERMINATED:
293         default:
294                 state_name = "terminated";
295                 break;
296         }
297
298         sub_state = pjsip_sub_state_hdr_create(tdata->pool);
299         pj_cstr(&sub_state->sub_state, state_name);
300         if (reason) {
301                 pj_cstr(&sub_state->reason_param, reason);
302         }
303         pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) sub_state);
304
305         event = pjsip_event_hdr_create(tdata->pool);
306         pj_cstr(&event->event_type, "message-summary");
307         pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) event);
308
309         pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_shallow_clone(tdata->pool, allow_events));
310         msg_body = pjsip_msg_body_create(tdata->pool, &mwi_type->type, &mwi_type->subtype, body_text);
311         tdata->msg->body = msg_body;
312         ast_sip_send_request(tdata, NULL, endpoint, NULL, NULL);
313
314         return 0;
315 }
316
317 static void send_unsolicited_mwi_notify(struct mwi_subscription *sub, pjsip_evsub_state state, const char *reason,
318                 const pjsip_media_type *mwi_type, const pj_str_t *body_text)
319 {
320         RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(),
321                                 "endpoint", sub->id), ao2_cleanup);
322         char *endpoint_aors;
323         char *aor_name;
324
325         if (!endpoint) {
326                 ast_log(LOG_WARNING, "Unable to send unsolicited MWI to %s because endpoint does not exist\n",
327                                 sub->id);
328                 return;
329         }
330         if (ast_strlen_zero(endpoint->aors)) {
331                 ast_log(LOG_WARNING, "Unable to send unsolicited MWI to %s because the endpoint has no"
332                                 " configured AORs\n", sub->id);
333                 return;
334         }
335
336         endpoint_aors = ast_strdupa(endpoint->aors);
337
338         while ((aor_name = strsep(&endpoint_aors, ","))) {
339                 RAII_VAR(struct ast_sip_aor *, aor, ast_sip_location_retrieve_aor(aor_name), ao2_cleanup);
340                 RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
341                 struct unsolicited_mwi_data mwi_data = {
342                         .sub = sub,
343                         .endpoint = endpoint,
344                         .state = state,
345                         .reason = reason,
346                         .mwi_type = mwi_type,
347                         .body_text = body_text,
348                 };
349
350                 if (!aor) {
351                         ast_log(LOG_WARNING, "Unable to locate AOR %s for unsolicited MWI\n", aor_name);
352                         continue;
353                 }
354
355                 contacts = ast_sip_location_retrieve_aor_contacts(aor);
356                 if (!contacts || (ao2_container_count(contacts) == 0)) {
357                         ast_log(LOG_WARNING, "No contacts bound to AOR %s. Cannot send unsolicited MWI.\n", aor_name);
358                         continue;
359                 }
360
361                 ao2_callback(contacts, OBJ_NODATA, send_unsolicited_mwi_notify_to_contact, &mwi_data);
362         }
363 }
364
365 static void send_mwi_notify(struct mwi_subscription *sub, pjsip_evsub_state state, const char *reason)
366 {
367         const pj_str_t *reason_str_ptr = NULL;
368         struct ast_sip_message_accumulator counter = {
369                 .old_msgs = 0,
370                 .new_msgs = 0,
371         };
372         RAII_VAR(struct ast_str *, body, ast_str_create(64), ast_free_ptr);
373         pjsip_tx_data *tdata;
374         pj_str_t reason_str;
375         pj_str_t pj_body;
376         const char *type = sub->is_solicited ?
377                 ast_sip_subscription_get_body_type(sub->sip_sub) :
378                 MWI_TYPE;
379         const char *subtype = sub->is_solicited ?
380                 ast_sip_subscription_get_body_subtype(sub->sip_sub) :
381                 MWI_SUBTYPE;
382         pjsip_media_type mwi_type = { { 0,}, };
383
384         ao2_callback(sub->stasis_subs, OBJ_NODATA, get_message_count, &counter);
385
386         if (reason) {
387                 pj_cstr(&reason_str, reason);
388                 reason_str_ptr = &reason_str;
389         }
390
391         if (ast_sip_pubsub_generate_body_content(type, subtype, &counter, &body)) {
392                 ast_log(LOG_WARNING, "Unable to generate SIP MWI NOTIFY body.\n");
393                 return;
394         }
395
396         pj_cstr(&pj_body, ast_str_buffer(body));
397         pj_cstr(&mwi_type.type, type);
398         pj_cstr(&mwi_type.subtype, subtype);
399
400         ast_debug(5, "Sending %s MWI NOTIFY to endpoint %s, new messages: %d, old messages: %d\n",
401                         sub->is_solicited ? "solicited" : "unsolicited", sub->id, counter.new_msgs,
402                         counter.old_msgs);
403
404         if (sub->is_solicited) {
405                 if (pjsip_mwi_notify(ast_sip_subscription_get_evsub(sub->sip_sub),
406                                 state,
407                                 NULL,
408                                 reason_str_ptr,
409                                 &mwi_type,
410                                 &pj_body,
411                                 &tdata) != PJ_SUCCESS) {
412                         ast_log(LOG_WARNING, "Unable to create MWI NOTIFY request to %s.\n", sub->id);
413                         return;
414                 }
415                 if (ast_sip_subscription_send_request(sub->sip_sub, tdata) != PJ_SUCCESS) {
416                         ast_log(LOG_WARNING, "Unable to send MWI NOTIFY request to %s\n", sub->id);
417                         return;
418                 }
419         } else {
420                 send_unsolicited_mwi_notify(sub, state, reason, &mwi_type, &pj_body);
421         }
422 }
423
424 static int unsubscribe_stasis(void *obj, void *arg, int flags)
425 {
426         struct mwi_stasis_subscription *mwi_stasis = obj;
427         if (mwi_stasis->stasis_sub) {
428                 ast_debug(3, "Removing stasis subscription to mailbox %s\n", mwi_stasis->mailbox);
429                 mwi_stasis->stasis_sub = stasis_unsubscribe(mwi_stasis->stasis_sub);
430         }
431         return CMP_MATCH;
432 }
433
434 static void mwi_subscription_shutdown(struct ast_sip_subscription *sub)
435 {
436         struct mwi_subscription *mwi_sub;
437         RAII_VAR(struct ast_datastore *, mwi_datastore,
438                         ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
439
440         if (!mwi_datastore) {
441                 return;
442         }
443
444         mwi_sub = mwi_datastore->data;
445         ao2_callback(mwi_sub->stasis_subs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe_stasis, NULL);
446 }
447
448 static struct ast_datastore_info mwi_ds_info = { };
449
450 static int add_mwi_datastore(struct mwi_subscription *sub)
451 {
452         RAII_VAR(struct ast_datastore *, mwi_datastore, NULL, ao2_cleanup);
453
454         mwi_datastore = ast_sip_subscription_alloc_datastore(&mwi_ds_info, "MWI datastore");
455         if (!mwi_datastore) {
456                 return -1;
457         }
458         mwi_datastore->data = sub;
459
460         ast_sip_subscription_add_datastore(sub->sip_sub, mwi_datastore);
461         return 0;
462 }
463
464 static int mwi_on_aor(void *obj, void *arg, int flags)
465 {
466         struct ast_sip_aor *aor = obj;
467         struct mwi_subscription *sub = arg;
468         char *mailboxes;
469         char *mailbox;
470
471         if (ast_strlen_zero(aor->mailboxes)) {
472                 return 0;
473         }
474
475         mailboxes = ast_strdupa(aor->mailboxes);
476         while ((mailbox = strsep(&mailboxes, ","))) {
477                 RAII_VAR(struct mwi_stasis_subscription *, mwi_stasis_sub,
478                                 mwi_stasis_subscription_alloc(mailbox, sub), ao2_cleanup);
479                 if (mwi_stasis_sub) {
480                         ao2_link(sub->stasis_subs, mwi_stasis_sub);
481                 }
482         }
483
484         return 0;
485 }
486
487 static struct mwi_subscription *mwi_create_subscription(
488         struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
489 {
490         struct mwi_subscription *sub = mwi_subscription_alloc(
491                 endpoint, AST_SIP_NOTIFIER, 1, rdata);
492
493         if (!sub) {
494                 return NULL;
495         }
496
497         if (add_mwi_datastore(sub)) {
498                 ast_log(LOG_WARNING, "Unable to allocate datastore on MWI "
499                         "subscription from %s\n", sub->id);
500                 ao2_ref(sub, -1);
501                 return NULL;
502         }
503
504         return sub;
505 }
506
507 static struct mwi_subscription *mwi_subscribe_single(
508         struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *name)
509 {
510         RAII_VAR(struct ast_sip_aor *, aor,
511                  ast_sip_location_retrieve_aor(name), ao2_cleanup);
512         struct mwi_subscription *sub;
513
514         if (!aor) {
515                 ast_log(LOG_WARNING, "Unable to locate aor %s. MWI "
516                         "subscription failed.\n", name);
517                 return NULL;
518         }
519
520         if (ast_strlen_zero(aor->mailboxes)) {
521                 ast_log(LOG_WARNING, "AOR %s has no configured mailboxes. "
522                         "MWI subscription failed\n", name);
523                 return NULL;
524         }
525
526         if (!(sub = mwi_create_subscription(endpoint, rdata))) {
527                 return NULL;
528         }
529
530         mwi_on_aor(aor, sub, 0);
531         return sub;
532 }
533
534 static struct mwi_subscription *mwi_subscribe_all(
535         struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
536 {
537         struct mwi_subscription *sub = mwi_create_subscription(endpoint, rdata);
538
539         if (!sub) {
540                 return NULL;
541         }
542
543         ast_sip_for_each_aor(endpoint->aors, mwi_on_aor, sub);
544         return sub;
545 }
546
547 static struct ast_sip_subscription *mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
548                 pjsip_rx_data *rdata)
549 {
550         /* It's not obvious here, but the reference(s) to this subscription,
551          * once this function exits, is held by the stasis subscription(s)
552          * created in mwi_stasis_subscription_alloc()
553          */
554         RAII_VAR(struct mwi_subscription *, sub, NULL, ao2_cleanup);
555         pjsip_uri *ruri = rdata->msg_info.msg->line.req.uri;
556         pjsip_sip_uri *sip_ruri;
557         pjsip_evsub *evsub;
558         char aor_name[80];
559
560         if (!PJSIP_URI_SCHEME_IS_SIP(ruri) && !PJSIP_URI_SCHEME_IS_SIPS(ruri)) {
561                 ast_log(LOG_WARNING, "Attempt to SUBSCRIBE to a non-SIP URI\n");
562                 return NULL;
563         }
564         sip_ruri = pjsip_uri_get_uri(ruri);
565         ast_copy_pj_str(aor_name, &sip_ruri->user, sizeof(aor_name));
566
567         /* no aor in uri? subscribe to all on endpoint */
568         if (!(sub = ast_strlen_zero(aor_name) ? mwi_subscribe_all(endpoint, rdata) :
569               mwi_subscribe_single(endpoint, rdata, aor_name))) {
570                 return NULL;
571         }
572
573         evsub = ast_sip_subscription_get_evsub(sub->sip_sub);
574         pjsip_evsub_accept(evsub, rdata, 200, NULL);
575         send_mwi_notify(sub, PJSIP_EVSUB_STATE_ACTIVE, NULL);
576
577         return sub->sip_sub;
578 }
579
580 static void mwi_resubscribe(struct ast_sip_subscription *sub,
581                 pjsip_rx_data *rdata, struct ast_sip_subscription_response_data *response_data)
582 {
583         pjsip_tx_data *tdata;
584
585         pjsip_mwi_current_notify(ast_sip_subscription_get_evsub(sub), &tdata);
586         ast_sip_subscription_send_request(sub, tdata);
587 }
588
589 static void mwi_subscription_timeout(struct ast_sip_subscription *sub)
590 {
591         struct mwi_subscription *mwi_sub;
592         RAII_VAR(struct ast_datastore *, mwi_datastore,
593                         ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
594
595         if (!mwi_datastore) {
596                 return;
597         }
598
599
600         mwi_sub = mwi_datastore->data;
601
602         ast_log(LOG_NOTICE, "MWI subscription for %s has timed out.\n", mwi_sub->id);
603
604         send_mwi_notify(mwi_sub, PJSIP_EVSUB_STATE_TERMINATED, "timeout");
605 }
606
607 static void mwi_subscription_terminated(struct ast_sip_subscription *sub, pjsip_rx_data *rdata)
608 {
609         struct mwi_subscription *mwi_sub;
610         RAII_VAR(struct ast_datastore *, mwi_datastore,
611                         ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
612
613         if (!mwi_datastore) {
614                 return;
615         }
616
617         mwi_sub = mwi_datastore->data;
618
619         ast_log(LOG_NOTICE, "MWI subscription for %s has been terminated\n", mwi_sub->id);
620
621         send_mwi_notify(mwi_sub, PJSIP_EVSUB_STATE_TERMINATED, NULL);
622 }
623
624 static void mwi_notify_response(struct ast_sip_subscription *sub, pjsip_rx_data *rdata)
625 {
626         /* We don't really care about NOTIFY responses for the moment */
627 }
628
629 static void mwi_notify_request(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
630                 struct ast_sip_subscription_response_data *response_data)
631 {
632         ast_log(LOG_WARNING, "Received an MWI NOTIFY request? This should not happen\n");
633 }
634
635 static int mwi_refresh_subscription(struct ast_sip_subscription *sub)
636 {
637         ast_log(LOG_WARNING, "Being told to refresh an MWI subscription? This should not happen\n");
638         return 0;
639 }
640
641 static void mwi_subscription_mailboxes_str(struct ao2_container *stasis_subs,
642                                            struct ast_str **str)
643 {
644         int num = ao2_container_count(stasis_subs);
645
646         struct mwi_stasis_subscription *node;
647         struct ao2_iterator i = ao2_iterator_init(stasis_subs, 0);
648
649         while ((node = ao2_iterator_next(&i))) {
650                 if (--num) {
651                         ast_str_append(str, 0, "%s,", node->mailbox);
652                 } else {
653                         ast_str_append(str, 0, "%s", node->mailbox);
654                 }
655                 ao2_ref(node, -1);
656         }
657         ao2_iterator_destroy(&i);
658 }
659
660 static void mwi_to_ami(struct ast_sip_subscription *sub,
661                        struct ast_str **buf)
662 {
663         struct mwi_subscription *mwi_sub;
664         RAII_VAR(struct ast_datastore *, mwi_datastore,
665                         ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
666
667         if (!mwi_datastore) {
668                 return;
669         }
670
671         mwi_sub = mwi_datastore->data;
672
673         ast_str_append(buf, 0, "SubscriptionType: mwi\r\n");
674         ast_str_append(buf, 0, "Mailboxes: ");
675         mwi_subscription_mailboxes_str(mwi_sub->stasis_subs, buf);
676         ast_str_append(buf, 0, "\r\n");
677 }
678
679 static int serialized_notify(void *userdata)
680 {
681         struct mwi_subscription *mwi_sub = userdata;
682
683         send_mwi_notify(mwi_sub, PJSIP_EVSUB_STATE_ACTIVE, NULL);
684         ao2_ref(mwi_sub, -1);
685         return 0;
686 }
687
688 static int serialized_cleanup(void *userdata)
689 {
690         struct mwi_subscription *mwi_sub = userdata;
691
692         /* This is getting rid of the reference that was added
693          * just before this serialized task was pushed.
694          */
695         ao2_cleanup(mwi_sub);
696         /* This is getting rid of the reference held by the
697          * stasis subscription
698          */
699         ao2_cleanup(mwi_sub);
700         return 0;
701 }
702
703 static void mwi_stasis_cb(void *userdata, struct stasis_subscription *sub,
704                 struct stasis_message *msg)
705 {
706         struct mwi_subscription *mwi_sub = userdata;
707
708         if (stasis_subscription_final_message(sub, msg)) {
709                 ao2_ref(mwi_sub, +1);
710                 ast_sip_push_task(NULL, serialized_cleanup, mwi_sub);
711                 return;
712         }
713
714         if (ast_mwi_state_type() == stasis_message_type(msg)) {
715                 struct ast_taskprocessor *serializer = mwi_sub->is_solicited ? ast_sip_subscription_get_serializer(mwi_sub->sip_sub) : NULL;
716                 ao2_ref(mwi_sub, +1);
717                 ast_sip_push_task(serializer, serialized_notify, mwi_sub);
718         }
719 }
720
721 static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags)
722 {
723         RAII_VAR(struct mwi_subscription *, aggregate_sub, NULL, ao2_cleanup);
724         struct ast_sip_endpoint *endpoint = obj;
725         struct ao2_container *mwi_subscriptions = arg;
726         char *mailboxes;
727         char *mailbox;
728
729         if (ast_strlen_zero(endpoint->subscription.mwi.mailboxes)) {
730                 return 0;
731         }
732
733         if (endpoint->subscription.mwi.aggregate) {
734                 aggregate_sub = mwi_subscription_alloc(endpoint, AST_SIP_NOTIFIER, 0, NULL);
735                 if (!aggregate_sub) {
736                         return 0;
737                 }
738         }
739
740         mailboxes = ast_strdupa(endpoint->subscription.mwi.mailboxes);
741         while ((mailbox = strsep(&mailboxes, ","))) {
742                 struct mwi_subscription *sub = aggregate_sub ?:
743                         mwi_subscription_alloc(endpoint, AST_SIP_SUBSCRIBER, 0, NULL);
744                 RAII_VAR(struct mwi_stasis_subscription *, mwi_stasis_sub,
745                                 mwi_stasis_subscription_alloc(mailbox, sub), ao2_cleanup);
746                 if (mwi_stasis_sub) {
747                         ao2_link(sub->stasis_subs, mwi_stasis_sub);
748                 }
749                 if (!aggregate_sub) {
750                         ao2_link(mwi_subscriptions, sub);
751                         ao2_cleanup(sub);
752                 }
753         }
754         ao2_link(mwi_subscriptions, aggregate_sub);
755         return 0;
756 }
757
758 static int unsubscribe(void *obj, void *arg, int flags)
759 {
760         struct mwi_subscription *mwi_sub = obj;
761
762         ao2_callback(mwi_sub->stasis_subs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe_stasis, NULL);
763         return CMP_MATCH;
764 }
765
766 static void create_mwi_subscriptions(void)
767 {
768         struct ao2_container *mwi_subscriptions = ao2_container_alloc(MWI_BUCKETS, mwi_sub_hash, mwi_sub_cmp);
769         RAII_VAR(struct ao2_container *, old_mwi_subscriptions, ao2_global_obj_ref(unsolicited_mwi), ao2_cleanup);
770         RAII_VAR(struct ao2_container *, endpoints, ast_sorcery_retrieve_by_fields(
771                                 ast_sip_get_sorcery(), "endpoint", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL),
772                         ao2_cleanup);
773
774         if (!mwi_subscriptions) {
775                 return;
776         }
777
778         /* We remove all the old stasis subscriptions first before applying the new configuration. This
779          * prevents a situation where there might be multiple overlapping stasis subscriptions for an
780          * endpoint for mailboxes. Though there may be mailbox changes during the gap between unsubscribing
781          * and resubscribing, up-to-date mailbox state will be sent out to the endpoint when the
782          * new stasis subscription is established
783          */
784         if (old_mwi_subscriptions) {
785                 ao2_callback(old_mwi_subscriptions, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
786         }
787         ao2_callback(endpoints, OBJ_NODATA, create_mwi_subscriptions_for_endpoint, mwi_subscriptions);
788         ao2_global_obj_replace_unref(unsolicited_mwi, mwi_subscriptions);
789         ao2_ref(mwi_subscriptions, -1);
790 }
791
792 static int reload(void)
793 {
794         create_mwi_subscriptions();
795         return 0;
796 }
797
798 static int load_module(void)
799 {
800         if (ast_sip_register_subscription_handler(&mwi_handler)) {
801                 return AST_MODULE_LOAD_DECLINE;
802         }
803         create_mwi_subscriptions();
804         return AST_MODULE_LOAD_SUCCESS;
805 }
806
807 static int unload_module(void)
808 {
809         RAII_VAR(struct ao2_container *, mwi_subscriptions, ao2_global_obj_ref(unsolicited_mwi), ao2_cleanup);
810         if (mwi_subscriptions) {
811                 ao2_callback(mwi_subscriptions, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
812                 ao2_global_obj_release(unsolicited_mwi);
813         }
814         ast_sip_unregister_subscription_handler(&mwi_handler);
815         return 0;
816 }
817
818 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP MWI resource",
819                 .load = load_module,
820                 .unload = unload_module,
821                 .reload = reload,
822                 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
823 );