Asterisk - The Open Source Telephony Project GIT-master-3dae2cf
pbx_hangup_handler.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2016, CFWare, LLC
5 *
6 * Corey Farrell <git@cfware.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 PBX Hangup Handler management routines.
22 *
23 * \author Corey Farrell <git@cfware.com>
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include "asterisk/_private.h"
33#include "asterisk/app.h"
34#include "asterisk/cli.h"
36#include "asterisk/pbx.h"
38#include "asterisk/utils.h"
39
40/*!
41 * \internal
42 * \brief Publish a hangup handler related message to \ref stasis
43 */
44static void publish_hangup_handler_message(const char *action, struct ast_channel *chan, const char *handler)
45{
46 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
47
48 blob = ast_json_pack("{s: s, s: s}",
49 "type", action,
50 "handler", S_OR(handler, ""));
51 if (!blob) {
52 return;
53 }
54
56}
57
59{
61 struct ast_hangup_handler *h_handler;
62
63 ast_channel_lock(chan);
67 return 0;
68 }
69
70 /*
71 * Make sure that the channel is marked as hungup since we are
72 * going to run the hangup handlers on it.
73 */
75
76 for (;;) {
79 if (!h_handler) {
80 break;
81 }
82
83 publish_hangup_handler_message("run", chan, h_handler->args);
85
86 ast_app_exec_sub(NULL, chan, h_handler->args, 1);
87 ast_free(h_handler);
88
89 ast_channel_lock(chan);
90 }
92 return 1;
93}
94
96{
98
101}
102
104{
106 struct ast_hangup_handler *h_handler;
107
108 ast_channel_lock(chan);
109
110 /* Get rid of each of the hangup handlers on the channel */
112 while ((h_handler = AST_LIST_REMOVE_HEAD(handlers, node))) {
113 ast_free(h_handler);
114 }
115
116 ast_channel_unlock(chan);
117}
118
120{
122 struct ast_hangup_handler *h_handler;
123
124 ast_channel_lock(chan);
126 h_handler = AST_LIST_REMOVE_HEAD(handlers, node);
127 if (h_handler) {
128 publish_hangup_handler_message("pop", chan, h_handler->args);
129 }
130 ast_channel_unlock(chan);
131 if (h_handler) {
132 ast_free(h_handler);
133 return 1;
134 }
135 return 0;
136}
137
138void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler)
139{
141 struct ast_hangup_handler *h_handler;
142 const char *expanded_handler;
143
145 return;
146 }
147
148 expanded_handler = ast_app_expand_sub_args(chan, handler);
149 if (!expanded_handler) {
150 return;
151 }
152 h_handler = ast_malloc(sizeof(*h_handler) + 1 + strlen(expanded_handler));
153 if (!h_handler) {
154 ast_free((char *) expanded_handler);
155 return;
156 }
157 strcpy(h_handler->args, expanded_handler);/* Safe */
158 ast_free((char *) expanded_handler);
159
160 ast_channel_lock(chan);
161
164 publish_hangup_handler_message("push", chan, h_handler->args);
165 ast_channel_unlock(chan);
166}
167
168#define HANDLER_FORMAT "%-30s %s\n"
169
170/*!
171 * \internal
172 * \brief CLI output the hangup handler headers.
173 * \since 11.0
174 *
175 * \param fd CLI file descriptor to use.
176 */
178{
179 ast_cli(fd, HANDLER_FORMAT, "Channel", "Handler");
180}
181
182/*!
183 * \internal
184 * \brief CLI output the channel hangup handlers.
185 * \since 11.0
186 *
187 * \param fd CLI file descriptor to use.
188 * \param chan Channel to show hangup handlers.
189 */
190static void ast_pbx_hangup_handler_show(int fd, struct ast_channel *chan)
191{
193 struct ast_hangup_handler *h_handler;
194 int first = 1;
195
196 ast_channel_lock(chan);
198 AST_LIST_TRAVERSE(handlers, h_handler, node) {
199 ast_cli(fd, HANDLER_FORMAT, first ? ast_channel_name(chan) : "", h_handler->args);
200 first = 0;
201 }
202 ast_channel_unlock(chan);
203}
204
205/*!
206 * \brief 'show hanguphandlers <channel>' CLI command implementation function...
207 */
208static char *handle_show_hangup_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
209{
210 struct ast_channel *chan;
211
212 switch (cmd) {
213 case CLI_INIT:
214 e->command = "core show hanguphandlers";
215 e->usage =
216 "Usage: core show hanguphandlers <channel>\n"
217 " Show hangup handlers of a specified channel.\n";
218 return NULL;
219 case CLI_GENERATE:
220 return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
221 }
222
223 if (a->argc < 4) {
224 return CLI_SHOWUSAGE;
225 }
226
227 chan = ast_channel_get_by_name(a->argv[3]);
228 if (!chan) {
229 ast_cli(a->fd, "Channel does not exist.\n");
230 return CLI_FAILURE;
231 }
232
235
236 ast_channel_unref(chan);
237
238 return CLI_SUCCESS;
239}
240
241/*!
242 * \brief 'show hanguphandlers all' CLI command implementation function...
243 */
244static char *handle_show_hangup_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
245{
246 struct ast_channel_iterator *iter;
247 struct ast_channel *chan;
248
249 switch (cmd) {
250 case CLI_INIT:
251 e->command = "core show hanguphandlers all";
252 e->usage =
253 "Usage: core show hanguphandlers all\n"
254 " Show hangup handlers for all channels.\n";
255 return NULL;
256 case CLI_GENERATE:
257 return NULL;
258 }
259
260 if (a->argc < 4) {
261 return CLI_SHOWUSAGE;
262 }
263
265 if (!iter) {
266 return CLI_FAILURE;
267 }
268
270 for (; (chan = ast_channel_iterator_next(iter)); ast_channel_unref(chan)) {
272 }
274
275 return CLI_SUCCESS;
276}
277
278static struct ast_cli_entry cli[] = {
279 AST_CLI_DEFINE(handle_show_hangup_all, "Show hangup handlers of all channels"),
280 AST_CLI_DEFINE(handle_show_hangup_channel, "Show hangup handlers of a specified channel"),
281};
282
284{
286}
287
289{
292
293 return 0;
294}
Prototypes for public functions only of internal interest,.
struct sla_ringing_trunk * first
Definition: app_sla.c:332
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_free(a)
Definition: astmm.h:180
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1379
#define ast_channel_lock(chan)
Definition: channel.h:2968
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1441
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
@ AST_SOFTHANGUP_HANGUP_EXEC
Definition: channel.h:1174
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2477
struct ast_hangup_handler_list * ast_channel_hangup_handlers(struct ast_channel *chan)
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1473
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
Definition: channel.c:1427
#define ast_channel_unlock(chan)
Definition: channel.h:2969
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
Definition: main/cli.c:1872
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
struct stasis_message_type * ast_channel_hangup_handler_type(void)
Message type for hangup handler related actions.
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
const char * ast_app_expand_sub_args(struct ast_channel *chan, const char *args)
Add missing context/exten to subroutine argument string.
Definition: main/app.c:278
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition: main/app.c:297
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
A set of macros to manage forward-linked lists.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
Core PBX routines and definitions.
static void ast_pbx_hangup_handler_headers(int fd)
#define HANDLER_FORMAT
static char * handle_show_hangup_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
'show hanguphandlers all' CLI command implementation function...
static char * handle_show_hangup_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
'show hanguphandlers <channel>' CLI command implementation function...
void ast_pbx_hangup_handler_destroy(struct ast_channel *chan)
Destroy the hangup handler container on a channel.
int load_pbx_hangup_handler(void)
static void ast_pbx_hangup_handler_show(int fd, struct ast_channel *chan)
void ast_pbx_hangup_handler_init(struct ast_channel *chan)
Init the hangup handler container on a channel.
static struct ast_cli_entry cli[]
void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler)
Push the given hangup handler onto the channel hangup handler stack.
static void unload_pbx_hangup_handler(void)
static void publish_hangup_handler_message(const char *action, struct ast_channel *chan, const char *handler)
int ast_pbx_hangup_handler_run(struct ast_channel *chan)
Run all hangup handlers on the channel.
int ast_pbx_hangup_handler_pop(struct ast_channel *chan)
Pop the top of the channel hangup handler stack.
#define NULL
Definition: resample.c:96
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Main Channel structure associated with a channel.
descriptor for a cli entry.
Definition: cli.h:171
int args
This gets set in ast_cli_register()
Definition: cli.h:185
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Abstract JSON element (object, array, string, int, ...).
Definition: test_heap.c:38
static const struct ast_aeap_message_handler handlers[]
Definition: test_aeap.c:135
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59
static struct test_val a
Utility functions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ARRAY_LEN(a)
Definition: utils.h:666