Improve call forwarding reporting, especially with regards to ARI.
[asterisk/asterisk.git] / main / stasis_channels.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Matt Jordan <mjordan@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 /*! \file
20  *
21  * \brief Stasis Messages and Data Types for Channel Objects
22  *
23  * \author \verbatim Matt Jordan <mjordan@digium.com> \endverbatim
24  *
25  */
26
27 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 #include "asterisk/astobj2.h"
36 #include "asterisk/json.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/bridge.h"
39 #include "asterisk/translate.h"
40 #include "asterisk/stasis.h"
41 #include "asterisk/stasis_cache_pattern.h"
42 #include "asterisk/stasis_channels.h"
43
44 /*** DOCUMENTATION
45         <managerEvent language="en_US" name="VarSet">
46                 <managerEventInstance class="EVENT_FLAG_DIALPLAN">
47                         <synopsis>Raised when a variable is set to a particular value.</synopsis>
48                         <syntax>
49                                 <channel_snapshot/>
50                                 <parameter name="Variable">
51                                         <para>The variable being set.</para>
52                                 </parameter>
53                                 <parameter name="Value">
54                                         <para>The new value of the variable.</para>
55                                 </parameter>
56                         </syntax>
57                 </managerEventInstance>
58         </managerEvent>
59         <managerEvent language="en_US" name="AgentLogin">
60                 <managerEventInstance class="EVENT_FLAG_AGENT">
61                         <synopsis>Raised when an Agent has logged in.</synopsis>
62                         <syntax>
63                                 <channel_snapshot/>
64                                 <parameter name="Agent">
65                                         <para>Agent ID of the agent.</para>
66                                 </parameter>
67                         </syntax>
68                         <see-also>
69                                 <ref type="application">AgentLogin</ref>
70                                 <ref type="managerEvent">AgentLogoff</ref>
71                         </see-also>
72                 </managerEventInstance>
73         </managerEvent>
74         <managerEvent language="en_US" name="AgentLogoff">
75                 <managerEventInstance class="EVENT_FLAG_AGENT">
76                         <synopsis>Raised when an Agent has logged off.</synopsis>
77                         <syntax>
78                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentLogin']/managerEventInstance/syntax/parameter)" />
79                                 <parameter name="Logintime">
80                                         <para>The number of seconds the agent was logged in.</para>
81                                 </parameter>
82                         </syntax>
83                         <see-also>
84                                 <ref type="managerEvent">AgentLogin</ref>
85                         </see-also>
86                 </managerEventInstance>
87         </managerEvent>
88         <managerEvent language="en_US" name="ChannelTalkingStart">
89                 <managerEventInstance class="EVENT_FLAG_CLASS">
90                         <synopsis>Raised when talking is detected on a channel.</synopsis>
91                         <syntax>
92                                 <channel_snapshot/>
93                         </syntax>
94                         <see-also>
95                                 <ref type="function">TALK_DETECT</ref>
96                                 <ref type="managerEvent">ChannelTalkingStop</ref>
97                         </see-also>
98                 </managerEventInstance>
99         </managerEvent>
100         <managerEvent language="en_US" name="ChannelTalkingStop">
101                 <managerEventInstance class="EVENT_FLAG_CLASS">
102                         <synopsis>Raised when talking is no longer detected on a channel.</synopsis>
103                         <syntax>
104                                 <channel_snapshot/>
105                                 <parameter name="Duration">
106                                         <para>The length in time, in milliseconds, that talking was
107                                         detected on the channel.</para>
108                                 </parameter>
109                         </syntax>
110                         <see-also>
111                                 <ref type="function">TALK_DETECT</ref>
112                                 <ref type="managerEvent">ChannelTalkingStart</ref>
113                         </see-also>
114                 </managerEventInstance>
115         </managerEvent>
116 ***/
117
118 #define NUM_MULTI_CHANNEL_BLOB_BUCKETS 7
119
120 static struct stasis_cp_all *channel_cache_all;
121 static struct stasis_cache *channel_cache_by_name;
122 static struct stasis_caching_topic *channel_by_name_topic;
123
124 struct stasis_cp_all *ast_channel_cache_all(void)
125 {
126         return channel_cache_all;
127 }
128
129 struct stasis_cache *ast_channel_cache(void)
130 {
131         return stasis_cp_all_cache(channel_cache_all);
132 }
133
134 struct stasis_topic *ast_channel_topic_all(void)
135 {
136         return stasis_cp_all_topic(channel_cache_all);
137 }
138
139 struct stasis_topic *ast_channel_topic_all_cached(void)
140 {
141         return stasis_cp_all_topic_cached(channel_cache_all);
142 }
143
144 struct stasis_cache *ast_channel_cache_by_name(void)
145 {
146         return channel_cache_by_name;
147 }
148
149 static const char *channel_snapshot_get_id(struct stasis_message *message)
150 {
151         struct ast_channel_snapshot *snapshot;
152         if (ast_channel_snapshot_type() != stasis_message_type(message)) {
153                 return NULL;
154         }
155         snapshot = stasis_message_data(message);
156         return snapshot->uniqueid;
157 }
158
159 static const char *channel_snapshot_get_name(struct stasis_message *message)
160 {
161         struct ast_channel_snapshot *snapshot;
162         if (ast_channel_snapshot_type() != stasis_message_type(message)) {
163                 return NULL;
164         }
165         snapshot = stasis_message_data(message);
166         return snapshot->name;
167 }
168
169 /*!
170  * \internal
171  * \brief Hash function for \ref ast_channel_snapshot objects
172  */
173 static int channel_snapshot_hash_cb(const void *obj, const int flags)
174 {
175         const struct ast_channel_snapshot *snapshot = obj;
176         const char *name = (flags & OBJ_KEY) ? obj : snapshot->name;
177         return ast_str_case_hash(name);
178 }
179
180 /*!
181  * \internal
182  * \brief Comparison function for \ref ast_channel_snapshot objects
183  */
184 static int channel_snapshot_cmp_cb(void *obj, void *arg, int flags)
185 {
186         struct ast_channel_snapshot *left = obj;
187         struct ast_channel_snapshot *right = arg;
188         const char *match = (flags & OBJ_KEY) ? arg : right->name;
189         return strcasecmp(left->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
190 }
191
192 static void channel_snapshot_dtor(void *obj)
193 {
194         struct ast_channel_snapshot *snapshot = obj;
195
196         ast_string_field_free_memory(snapshot);
197         ao2_cleanup(snapshot->manager_vars);
198 }
199
200 struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
201 {
202         struct ast_channel_snapshot *snapshot;
203         struct ast_bridge *bridge;
204
205         /* no snapshots for dummy channels */
206         if (!ast_channel_tech(chan)) {
207                 return NULL;
208         }
209
210         snapshot = ao2_alloc(sizeof(*snapshot), channel_snapshot_dtor);
211         if (!snapshot || ast_string_field_init(snapshot, 1024)) {
212                 ao2_cleanup(snapshot);
213                 return NULL;
214         }
215
216         ast_string_field_set(snapshot, name, ast_channel_name(chan));
217         ast_string_field_set(snapshot, type, ast_channel_tech(chan)->type);
218         ast_string_field_set(snapshot, accountcode, ast_channel_accountcode(chan));
219         ast_string_field_set(snapshot, peeraccount, ast_channel_peeraccount(chan));
220         ast_string_field_set(snapshot, userfield, ast_channel_userfield(chan));
221         ast_string_field_set(snapshot, uniqueid, ast_channel_uniqueid(chan));
222         ast_string_field_set(snapshot, linkedid, ast_channel_linkedid(chan));
223         ast_string_field_set(snapshot, hangupsource, ast_channel_hangupsource(chan));
224         if (ast_channel_appl(chan)) {
225                 ast_string_field_set(snapshot, appl, ast_channel_appl(chan));
226         }
227         if (ast_channel_data(chan)) {
228                 ast_string_field_set(snapshot, data, ast_channel_data(chan));
229         }
230         ast_string_field_set(snapshot, context, ast_channel_context(chan));
231         ast_string_field_set(snapshot, exten, ast_channel_exten(chan));
232
233         ast_string_field_set(snapshot, caller_name,
234                 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));
235         ast_string_field_set(snapshot, caller_number,
236                 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));
237         ast_string_field_set(snapshot, caller_dnid, S_OR(ast_channel_dialed(chan)->number.str, ""));
238         ast_string_field_set(snapshot, caller_subaddr,
239                 S_COR(ast_channel_caller(chan)->id.subaddress.valid, ast_channel_caller(chan)->id.subaddress.str, ""));
240         ast_string_field_set(snapshot, dialed_subaddr,
241                 S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, ""));
242         ast_string_field_set(snapshot, caller_ani,
243                 S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""));
244         ast_string_field_set(snapshot, caller_rdnis,
245                 S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""));
246         ast_string_field_set(snapshot, caller_dnid,
247                 S_OR(ast_channel_dialed(chan)->number.str, ""));
248
249         ast_string_field_set(snapshot, connected_name,
250                 S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""));
251         ast_string_field_set(snapshot, connected_number,
252                 S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""));
253         ast_string_field_set(snapshot, language, ast_channel_language(chan));
254
255         if ((bridge = ast_channel_get_bridge(chan))) {
256                 ast_string_field_set(snapshot, bridgeid, bridge->uniqueid);
257                 ao2_cleanup(bridge);
258         }
259
260         snapshot->creationtime = ast_channel_creationtime(chan);
261         snapshot->state = ast_channel_state(chan);
262         snapshot->priority = ast_channel_priority(chan);
263         snapshot->amaflags = ast_channel_amaflags(chan);
264         snapshot->hangupcause = ast_channel_hangupcause(chan);
265         ast_copy_flags(&snapshot->flags, ast_channel_flags(chan), 0xFFFFFFFF);
266         snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
267         ast_set_flag(&snapshot->softhangup_flags, ast_channel_softhangup_internal_flag(chan));
268
269         snapshot->manager_vars = ast_channel_get_manager_vars(chan);
270         snapshot->tech_properties = ast_channel_tech(chan)->properties;
271
272         return snapshot;
273 }
274
275 static void publish_message_for_channel_topics(struct stasis_message *message, struct ast_channel *chan)
276 {
277         if (chan) {
278                 stasis_publish(ast_channel_topic(chan), message);
279         } else {
280                 stasis_publish(ast_channel_topic_all(), message);
281         }
282 }
283
284 static void channel_blob_dtor(void *obj)
285 {
286         struct ast_channel_blob *event = obj;
287         ao2_cleanup(event->snapshot);
288         ast_json_unref(event->blob);
289 }
290
291 void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer,
292         struct ast_channel *forwarded, const char *dialstring, const char *dialstatus,
293         const char *forward)
294 {
295         RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
296         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
297         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
298         RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
299         RAII_VAR(struct ast_channel_snapshot *, peer_snapshot, NULL, ao2_cleanup);
300         RAII_VAR(struct ast_channel_snapshot *, forwarded_snapshot, NULL, ao2_cleanup);
301
302         if (!ast_channel_dial_type()) {
303                 return;
304         }
305
306         ast_assert(peer != NULL);
307         blob = ast_json_pack("{s: s, s: s, s: s}",
308                              "dialstatus", S_OR(dialstatus, ""),
309                              "forward", S_OR(forward, ""),
310                              "dialstring", S_OR(dialstring, ""));
311         if (!blob) {
312                 return;
313         }
314         payload = ast_multi_channel_blob_create(blob);
315         if (!payload) {
316                 return;
317         }
318
319         if (caller) {
320                 ast_channel_lock(caller);
321                 if (ast_strlen_zero(dialstatus)) {
322                         caller_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(caller));
323                 } else {
324                         caller_snapshot = ast_channel_snapshot_create(caller);
325                 }
326                 ast_channel_unlock(caller);
327                 if (!caller_snapshot) {
328                         return;
329                 }
330                 ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
331         }
332
333         ast_channel_lock(peer);
334         if (ast_strlen_zero(dialstatus)) {
335                 peer_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(peer));
336         } else {
337                 peer_snapshot = ast_channel_snapshot_create(peer);
338         }
339         ast_channel_unlock(peer);
340         if (!peer_snapshot) {
341                 return;
342         }
343         ast_multi_channel_blob_add_channel(payload, "peer", peer_snapshot);
344
345         if (forwarded) {
346                 ast_channel_lock(forwarded);
347                 forwarded_snapshot = ast_channel_snapshot_create(forwarded);
348                 ast_channel_unlock(forwarded);
349                 if (!forwarded_snapshot) {
350                         return;
351                 }
352                 ast_multi_channel_blob_add_channel(payload, "forwarded", forwarded_snapshot);
353         }
354
355         msg = stasis_message_create(ast_channel_dial_type(), payload);
356         if (!msg) {
357                 return;
358         }
359
360         publish_message_for_channel_topics(msg, caller);
361 }
362
363 void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer,
364         const char *dialstring, const char *dialstatus)
365 {
366         ast_channel_publish_dial_forward(caller, peer, NULL, dialstring, dialstatus, NULL);
367 }
368
369 static struct stasis_message *create_channel_blob_message(struct ast_channel_snapshot *snapshot,
370                 struct stasis_message_type *type,
371                 struct ast_json *blob)
372 {
373         struct stasis_message *msg;
374         struct ast_channel_blob *obj;
375
376         obj = ao2_alloc(sizeof(*obj), channel_blob_dtor);
377         if (!obj) {
378                 return NULL;
379         }
380
381         if (snapshot) {
382                 obj->snapshot = snapshot;
383                 ao2_ref(obj->snapshot, +1);
384         }
385         if (!blob) {
386                 blob = ast_json_null();
387         }
388         obj->blob = ast_json_ref(blob);
389
390         msg = stasis_message_create(type, obj);
391         ao2_cleanup(obj);
392         return msg;
393 }
394
395 struct stasis_message *ast_channel_blob_create_from_cache(const char *channel_id,
396                                                struct stasis_message_type *type,
397                                                struct ast_json *blob)
398 {
399         RAII_VAR(struct ast_channel_snapshot *, snapshot,
400                         NULL,
401                         ao2_cleanup);
402
403         if (!type) {
404                 return NULL;
405         }
406
407         snapshot = ast_channel_snapshot_get_latest(channel_id);
408
409         return create_channel_blob_message(snapshot, type, blob);
410 }
411
412 struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
413         struct stasis_message_type *type, struct ast_json *blob)
414 {
415         RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
416
417         if (!type) {
418                 return NULL;
419         }
420
421         if (chan) {
422                 snapshot = ast_channel_snapshot_create(chan);
423         }
424
425         return create_channel_blob_message(snapshot, type, blob);
426 }
427
428 /*! \brief A channel snapshot wrapper object used in \ref ast_multi_channel_blob objects */
429 struct channel_role_snapshot {
430         struct ast_channel_snapshot *snapshot;  /*!< A channel snapshot */
431         char role[0];                                                   /*!< The role assigned to the channel */
432 };
433
434 /*! \brief A multi channel blob data structure for multi_channel_blob stasis messages */
435 struct ast_multi_channel_blob {
436         struct ao2_container *channel_snapshots;        /*!< A container holding the snapshots */
437         struct ast_json *blob;                                          /*< A blob of JSON data */
438 };
439
440 /*!
441  * \internal
442  * \brief Standard comparison function for \ref channel_role_snapshot objects
443  */
444 static int channel_role_single_cmp_cb(void *obj, void *arg, int flags)
445 {
446         struct channel_role_snapshot *left = obj;
447         struct channel_role_snapshot *right = arg;
448         const char *match = (flags & OBJ_KEY) ? arg : right->role;
449         return strcasecmp(left->role, match) ? 0 : (CMP_MATCH | CMP_STOP);
450 }
451
452 /*!
453  * \internal
454  * \brief Multi comparison function for \ref channel_role_snapshot objects
455  */
456 static int channel_role_multi_cmp_cb(void *obj, void *arg, int flags)
457 {
458         struct channel_role_snapshot *left = obj;
459         struct channel_role_snapshot *right = arg;
460         const char *match = (flags & OBJ_KEY) ? arg : right->role;
461         return strcasecmp(left->role, match) ? 0 : (CMP_MATCH);
462 }
463
464 /*!
465  * \internal
466  * \brief Hash function for \ref channel_role_snapshot objects
467  */
468 static int channel_role_hash_cb(const void *obj, const int flags)
469 {
470         const struct channel_role_snapshot *snapshot = obj;
471         const char *name = (flags & OBJ_KEY) ? obj : snapshot->role;
472         return ast_str_case_hash(name);
473 }
474
475 /*!
476  * \internal
477  * \brief Destructor for \ref ast_multi_channel_blob objects
478  */
479 static void multi_channel_blob_dtor(void *obj)
480 {
481         struct ast_multi_channel_blob *multi_blob = obj;
482
483         ao2_cleanup(multi_blob->channel_snapshots);
484         ast_json_unref(multi_blob->blob);
485 }
486
487 struct ast_multi_channel_blob *ast_multi_channel_blob_create(struct ast_json *blob)
488 {
489         RAII_VAR(struct ast_multi_channel_blob *, obj,
490                         ao2_alloc(sizeof(*obj), multi_channel_blob_dtor),
491                         ao2_cleanup);
492
493         ast_assert(blob != NULL);
494
495         if (!obj) {
496                 return NULL;
497         }
498
499         obj->channel_snapshots = ao2_container_alloc(NUM_MULTI_CHANNEL_BLOB_BUCKETS,
500                         channel_role_hash_cb, channel_role_single_cmp_cb);
501         if (!obj->channel_snapshots) {
502                 return NULL;
503         }
504
505         obj->blob = ast_json_ref(blob);
506
507         ao2_ref(obj, +1);
508         return obj;
509 }
510
511 struct ast_channel_snapshot *ast_channel_snapshot_get_latest(const char *uniqueid)
512 {
513         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
514         struct ast_channel_snapshot *snapshot;
515
516         ast_assert(!ast_strlen_zero(uniqueid));
517
518         message = stasis_cache_get(ast_channel_cache(),
519                         ast_channel_snapshot_type(),
520                         uniqueid);
521         if (!message) {
522                 return NULL;
523         }
524
525         snapshot = stasis_message_data(message);
526         if (!snapshot) {
527                 return NULL;
528         }
529         ao2_ref(snapshot, +1);
530         return snapshot;
531 }
532
533 struct ast_channel_snapshot *ast_channel_snapshot_get_latest_by_name(const char *name)
534 {
535         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
536         struct ast_channel_snapshot *snapshot;
537
538         ast_assert(!ast_strlen_zero(name));
539
540         message = stasis_cache_get(ast_channel_cache_by_name(),
541                         ast_channel_snapshot_type(),
542                         name);
543         if (!message) {
544                 return NULL;
545         }
546
547         snapshot = stasis_message_data(message);
548         if (!snapshot) {
549                 return NULL;
550         }
551         ao2_ref(snapshot, +1);
552         return snapshot;
553 }
554
555 static void channel_role_snapshot_dtor(void *obj)
556 {
557         struct channel_role_snapshot *role_snapshot = obj;
558         ao2_cleanup(role_snapshot->snapshot);
559 }
560
561 void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
562 {
563         RAII_VAR(struct channel_role_snapshot *, role_snapshot, NULL, ao2_cleanup);
564         int role_len = strlen(role) + 1;
565
566         if (!obj || ast_strlen_zero(role) || !snapshot) {
567                 return;
568         }
569
570         role_snapshot = ao2_alloc(sizeof(*role_snapshot) + role_len, channel_role_snapshot_dtor);
571         if (!role_snapshot) {
572                 return;
573         }
574         ast_copy_string(role_snapshot->role, role, role_len);
575         role_snapshot->snapshot = snapshot;
576         ao2_ref(role_snapshot->snapshot, +1);
577         ao2_link(obj->channel_snapshots, role_snapshot);
578 }
579
580 struct ast_channel_snapshot *ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
581 {
582         struct channel_role_snapshot *role_snapshot;
583
584         if (!obj || ast_strlen_zero(role)) {
585                 return NULL;
586         }
587         role_snapshot = ao2_find(obj->channel_snapshots, role, OBJ_KEY);
588         /* Note that this function does not increase the ref count on snapshot */
589         if (!role_snapshot) {
590                 return NULL;
591         }
592         ao2_ref(role_snapshot, -1);
593         return role_snapshot->snapshot;
594 }
595
596 struct ao2_container *ast_multi_channel_blob_get_channels(struct ast_multi_channel_blob *obj, const char *role)
597 {
598         RAII_VAR(struct ao2_container *, ret_container,
599                 ao2_container_alloc(NUM_MULTI_CHANNEL_BLOB_BUCKETS, channel_snapshot_hash_cb, channel_snapshot_cmp_cb),
600                 ao2_cleanup);
601         struct ao2_iterator *it_role_snapshots;
602         struct channel_role_snapshot *role_snapshot;
603         char *arg;
604
605         if (!obj || ast_strlen_zero(role) || !ret_container) {
606                 return NULL;
607         }
608         arg = ast_strdupa(role);
609
610         it_role_snapshots = ao2_callback(obj->channel_snapshots, OBJ_MULTIPLE | OBJ_KEY, channel_role_multi_cmp_cb, arg);
611         if (!it_role_snapshots) {
612                 return NULL;
613         }
614
615         while ((role_snapshot = ao2_iterator_next(it_role_snapshots))) {
616                 ao2_link(ret_container, role_snapshot->snapshot);
617                 ao2_ref(role_snapshot, -1);
618         }
619         ao2_iterator_destroy(it_role_snapshots);
620
621         ao2_ref(ret_container, +1);
622         return ret_container;
623 }
624
625 struct ast_json *ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
626 {
627         if (!obj) {
628                 return NULL;
629         }
630         return obj->blob;
631 }
632
633 void ast_channel_stage_snapshot(struct ast_channel *chan)
634 {
635         ast_set_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE);
636 }
637
638 void ast_channel_stage_snapshot_done(struct ast_channel *chan)
639 {
640         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE);
641         ast_channel_publish_snapshot(chan);
642 }
643
644 void ast_channel_publish_snapshot(struct ast_channel *chan)
645 {
646         RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
647         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
648
649         if (!ast_channel_snapshot_type()) {
650                 return;
651         }
652
653         if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE)) {
654                 return;
655         }
656
657         snapshot = ast_channel_snapshot_create(chan);
658         if (!snapshot) {
659                 return;
660         }
661
662         message = stasis_message_create(ast_channel_snapshot_type(), snapshot);
663         if (!message) {
664                 return;
665         }
666
667         ast_assert(ast_channel_topic(chan) != NULL);
668         stasis_publish(ast_channel_topic(chan), message);
669 }
670
671 void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
672 {
673         struct stasis_message *message;
674
675         if (!blob) {
676                 blob = ast_json_null();
677         }
678
679         message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), type, blob);
680         if (message) {
681                 stasis_publish(ast_channel_topic(chan), message);
682         }
683         ao2_cleanup(message);
684 }
685
686 void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
687 {
688         struct stasis_message *message;
689
690         if (!blob) {
691                 blob = ast_json_null();
692         }
693
694         message = ast_channel_blob_create(chan, type, blob);
695         if (message) {
696                 stasis_publish(ast_channel_topic(chan), message);
697         }
698         ao2_cleanup(message);
699 }
700
701 void ast_channel_publish_varset(struct ast_channel *chan, const char *name, const char *value)
702 {
703         struct ast_json *blob;
704
705         ast_assert(name != NULL);
706         ast_assert(value != NULL);
707
708         blob = ast_json_pack("{s: s, s: s}",
709                              "variable", name,
710                              "value", value);
711         if (!blob) {
712                 ast_log(LOG_ERROR, "Error creating message\n");
713                 return;
714         }
715
716         /*! If there are manager variables, force a cache update */
717         if (chan && ast_channel_has_manager_vars()) {
718                 ast_channel_publish_snapshot(chan);
719         }
720
721         if (chan) {
722                 ast_channel_publish_cached_blob(chan, ast_channel_varset_type(), blob);
723         } else {
724                 /* This function is NULL safe for global variables */
725                 ast_channel_publish_blob(NULL, ast_channel_varset_type(), blob);
726         }
727
728         ast_json_unref(blob);
729 }
730
731 static struct ast_manager_event_blob *varset_to_ami(struct stasis_message *msg)
732 {
733         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
734         struct ast_channel_blob *obj = stasis_message_data(msg);
735         const char *variable =
736                 ast_json_string_get(ast_json_object_get(obj->blob, "variable"));
737         const char *value =
738                 ast_json_string_get(ast_json_object_get(obj->blob, "value"));
739
740         if (obj->snapshot) {
741                 channel_event_string =
742                         ast_manager_build_channel_state_string(obj->snapshot);
743         } else {
744                 channel_event_string = ast_str_create(35);
745                 ast_str_set(&channel_event_string, 0,
746                             "Channel: none\r\n"
747                             "Uniqueid: none\r\n");
748         }
749
750         if (!channel_event_string) {
751                 return NULL;
752         }
753
754         return ast_manager_event_blob_create(EVENT_FLAG_DIALPLAN, "VarSet",
755                 "%s"
756                 "Variable: %s\r\n"
757                 "Value: %s\r\n",
758                 ast_str_buffer(channel_event_string), variable, value);
759 }
760
761 static struct ast_manager_event_blob *agent_login_to_ami(struct stasis_message *msg)
762 {
763         RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
764         struct ast_channel_blob *obj = stasis_message_data(msg);
765         const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
766
767         channel_string = ast_manager_build_channel_state_string(obj->snapshot);
768         if (!channel_string) {
769                 return NULL;
770         }
771
772         return ast_manager_event_blob_create(EVENT_FLAG_AGENT, "AgentLogin",
773                 "%s"
774                 "Agent: %s\r\n",
775                 ast_str_buffer(channel_string), agent);
776 }
777
778 static struct ast_manager_event_blob *agent_logoff_to_ami(struct stasis_message *msg)
779 {
780         RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
781         struct ast_channel_blob *obj = stasis_message_data(msg);
782         const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
783         long logintime = ast_json_integer_get(ast_json_object_get(obj->blob, "logintime"));
784
785         channel_string = ast_manager_build_channel_state_string(obj->snapshot);
786         if (!channel_string) {
787                 return NULL;
788         }
789
790         return ast_manager_event_blob_create(EVENT_FLAG_AGENT, "AgentLogoff",
791                 "%s"
792                 "Agent: %s\r\n"
793                 "Logintime: %ld\r\n",
794                 ast_str_buffer(channel_string), agent, logintime);
795 }
796
797 void ast_publish_channel_state(struct ast_channel *chan)
798 {
799         RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
800         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
801
802         if (!ast_channel_snapshot_type()) {
803                 return;
804         }
805
806         ast_assert(chan != NULL);
807         if (!chan) {
808                 return;
809         }
810
811         snapshot = ast_channel_snapshot_create(chan);
812         if (!snapshot) {
813                 return;
814         }
815
816         message = stasis_message_create(ast_channel_snapshot_type(), snapshot);
817         if (!message) {
818                 return;
819         }
820
821         ast_assert(ast_channel_topic(chan) != NULL);
822         stasis_publish(ast_channel_topic(chan), message);
823 }
824
825 struct ast_json *ast_channel_snapshot_to_json(
826         const struct ast_channel_snapshot *snapshot,
827         const struct stasis_message_sanitizer *sanitize)
828 {
829         RAII_VAR(struct ast_json *, json_chan, NULL, ast_json_unref);
830
831         if (snapshot == NULL
832                 || (sanitize && sanitize->channel_snapshot
833                 && sanitize->channel_snapshot(snapshot))) {
834                 return NULL;
835         }
836
837         json_chan = ast_json_pack(
838                 /* Broken up into groups of three for readability */
839                 "{ s: s, s: s, s: s,"
840                 "  s: o, s: o, s: s,"
841                 "  s: o, s: o }",
842                 /* First line */
843                 "id", snapshot->uniqueid,
844                 "name", snapshot->name,
845                 "state", ast_state2str(snapshot->state),
846                 /* Second line */
847                 "caller", ast_json_name_number(
848                         snapshot->caller_name, snapshot->caller_number),
849                 "connected", ast_json_name_number(
850                         snapshot->connected_name, snapshot->connected_number),
851                 "accountcode", snapshot->accountcode,
852                 /* Third line */
853                 "dialplan", ast_json_dialplan_cep(
854                         snapshot->context, snapshot->exten, snapshot->priority),
855                 "creationtime", ast_json_timeval(snapshot->creationtime, NULL));
856
857         return ast_json_ref(json_chan);
858 }
859
860 int ast_channel_snapshot_cep_equal(
861         const struct ast_channel_snapshot *old_snapshot,
862         const struct ast_channel_snapshot *new_snapshot)
863 {
864         ast_assert(old_snapshot != NULL);
865         ast_assert(new_snapshot != NULL);
866
867         /* We actually get some snapshots with CEP set, but before the
868          * application is set. Since empty application is invalid, we treat
869          * setting the application from nothing as a CEP change.
870          */
871         if (ast_strlen_zero(old_snapshot->appl) &&
872             !ast_strlen_zero(new_snapshot->appl)) {
873                 return 0;
874         }
875
876         return old_snapshot->priority == new_snapshot->priority &&
877                 strcmp(old_snapshot->context, new_snapshot->context) == 0 &&
878                 strcmp(old_snapshot->exten, new_snapshot->exten) == 0;
879 }
880
881 int ast_channel_snapshot_caller_id_equal(
882         const struct ast_channel_snapshot *old_snapshot,
883         const struct ast_channel_snapshot *new_snapshot)
884 {
885         ast_assert(old_snapshot != NULL);
886         ast_assert(new_snapshot != NULL);
887         return strcmp(old_snapshot->caller_number, new_snapshot->caller_number) == 0 &&
888                 strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0;
889 }
890
891 static struct ast_json *channel_blob_to_json(
892         struct stasis_message *message,
893         const char *type,
894         const struct stasis_message_sanitizer *sanitize)
895 {
896         RAII_VAR(struct ast_json *, out, NULL, ast_json_unref);
897         struct ast_channel_blob *channel_blob = stasis_message_data(message);
898         struct ast_json *blob = channel_blob->blob;
899         struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
900         const struct timeval *tv = stasis_message_timestamp(message);
901         int res = 0;
902
903         if (blob == NULL || ast_json_is_null(blob)) {
904                 out = ast_json_object_create();
905         } else {
906                 /* blobs are immutable, so shallow copies are fine */
907                 out = ast_json_copy(blob);
908         }
909
910         if (!out) {
911                 return NULL;
912         }
913
914         res |= ast_json_object_set(out, "type", ast_json_string_create(type));
915         res |= ast_json_object_set(out, "timestamp",
916                 ast_json_timeval(*tv, NULL));
917
918         /* For global channel messages, the snapshot is optional */
919         if (snapshot) {
920                 struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, sanitize);
921
922                 if (!json_channel) {
923                         return NULL;
924                 }
925
926                 res |= ast_json_object_set(out, "channel", json_channel);
927         }
928
929         if (res != 0) {
930                 return NULL;
931         }
932
933         return ast_json_ref(out);
934 }
935
936 static struct ast_json *dtmf_end_to_json(
937         struct stasis_message *message,
938         const struct stasis_message_sanitizer *sanitize)
939 {
940         struct ast_channel_blob *channel_blob = stasis_message_data(message);
941         struct ast_json *blob = channel_blob->blob;
942         struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
943         const char *direction =
944                 ast_json_string_get(ast_json_object_get(blob, "direction"));
945         const struct timeval *tv = stasis_message_timestamp(message);
946         struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, sanitize);
947
948         /* Only present received DTMF end events as JSON */
949         if (strcasecmp("Received", direction) != 0) {
950                 return NULL;
951         }
952
953         if (!json_channel) {
954                 return NULL;
955         }
956
957         return ast_json_pack("{s: s, s: o, s: O, s: O, s: o}",
958                 "type", "ChannelDtmfReceived",
959                 "timestamp", ast_json_timeval(*tv, NULL),
960                 "digit", ast_json_object_get(blob, "digit"),
961                 "duration_ms", ast_json_object_get(blob, "duration_ms"),
962                 "channel", json_channel);
963 }
964
965 static struct ast_json *varset_to_json(
966         struct stasis_message *message,
967         const struct stasis_message_sanitizer *sanitize)
968 {
969         return channel_blob_to_json(message, "ChannelVarset", sanitize);
970 }
971
972 static struct ast_json *hangup_request_to_json(
973         struct stasis_message *message,
974         const struct stasis_message_sanitizer *sanitize)
975 {
976         return channel_blob_to_json(message, "ChannelHangupRequest", sanitize);
977 }
978
979 static struct ast_json *dial_to_json(
980         struct stasis_message *message,
981         const struct stasis_message_sanitizer *sanitize)
982 {
983         struct ast_multi_channel_blob *payload = stasis_message_data(message);
984         struct ast_json *blob = ast_multi_channel_blob_get_json(payload);
985         struct ast_json *caller_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "caller"), sanitize);
986         struct ast_json *peer_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "peer"), sanitize);
987         struct ast_json *forwarded_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "forwarded"), sanitize);
988         struct ast_json *json;
989         const struct timeval *tv = stasis_message_timestamp(message);
990         int res = 0;
991
992         json = ast_json_pack("{s: s, s: o, s: O, s: O, s: O}",
993                 "type", "Dial",
994                 "timestamp", ast_json_timeval(*tv, NULL),
995                 "dialstatus", ast_json_object_get(blob, "dialstatus"),
996                 "forward", ast_json_object_get(blob, "forward"),
997                 "dialstring", ast_json_object_get(blob, "dialstring"));
998         if (!json) {
999                 ast_json_unref(caller_json);
1000                 ast_json_unref(peer_json);
1001                 ast_json_unref(forwarded_json);
1002                 return NULL;
1003         }
1004
1005         if (caller_json) {
1006                 res |= ast_json_object_set(json, "caller", caller_json);
1007         }
1008         if (peer_json) {
1009                 res |= ast_json_object_set(json, "peer", peer_json);
1010         }
1011         if (forwarded_json) {
1012                 res |= ast_json_object_set(json, "forwarded", forwarded_json);
1013         }
1014
1015         if (res) {
1016                 ast_json_unref(json);
1017                 return NULL;
1018         }
1019
1020         return json;
1021 }
1022
1023 static struct ast_manager_event_blob *talking_start_to_ami(struct stasis_message *msg)
1024 {
1025         struct ast_str *channel_string;
1026         struct ast_channel_blob *obj = stasis_message_data(msg);
1027         struct ast_manager_event_blob *blob;
1028
1029         channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1030         if (!channel_string) {
1031                 return NULL;
1032         }
1033
1034         blob = ast_manager_event_blob_create(EVENT_FLAG_CALL, "ChannelTalkingStart",
1035                                              "%s", ast_str_buffer(channel_string));
1036         ast_free(channel_string);
1037
1038         return blob;
1039 }
1040
1041 static struct ast_json *talking_start_to_json(struct stasis_message *message,
1042         const struct stasis_message_sanitizer *sanitize)
1043 {
1044         return channel_blob_to_json(message, "ChannelTalkingStarted", sanitize);
1045 }
1046
1047 static struct ast_manager_event_blob *talking_stop_to_ami(struct stasis_message *msg)
1048 {
1049         struct ast_str *channel_string;
1050         struct ast_channel_blob *obj = stasis_message_data(msg);
1051         int duration = ast_json_integer_get(ast_json_object_get(obj->blob, "duration"));
1052         struct ast_manager_event_blob *blob;
1053
1054         channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1055         if (!channel_string) {
1056                 return NULL;
1057         }
1058
1059         blob = ast_manager_event_blob_create(EVENT_FLAG_CALL, "ChannelTalkingStop",
1060                                              "%s"
1061                                              "Duration: %d\r\n",
1062                                              ast_str_buffer(channel_string),
1063                                              duration);
1064         ast_free(channel_string);
1065
1066         return blob;
1067 }
1068
1069 static struct ast_json *talking_stop_to_json(struct stasis_message *message,
1070         const struct stasis_message_sanitizer *sanitize)
1071 {
1072         return channel_blob_to_json(message, "ChannelTalkingFinished", sanitize);
1073 }
1074
1075 /*!
1076  * @{ \brief Define channel message types.
1077  */
1078 STASIS_MESSAGE_TYPE_DEFN(ast_channel_snapshot_type);
1079 STASIS_MESSAGE_TYPE_DEFN(ast_channel_dial_type,
1080         .to_json = dial_to_json,
1081         );
1082 STASIS_MESSAGE_TYPE_DEFN(ast_channel_varset_type,
1083         .to_ami = varset_to_ami,
1084         .to_json = varset_to_json,
1085         );
1086 STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_request_type,
1087         .to_json = hangup_request_to_json,
1088         );
1089 STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_begin_type);
1090 STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_end_type,
1091         .to_json = dtmf_end_to_json,
1092         );
1093 STASIS_MESSAGE_TYPE_DEFN(ast_channel_hold_type);
1094 STASIS_MESSAGE_TYPE_DEFN(ast_channel_unhold_type);
1095 STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_start_type);
1096 STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_stop_type);
1097 STASIS_MESSAGE_TYPE_DEFN(ast_channel_fax_type);
1098 STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_handler_type);
1099 STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_start_type);
1100 STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_stop_type);
1101 STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_start_type);
1102 STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_stop_type);
1103 STASIS_MESSAGE_TYPE_DEFN(ast_channel_agent_login_type,
1104         .to_ami = agent_login_to_ami,
1105         );
1106 STASIS_MESSAGE_TYPE_DEFN(ast_channel_agent_logoff_type,
1107         .to_ami = agent_logoff_to_ami,
1108         );
1109 STASIS_MESSAGE_TYPE_DEFN(ast_channel_talking_start,
1110         .to_ami = talking_start_to_ami,
1111         .to_json = talking_start_to_json,
1112         );
1113 STASIS_MESSAGE_TYPE_DEFN(ast_channel_talking_stop,
1114         .to_ami = talking_stop_to_ami,
1115         .to_json = talking_stop_to_json,
1116         );
1117
1118 /*! @} */
1119
1120 static void stasis_channels_cleanup(void)
1121 {
1122         stasis_caching_unsubscribe_and_join(channel_by_name_topic);
1123         channel_by_name_topic = NULL;
1124         ao2_cleanup(channel_cache_by_name);
1125         channel_cache_by_name = NULL;
1126         ao2_cleanup(channel_cache_all);
1127         channel_cache_all = NULL;
1128
1129         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_snapshot_type);
1130         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dial_type);
1131         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_varset_type);
1132         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hangup_request_type);
1133         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dtmf_begin_type);
1134         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dtmf_end_type);
1135         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hold_type);
1136         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_unhold_type);
1137         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_chanspy_start_type);
1138         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_chanspy_stop_type);
1139         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_fax_type);
1140         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hangup_handler_type);
1141         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_moh_start_type);
1142         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_moh_stop_type);
1143         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_monitor_start_type);
1144         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_monitor_stop_type);
1145         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_agent_login_type);
1146         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_agent_logoff_type);
1147         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_talking_start);
1148         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_talking_stop);
1149 }
1150
1151 int ast_stasis_channels_init(void)
1152 {
1153         int res = 0;
1154
1155         ast_register_cleanup(stasis_channels_cleanup);
1156
1157         channel_cache_all = stasis_cp_all_create("ast_channel_topic_all",
1158                 channel_snapshot_get_id);
1159         if (!channel_cache_all) {
1160                 return -1;
1161         }
1162         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_agent_login_type);
1163         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_agent_logoff_type);
1164
1165         channel_cache_by_name = stasis_cache_create(channel_snapshot_get_name);
1166         if (!channel_cache_by_name) {
1167                 return -1;
1168         }
1169
1170         /* This should be initialized before the caching topic */
1171         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_snapshot_type);
1172
1173         channel_by_name_topic = stasis_caching_topic_create(
1174                 stasis_cp_all_topic(channel_cache_all),
1175                 channel_cache_by_name);
1176         if (!channel_by_name_topic) {
1177                 return -1;
1178         }
1179
1180         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_dial_type);
1181         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_varset_type);
1182         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_hangup_request_type);
1183         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_dtmf_begin_type);
1184         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_dtmf_end_type);
1185         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_hold_type);
1186         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_unhold_type);
1187         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_chanspy_start_type);
1188         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_chanspy_stop_type);
1189         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_fax_type);
1190         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_hangup_handler_type);
1191         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_moh_start_type);
1192         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_moh_stop_type);
1193         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_start_type);
1194         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_stop_type);
1195         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_talking_start);
1196         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_talking_stop);
1197
1198         return res;
1199 }
1200