Move NewCallerid, HangupRequest and SoftHangupRequest to Stasis
[asterisk/asterisk.git] / main / manager_channels.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * David M. Lee, II <dlee@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 The Asterisk Management Interface - AMI (channel event handling)
22  *
23  * \author David M. Lee, II <dlee@digium.com>
24  *
25  * AMI generated many per-channel and global-channel events by converting Stasis
26  * messages to AMI events. It makes sense to simply put them into a single file.
27  */
28
29 #include "asterisk.h"
30
31 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
32
33 #include "asterisk/callerid.h"
34 #include "asterisk/channel.h"
35 #include "asterisk/manager.h"
36 #include "asterisk/stasis_message_router.h"
37 #include "asterisk/pbx.h"
38
39 static struct stasis_message_router *channel_state_router;
40
41 /*** DOCUMENTATION
42         <managerEvent language="en_US" name="Newchannel">
43                 <managerEventInstance class="EVENT_FLAG_CALL">
44                         <synopsis>Raised when a new channel is created.</synopsis>
45                         <syntax>
46                                 <parameter name="Channel">
47                                 </parameter>
48                                 <parameter name="ChannelState">
49                                         <para>A numeric code for the channel's current state, related to ChannelStateDesc</para>
50                                 </parameter>
51                                 <parameter name="ChannelStateDesc">
52                                         <enumlist>
53                                                 <enum name="Down"/>
54                                                 <enum name="Rsrvd"/>
55                                                 <enum name="OffHook"/>
56                                                 <enum name="Dialing"/>
57                                                 <enum name="Ring"/>
58                                                 <enum name="Ringing"/>
59                                                 <enum name="Up"/>
60                                                 <enum name="Busy"/>
61                                                 <enum name="Dialing Offhook"/>
62                                                 <enum name="Pre-ring"/>
63                                                 <enum name="Unknown"/>
64                                         </enumlist>
65                                 </parameter>
66                                 <parameter name="CallerIDNum">
67                                 </parameter>
68                                 <parameter name="CallerIDName">
69                                 </parameter>
70                                 <parameter name="ConnectedLineNum">
71                                 </parameter>
72                                 <parameter name="ConnectedLineName">
73                                 </parameter>
74                                 <parameter name="AccountCode">
75                                 </parameter>
76                                 <parameter name="Context">
77                                 </parameter>
78                                 <parameter name="Exten">
79                                 </parameter>
80                                 <parameter name="Priority">
81                                 </parameter>
82                                 <parameter name="Uniqueid">
83                                 </parameter>
84                         </syntax>
85                 </managerEventInstance>
86         </managerEvent>
87         <managerEvent language="en_US" name="Newstate">
88                 <managerEventInstance class="EVENT_FLAG_CALL">
89                         <synopsis>Raised when a channel's state changes.</synopsis>
90                         <syntax>
91                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
92                         </syntax>
93                 </managerEventInstance>
94         </managerEvent>
95         <managerEvent language="en_US" name="Hangup">
96                 <managerEventInstance class="EVENT_FLAG_CALL">
97                         <synopsis>Raised when a channel is hung up.</synopsis>
98                         <syntax>
99                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
100                                 <parameter name="Cause">
101                                         <para>A numeric cause code for why the channel was hung up.</para>
102                                 </parameter>
103                                 <parameter name="Cause-txt">
104                                         <para>A description of why the channel was hung up.</para>
105                                 </parameter>
106                         </syntax>
107                 </managerEventInstance>
108         </managerEvent>
109         <managerEvent language="en_US" name="HangupRequest">
110                 <managerEventInstance class="EVENT_FLAG_CALL">
111                         <synopsis>Raised when a hangup is requested.</synopsis>
112                         <syntax>
113                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
114                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
115                         </syntax>
116                 </managerEventInstance>
117         </managerEvent>
118         <managerEvent language="en_US" name="SoftHangupRequest">
119                 <managerEventInstance class="EVENT_FLAG_CALL">
120                         <synopsis>Raised when a soft hangup is requested with a specific cause code.</synopsis>
121                         <syntax>
122                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
123                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
124                         </syntax>
125                 </managerEventInstance>
126         </managerEvent>
127         <managerEvent language="en_US" name="NewExten">
128                 <managerEventInstance class="EVENT_FLAG_DIALPLAN">
129                         <synopsis>Raised when a channel enters a new context, extension, priority.</synopsis>
130                         <syntax>
131                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
132                                 <parameter name="Extension">
133                                         <para>Deprecated in 12, but kept for
134                                         backward compatability. Please use
135                                         'Exten' instead.</para>
136                                 </parameter>
137                                 <parameter name="Application">
138                                         <para>The application about to be executed.</para>
139                                 </parameter>
140                                 <parameter name="AppData">
141                                         <para>The data to be passed to the application.</para>
142                                 </parameter>
143                         </syntax>
144                 </managerEventInstance>
145         </managerEvent>
146         <managerEvent language="en_US" name="NewCallerid">
147                 <managerEventInstance class="EVENT_FLAG_CALL">
148                         <synopsis>Raised when a channel receives new Caller ID information.</synopsis>
149                         <syntax>
150                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
151                                 <parameter name="CID-CallingPres">
152                                         <para>A description of the Caller ID presentation.</para>
153                                 </parameter>
154                         </syntax>
155                 </managerEventInstance>
156         </managerEvent>
157  ***/
158
159 /*!
160  * \brief Generate the AMI message body from a channel snapshot
161  * \internal
162  *
163  * \param snapshot the channel snapshot for which to generate an AMI message
164  *                 body
165  *
166  * \retval NULL on error
167  * \retval ast_str* on success (must be ast_freed by caller)
168  */
169 static struct ast_str *manager_build_channel_state_string(
170         const struct ast_channel_snapshot *snapshot)
171 {
172         struct ast_str *out = ast_str_create(1024);
173         int res = 0;
174         if (!out) {
175                 return NULL;
176         }
177         res = ast_str_set(&out, 0,
178                 "Channel: %s\r\n"
179                 "ChannelState: %d\r\n"
180                 "ChannelStateDesc: %s\r\n"
181                 "CallerIDNum: %s\r\n"
182                 "CallerIDName: %s\r\n"
183                 "ConnectedLineNum: %s\r\n"
184                 "ConnectedLineName: %s\r\n"
185                 "AccountCode: %s\r\n"
186                 "Context: %s\r\n"
187                 "Exten: %s\r\n"
188                 "Priority: %d\r\n"
189                 "Uniqueid: %s\r\n",
190                 snapshot->name,
191                 snapshot->state,
192                 ast_state2str(snapshot->state),
193                 snapshot->caller_number,
194                 snapshot->caller_name,
195                 snapshot->connected_number,
196                 snapshot->connected_name,
197                 snapshot->accountcode,
198                 snapshot->context,
199                 snapshot->exten,
200                 snapshot->priority,
201                 snapshot->uniqueid);
202
203         if (!res) {
204                 return NULL;
205         }
206
207         if (snapshot->manager_vars) {
208                 struct ast_var_t *var;
209                 AST_LIST_TRAVERSE(snapshot->manager_vars, var, entries) {
210                         ast_str_append(&out, 0, "ChanVariable(%s): %s=%s\r\n",
211                                        snapshot->name,
212                                        var->name, var->value);
213                 }
214         }
215
216         return out;
217 }
218
219 /*! \brief Struct containing info for an AMI channel event to send out. */
220 struct snapshot_manager_event {
221         /*! event_flags manager_event() flags parameter. */
222         int event_flags;
223         /*!  manager_event manager_event() category. */
224         const char *manager_event;
225         AST_DECLARE_STRING_FIELDS(
226                 /* extra fields to include in the event. */
227                 AST_STRING_FIELD(extra_fields);
228                 );
229 };
230
231 static void snapshot_manager_event_dtor(void *obj)
232 {
233         struct snapshot_manager_event *ev = obj;
234         ast_string_field_free_memory(ev);
235 }
236
237 /*!
238  * \brief Construct a \ref snapshot_manager_event.
239  * \param event_flags manager_event() flags parameter.
240  * \param manager_event manager_event() category.
241  * \param extra_fields_fmt Format string for extra fields to include.
242  *                         Or NO_EXTRA_FIELDS for no extra fields.
243  * \return New \ref snapshot_manager_event object.
244  * \return \c NULL on error.
245  */
246 static struct snapshot_manager_event *
247 __attribute__((format(printf, 3, 4)))
248 snapshot_manager_event_create(
249         int event_flags,
250         const char *manager_event,
251         const char *extra_fields_fmt,
252         ...)
253 {
254         RAII_VAR(struct snapshot_manager_event *, ev, NULL, ao2_cleanup);
255         va_list argp;
256
257         ast_assert(extra_fields_fmt != NULL);
258         ast_assert(manager_event != NULL);
259
260         ev = ao2_alloc(sizeof(*ev), snapshot_manager_event_dtor);
261         if (!ev) {
262                 return NULL;
263         }
264
265         if (ast_string_field_init(ev, 20)) {
266                 return NULL;
267         }
268
269         ev->manager_event = manager_event;
270         ev->event_flags = event_flags;
271
272         va_start(argp, extra_fields_fmt);
273         ast_string_field_ptr_build_va(ev, &ev->extra_fields, extra_fields_fmt,
274                                       argp);
275         va_end(argp);
276
277         ao2_ref(ev, +1);
278         return ev;
279 }
280
281 /*! GCC warns about blank or NULL format strings. So, shenanigans! */
282 #define NO_EXTRA_FIELDS "%s", ""
283
284 /*! \brief Typedef for callbacks that get called on channel snapshot updates */
285 typedef struct snapshot_manager_event *(*snapshot_monitor)(
286         struct ast_channel_snapshot *old_snapshot,
287         struct ast_channel_snapshot *new_snapshot);
288
289 /*! \brief Handle channel state changes */
290 static struct snapshot_manager_event *channel_state_change(
291         struct ast_channel_snapshot *old_snapshot,
292         struct ast_channel_snapshot *new_snapshot)
293 {
294         int is_hungup, was_hungup;
295
296         if (!new_snapshot) {
297                 /* Ignore cache clearing events; we'll see the hangup first */
298                 return NULL;
299         }
300
301         /* The Newchannel, Newstate and Hangup events are closely related, in
302          * in that they are mutually exclusive, basically different flavors
303          * of a new channel state event.
304          */
305
306         if (!old_snapshot) {
307                 return snapshot_manager_event_create(
308                         EVENT_FLAG_CALL, "Newchannel", NO_EXTRA_FIELDS);
309         }
310
311         was_hungup = ast_test_flag(&old_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
312         is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
313
314         if (!was_hungup && is_hungup) {
315                 return snapshot_manager_event_create(
316                         EVENT_FLAG_CALL, "Hangup",
317                         "Cause: %d\r\n"
318                         "Cause-txt: %s\r\n",
319                         new_snapshot->hangupcause,
320                         ast_cause2str(new_snapshot->hangupcause));
321         }
322
323         if (old_snapshot->state != new_snapshot->state) {
324                 return snapshot_manager_event_create(
325                         EVENT_FLAG_CALL, "Newstate", NO_EXTRA_FIELDS);
326         }
327
328         /* No event */
329         return NULL;
330 }
331
332 /*!
333  * \brief Compares the context, exten and priority of two snapshots.
334  * \param old_snapshot Old snapshot
335  * \param new_snapshot New snapshot
336  * \return True (non-zero) if context, exten or priority are identical.
337  * \return False (zero) if context, exten and priority changed.
338  */
339 static inline int cep_equal(
340         const struct ast_channel_snapshot *old_snapshot,
341         const struct ast_channel_snapshot *new_snapshot)
342 {
343         ast_assert(old_snapshot != NULL);
344         ast_assert(new_snapshot != NULL);
345
346         /* We actually get some snapshots with CEP set, but before the
347          * application is set. Since empty application is invalid, we treat
348          * setting the application from nothing as a CEP change.
349          */
350         if (ast_strlen_zero(old_snapshot->appl) &&
351             !ast_strlen_zero(new_snapshot->appl)) {
352                 return 0;
353         }
354
355         return old_snapshot->priority == new_snapshot->priority &&
356                 strcmp(old_snapshot->context, new_snapshot->context) == 0 &&
357                 strcmp(old_snapshot->exten, new_snapshot->exten) == 0;
358 }
359
360 static struct snapshot_manager_event *channel_newexten(
361         struct ast_channel_snapshot *old_snapshot,
362         struct ast_channel_snapshot *new_snapshot)
363 {
364         /* No Newexten event on cache clear */
365         if (!new_snapshot) {
366                 return NULL;
367         }
368
369         /* Empty application is not valid for a Newexten event */
370         if (ast_strlen_zero(new_snapshot->appl)) {
371                 return NULL;
372         }
373
374         if (old_snapshot && cep_equal(old_snapshot, new_snapshot)) {
375                 return NULL;
376         }
377
378         /* DEPRECATED: Extension field deprecated in 12; remove in 14 */
379         return snapshot_manager_event_create(
380                 EVENT_FLAG_CALL, "Newexten",
381                 "Extension: %s\r\n"
382                 "Application: %s\r\n"
383                 "AppData: %s\r\n",
384                 new_snapshot->exten,
385                 new_snapshot->appl,
386                 new_snapshot->data);
387 }
388
389 /*!
390  * \brief Compares the callerid info of two snapshots.
391  * \param old_snapshot Old snapshot
392  * \param new_snapshot New snapshot
393  * \return True (non-zero) if callerid are identical.
394  * \return False (zero) if callerid changed.
395  */
396 static inline int caller_id_equal(
397         const struct ast_channel_snapshot *old_snapshot,
398         const struct ast_channel_snapshot *new_snapshot)
399 {
400         ast_assert(old_snapshot != NULL);
401         ast_assert(new_snapshot != NULL);
402         return strcmp(old_snapshot->caller_number, new_snapshot->caller_number) == 0 &&
403                 strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0;
404 }
405
406 static struct snapshot_manager_event *channel_new_callerid(
407         struct ast_channel_snapshot *old_snapshot,
408         struct ast_channel_snapshot *new_snapshot)
409 {
410         /* No NewCallerid event on cache clear or first event */
411         if (!old_snapshot || !new_snapshot) {
412                 return NULL;
413         }
414
415         if (caller_id_equal(old_snapshot, new_snapshot)) {
416                 return NULL;
417         }
418
419         return snapshot_manager_event_create(
420                 EVENT_FLAG_CALL, "NewCallerid",
421                 "CID-CallingPres: %d (%s)\r\n",
422                 new_snapshot->caller_pres,
423                 ast_describe_caller_presentation(new_snapshot->caller_pres));
424 }
425
426 snapshot_monitor monitors[] = {
427         channel_state_change,
428         channel_newexten,
429         channel_new_callerid
430 };
431
432 static void channel_snapshot_update(void *data, struct stasis_subscription *sub,
433                                     struct stasis_topic *topic,
434                                     struct stasis_message *message)
435 {
436         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
437         struct stasis_cache_update *update;
438         struct ast_channel_snapshot *old_snapshot;
439         struct ast_channel_snapshot *new_snapshot;
440         size_t i;
441
442         update = stasis_message_data(message);
443
444         if (ast_channel_snapshot() != update->type) {
445                 return;
446         }
447
448         old_snapshot = stasis_message_data(update->old_snapshot);
449         new_snapshot = stasis_message_data(update->new_snapshot);
450
451         for (i = 0; i < ARRAY_LEN(monitors); ++i) {
452                 RAII_VAR(struct snapshot_manager_event *, ev, NULL, ao2_cleanup);
453                 ev = monitors[i](old_snapshot, new_snapshot);
454
455                 if (!ev) {
456                         continue;
457                 }
458
459                 /* If we haven't already, build the channel event string */
460                 if (!channel_event_string) {
461                         channel_event_string =
462                                 manager_build_channel_state_string(new_snapshot);
463                         if (!channel_event_string) {
464                                 return;
465                         }
466                 }
467
468                 manager_event(ev->event_flags, ev->manager_event, "%s%s",
469                         ast_str_buffer(channel_event_string),
470                         ev->extra_fields);
471         }
472 }
473
474 static void channel_varset(struct ast_channel_blob *obj)
475 {
476         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
477         const char *variable = ast_json_string_get(ast_json_object_get(obj->blob, "variable"));
478         const char *value = ast_json_string_get(ast_json_object_get(obj->blob, "value"));
479
480         if (obj->snapshot) {
481                 channel_event_string = manager_build_channel_state_string(obj->snapshot);
482         } else {
483                 channel_event_string = ast_str_create(35);
484                 ast_str_set(&channel_event_string, 0,
485                             "Channel: none\r\n"
486                             "Uniqueid: none\r\n");
487         }
488
489         if (!channel_event_string) {
490                 return;
491         }
492
493         /*** DOCUMENTATION
494                 <managerEventInstance>
495                         <synopsis>Raised when a variable is set to a particular value.</synopsis>
496                         <syntax>
497                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
498                                 <parameter name="Variable">
499                                         <para>The variable being set.</para>
500                                 </parameter>
501                                 <parameter name="Value">
502                                         <para>The new value of the variable.</para>
503                                 </parameter>
504                         </syntax>
505                 </managerEventInstance>
506         ***/
507         manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
508                       "%s"
509                       "Variable: %s\r\n"
510                       "Value: %s\r\n",
511                       ast_str_buffer(channel_event_string),
512                       variable, value);
513 }
514
515 static void channel_userevent(struct ast_channel_blob *obj)
516 {
517         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
518         const char *eventname;
519         const char *body;
520
521         eventname = ast_json_string_get(ast_json_object_get(obj->blob, "eventname"));
522         body = ast_json_string_get(ast_json_object_get(obj->blob, "body"));
523         channel_event_string = manager_build_channel_state_string(obj->snapshot);
524
525         if (!channel_event_string) {
526                 return;
527         }
528
529         /*** DOCUMENTATION
530                 <managerEventInstance>
531                         <synopsis>A user defined event raised from the dialplan.</synopsis>
532                         <syntax>
533                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
534                                 <parameter name="UserEvent">
535                                         <para>The event name, as specified in the dialplan.</para>
536                                 </parameter>
537                         </syntax>
538                         <see-also>
539                                 <ref type="application">UserEvent</ref>
540                         </see-also>
541                 </managerEventInstance>
542         ***/
543         manager_event(EVENT_FLAG_USER, "UserEvent",
544                       "%s"
545                       "UserEvent: %s\r\n"
546                       "%s",
547                       ast_str_buffer(channel_event_string), eventname, body);
548 }
549
550 static void channel_hangup_request(struct ast_channel_blob *obj)
551 {
552         RAII_VAR(struct ast_str *, extra, NULL, ast_free);
553         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
554         struct ast_json *cause;
555         int is_soft;
556         char *manager_event = "HangupRequest";
557
558         extra = ast_str_create(20);
559         if (!extra) {
560                 return;
561         }
562
563         channel_event_string = manager_build_channel_state_string(obj->snapshot);
564
565         if (!channel_event_string) {
566                 return;
567         }
568
569         cause = ast_json_object_get(obj->blob, "cause");
570         if (cause) {
571                 ast_str_append(&extra, 0,
572                                "Cause: %jd\r\n",
573                                ast_json_integer_get(cause));
574         }
575
576         is_soft = ast_json_is_true(ast_json_object_get(obj->blob, "soft"));
577         if (is_soft) {
578                 manager_event = "SoftHangupRequest";
579         }
580
581         manager_event(EVENT_FLAG_CALL, manager_event,
582                       "%s%s",
583                       ast_str_buffer(channel_event_string),
584                       ast_str_buffer(extra));
585 }
586
587 /*!
588  * \brief Callback processing messages on the channel topic.
589  */
590 static void channel_blob_cb(void *data, struct stasis_subscription *sub,
591                             struct stasis_topic *topic,
592                             struct stasis_message *message)
593 {
594         struct ast_channel_blob *obj = stasis_message_data(message);
595
596         if (strcmp("varset", ast_channel_blob_type(obj)) == 0) {
597                 channel_varset(obj);
598         } else if (strcmp("userevent", ast_channel_blob_type(obj)) == 0) {
599                 channel_userevent(obj);
600         } else if (strcmp("hangup_request", ast_channel_blob_type(obj)) == 0) {
601                 channel_hangup_request(obj);
602         }
603 }
604
605 static void manager_channels_shutdown(void)
606 {
607         stasis_message_router_unsubscribe(channel_state_router);
608         channel_state_router = NULL;
609 }
610
611 int manager_channels_init(void)
612 {
613         int ret = 0;
614
615         if (channel_state_router) {
616                 /* Already initialized */
617                 return 0;
618         }
619
620         ast_register_atexit(manager_channels_shutdown);
621
622         channel_state_router = stasis_message_router_create(
623                 stasis_caching_get_topic(ast_channel_topic_all_cached()));
624
625         if (!channel_state_router) {
626                 return -1;
627         }
628
629         ret |= stasis_message_router_add(channel_state_router,
630                                          stasis_cache_update(),
631                                          channel_snapshot_update,
632                                          NULL);
633
634         ret |= stasis_message_router_add(channel_state_router,
635                                          ast_channel_blob(),
636                                          channel_blob_cb,
637                                          NULL);
638
639         /* If somehow we failed to add any routes, just shut down the whole
640          * things and fail it.
641          */
642         if (ret) {
643                 manager_channels_shutdown();
644                 return -1;
645         }
646
647         return 0;
648 }