app_dial: Allow macro/gosub pre-bridge execution to occur on priorities
[asterisk/asterisk.git] / main / stasis_system.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Jason Parker <jparker@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 System events
22  *
23  * \author Jason Parker <jparker@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/astobj2.h"
35 #include "asterisk/stasis.h"
36 #include "asterisk/stasis_system.h"
37
38 /*** DOCUMENTATION
39         <managerEvent language="en_US" name="Registry">
40                 <managerEventInstance class="EVENT_FLAG_SYSTEM">
41                         <synopsis>Raised when an outbound registration completes.</synopsis>
42                         <syntax>
43                                 <parameter name="ChannelType">
44                                         <para>The type of channel that was registered (or not).</para>
45                                 </parameter>
46                                 <parameter name="Username">
47                                         <para>The username portion of the registration.</para>
48                                 </parameter>
49                                 <parameter name="Domain">
50                                         <para>The address portion of the registration.</para>
51                                 </parameter>
52                                 <parameter name="Status">
53                                         <para>The status of the registration request.</para>
54                                         <enumlist>
55                                                 <enum name="Registered"/>
56                                                 <enum name="Unregistered"/>
57                                                 <enum name="Rejected"/>
58                                                 <enum name="Failed"/>
59                                         </enumlist>
60                                 </parameter>
61                                 <parameter name="Cause">
62                                         <para>What caused the rejection of the request, if available.</para>
63                                 </parameter>
64                         </syntax>
65                 </managerEventInstance>
66         </managerEvent>
67  ***/
68
69 /*! \brief The \ref stasis topic for system level changes */
70 static struct stasis_topic *system_topic;
71
72 static struct ast_manager_event_blob *system_registry_to_ami(struct stasis_message *message);
73 static struct ast_manager_event_blob *cc_available_to_ami(struct stasis_message *message);
74 static struct ast_manager_event_blob *cc_offertimerstart_to_ami(struct stasis_message *message);
75 static struct ast_manager_event_blob *cc_requested_to_ami(struct stasis_message *message);
76 static struct ast_manager_event_blob *cc_requestacknowledged_to_ami(struct stasis_message *message);
77 static struct ast_manager_event_blob *cc_callerstopmonitoring_to_ami(struct stasis_message *message);
78 static struct ast_manager_event_blob *cc_callerstartmonitoring_to_ami(struct stasis_message *message);
79 static struct ast_manager_event_blob *cc_callerrecalling_to_ami(struct stasis_message *message);
80 static struct ast_manager_event_blob *cc_recallcomplete_to_ami(struct stasis_message *message);
81 static struct ast_manager_event_blob *cc_failure_to_ami(struct stasis_message *message);
82 static struct ast_manager_event_blob *cc_monitorfailed_to_ami(struct stasis_message *message);
83
84 STASIS_MESSAGE_TYPE_DEFN(ast_network_change_type);
85 STASIS_MESSAGE_TYPE_DEFN(ast_system_registry_type,
86         .to_ami = system_registry_to_ami,
87         );
88 STASIS_MESSAGE_TYPE_DEFN(ast_cc_available_type,
89         .to_ami = cc_available_to_ami,
90         );
91 STASIS_MESSAGE_TYPE_DEFN(ast_cc_offertimerstart_type,
92         .to_ami = cc_offertimerstart_to_ami,
93         );
94 STASIS_MESSAGE_TYPE_DEFN(ast_cc_requested_type,
95         .to_ami = cc_requested_to_ami,
96         );
97 STASIS_MESSAGE_TYPE_DEFN(ast_cc_requestacknowledged_type,
98         .to_ami = cc_requestacknowledged_to_ami,
99         );
100 STASIS_MESSAGE_TYPE_DEFN(ast_cc_callerstopmonitoring_type,
101         .to_ami = cc_callerstopmonitoring_to_ami,
102         );
103 STASIS_MESSAGE_TYPE_DEFN(ast_cc_callerstartmonitoring_type,
104         .to_ami = cc_callerstartmonitoring_to_ami,
105         );
106 STASIS_MESSAGE_TYPE_DEFN(ast_cc_callerrecalling_type,
107         .to_ami = cc_callerrecalling_to_ami,
108         );
109 STASIS_MESSAGE_TYPE_DEFN(ast_cc_recallcomplete_type,
110         .to_ami = cc_recallcomplete_to_ami,
111         );
112 STASIS_MESSAGE_TYPE_DEFN(ast_cc_failure_type,
113         .to_ami = cc_failure_to_ami,
114         );
115 STASIS_MESSAGE_TYPE_DEFN(ast_cc_monitorfailed_type,
116         .to_ami = cc_monitorfailed_to_ami,
117         );
118
119 void ast_system_publish_registry(const char *channeltype, const char *username, const char *domain, const char *status, const char *cause)
120 {
121         RAII_VAR(struct ast_json *, registry, NULL, ast_json_unref);
122         RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
123         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
124
125         registry = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s}",
126                 "type", "registry",
127                 "channeltype", channeltype,
128                 "username", username,
129                 "domain", domain,
130                 "status", status,
131                 "cause", S_OR(cause, ""));
132
133         if (!(payload = ast_json_payload_create(registry))) {
134                 return;
135         }
136
137         if (!(message = stasis_message_create(ast_system_registry_type(), payload))) {
138                 return;
139         }
140
141         stasis_publish(ast_system_topic(), message);
142 }
143
144 static struct ast_manager_event_blob *system_registry_to_ami(struct stasis_message *message)
145 {
146         struct ast_json_payload *payload = stasis_message_data(message);
147         const char *channeltype;
148         const char *username;
149         const char *domain;
150         const char *status;
151         const char *cause;
152         RAII_VAR(struct ast_str *, cause_string, ast_str_create(32), ast_free);
153
154         if (!cause_string) {
155                 return NULL;
156         }
157
158         channeltype = ast_json_string_get(ast_json_object_get(payload->json, "channeltype"));
159         username = ast_json_string_get(ast_json_object_get(payload->json, "username"));
160         domain = ast_json_string_get(ast_json_object_get(payload->json, "domain"));
161         status = ast_json_string_get(ast_json_object_get(payload->json, "status"));
162         cause = ast_json_string_get(ast_json_object_get(payload->json, "cause"));
163
164         if (!ast_strlen_zero(cause)) {
165                 ast_str_set(&cause_string, 0, "Cause: %s\r\n", cause);
166         }
167
168         return ast_manager_event_blob_create(EVENT_FLAG_SYSTEM, "Registry",
169                 "ChannelType: %s\r\n"
170                 "Username: %s\r\n"
171                 "Domain: %s\r\n"
172                 "Status: %s\r\n"
173                 "%s",
174                 channeltype, username, domain, status, ast_str_buffer(cause_string));
175 }
176
177 static struct ast_manager_event_blob *cc_available_to_ami(struct stasis_message *message)
178 {
179         struct ast_json_payload *payload = stasis_message_data(message);
180         int core_id;
181         const char *callee;
182         const char *service;
183
184         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
185         callee = ast_json_string_get(ast_json_object_get(payload->json, "callee"));
186         service = ast_json_string_get(ast_json_object_get(payload->json, "service"));
187
188         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCAvailable",
189                 "CoreID: %d\r\n"
190                 "Callee: %s\r\n"
191                 "Service: %s\r\n",
192                 core_id, callee, service);
193 }
194
195 static struct ast_manager_event_blob *cc_offertimerstart_to_ami(struct stasis_message *message)
196 {
197         struct ast_json_payload *payload = stasis_message_data(message);
198         int core_id;
199         const char *caller;
200         unsigned int expires;
201
202         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
203         caller = ast_json_string_get(ast_json_object_get(payload->json, "caller"));
204         expires = ast_json_integer_get(ast_json_object_get(payload->json, "expires"));
205
206         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCOfferTimerStart",
207                 "CoreID: %d\r\n"
208                 "Caller: %s\r\n"
209                 "Expires: %u\r\n",
210                 core_id, caller, expires);
211 }
212
213 static struct ast_manager_event_blob *cc_requested_to_ami(struct stasis_message *message)
214 {
215         struct ast_json_payload *payload = stasis_message_data(message);
216         int core_id;
217         const char *caller;
218         const char *callee;
219
220         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
221         caller = ast_json_string_get(ast_json_object_get(payload->json, "caller"));
222         callee = ast_json_string_get(ast_json_object_get(payload->json, "callee"));
223
224         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCRequested",
225                 "CoreID: %d\r\n"
226                 "Caller: %s\r\n"
227                 "Callee: %s\r\n",
228                 core_id, caller, callee);
229 }
230
231 static struct ast_manager_event_blob *cc_requestacknowledged_to_ami(struct stasis_message *message)
232 {
233         struct ast_json_payload *payload = stasis_message_data(message);
234         int core_id;
235         const char *caller;
236
237         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
238         caller = ast_json_string_get(ast_json_object_get(payload->json, "caller"));
239
240         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCRequestAcknowledged",
241                 "CoreID: %d\r\n"
242                 "Caller: %s\r\n",
243                 core_id, caller);
244 }
245
246 static struct ast_manager_event_blob *cc_callerstopmonitoring_to_ami(struct stasis_message *message)
247 {
248         struct ast_json_payload *payload = stasis_message_data(message);
249         int core_id;
250         const char *caller;
251
252         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
253         caller = ast_json_string_get(ast_json_object_get(payload->json, "caller"));
254
255         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCCallerStopMonitoring",
256                 "CoreID: %d\r\n"
257                 "Caller: %s\r\n",
258                 core_id, caller);
259 }
260
261 static struct ast_manager_event_blob *cc_callerstartmonitoring_to_ami(struct stasis_message *message)
262 {
263         struct ast_json_payload *payload = stasis_message_data(message);
264         int core_id;
265         const char *caller;
266
267         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
268         caller = ast_json_string_get(ast_json_object_get(payload->json, "caller"));
269
270         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCCallerStartMonitoring",
271                 "CoreID: %d\r\n"
272                 "Caller: %s\r\n",
273                 core_id, caller);
274 }
275
276 static struct ast_manager_event_blob *cc_callerrecalling_to_ami(struct stasis_message *message)
277 {
278         struct ast_json_payload *payload = stasis_message_data(message);
279         int core_id;
280         const char *caller;
281
282         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
283         caller = ast_json_string_get(ast_json_object_get(payload->json, "caller"));
284
285         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCCallerRecalling",
286                 "CoreID: %d\r\n"
287                 "Caller: %s\r\n",
288                 core_id, caller);
289 }
290
291 static struct ast_manager_event_blob *cc_recallcomplete_to_ami(struct stasis_message *message)
292 {
293         struct ast_json_payload *payload = stasis_message_data(message);
294         int core_id;
295         const char *caller;
296
297         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
298         caller = ast_json_string_get(ast_json_object_get(payload->json, "caller"));
299
300         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCRecallComplete",
301                 "CoreID: %d\r\n"
302                 "Caller: %s\r\n",
303                 core_id, caller);
304 }
305
306 static struct ast_manager_event_blob *cc_failure_to_ami(struct stasis_message *message)
307 {
308         struct ast_json_payload *payload = stasis_message_data(message);
309         int core_id;
310         const char *caller;
311         const char *reason;
312
313         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
314         caller = ast_json_string_get(ast_json_object_get(payload->json, "caller"));
315         reason = ast_json_string_get(ast_json_object_get(payload->json, "reason"));
316
317         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCFailure",
318                 "CoreID: %d\r\n"
319                 "Caller: %s\r\n"
320                 "Reason: %s\r\n",
321                 core_id, caller, reason);
322 }
323
324 static struct ast_manager_event_blob *cc_monitorfailed_to_ami(struct stasis_message *message)
325 {
326         struct ast_json_payload *payload = stasis_message_data(message);
327         int core_id;
328         const char *callee;
329
330         core_id = ast_json_integer_get(ast_json_object_get(payload->json, "core_id"));
331         callee = ast_json_string_get(ast_json_object_get(payload->json, "callee"));
332
333         return ast_manager_event_blob_create(EVENT_FLAG_CC, "CCMonitorFailed",
334                 "CoreID: %d\r\n"
335                 "Callee: %s\r\n",
336                 core_id, callee);
337 }
338
339 struct stasis_topic *ast_system_topic(void)
340 {
341         return system_topic;
342 }
343
344 /*! \brief Cleanup the \ref stasis system level items */
345 static void stasis_system_cleanup(void)
346 {
347         ao2_cleanup(system_topic);
348         system_topic = NULL;
349         STASIS_MESSAGE_TYPE_CLEANUP(ast_network_change_type);
350         STASIS_MESSAGE_TYPE_CLEANUP(ast_system_registry_type);
351         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_available_type);
352         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_offertimerstart_type);
353         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_requested_type);
354         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_requestacknowledged_type);
355         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_callerstopmonitoring_type);
356         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_callerstartmonitoring_type);
357         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_callerrecalling_type);
358         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_recallcomplete_type);
359         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_failure_type);
360         STASIS_MESSAGE_TYPE_CLEANUP(ast_cc_monitorfailed_type);
361 }
362
363 /*! \brief Initialize the system level items for \ref stasis */
364 int ast_stasis_system_init(void)
365 {
366         ast_register_cleanup(stasis_system_cleanup);
367
368         system_topic = stasis_topic_create("ast_system");
369         if (!system_topic) {
370                 return 1;
371         }
372
373         if (STASIS_MESSAGE_TYPE_INIT(ast_network_change_type) != 0) {
374                 return -1;
375         }
376
377         if (STASIS_MESSAGE_TYPE_INIT(ast_system_registry_type) != 0) {
378                 return -1;
379         }
380
381         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_available_type) != 0) {
382                 return -1;
383         }
384
385         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_offertimerstart_type) != 0) {
386                 return -1;
387         }
388
389         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_requested_type) != 0) {
390                 return -1;
391         }
392
393         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_requestacknowledged_type) != 0) {
394                 return -1;
395         }
396
397         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_callerstopmonitoring_type) != 0) {
398                 return -1;
399         }
400
401         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_callerstartmonitoring_type) != 0) {
402                 return -1;
403         }
404
405         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_callerrecalling_type) != 0) {
406                 return -1;
407         }
408
409         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_recallcomplete_type) != 0) {
410                 return -1;
411         }
412
413         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_failure_type) != 0) {
414                 return -1;
415         }
416
417         if (STASIS_MESSAGE_TYPE_INIT(ast_cc_monitorfailed_type) != 0) {
418                 return -1;
419         }
420
421         return 0;
422 }