Wed Jan 8 2020 09:49:54

Asterisk developer's documentation


app_page.c File Reference

page() - Paging application More...

#include "asterisk.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/chanvars.h"
#include "asterisk/utils.h"
#include "asterisk/devicestate.h"
#include "asterisk/dial.h"

Go to the source code of this file.

Enumerations

enum  { OPT_ARG_ANNOUNCE = 0, OPT_ARG_ARRAY_SIZE = 1 }
 
enum  page_opt_flags {
  PAGE_DUPLEX = (1 << 0), PAGE_QUIET = (1 << 1), PAGE_RECORD = (1 << 2), PAGE_SKIP = (1 << 3),
  PAGE_IGNORE_FORWARDS = (1 << 4), PAGE_ANNOUNCE = (1 << 5), PAGE_NOCALLERANNOUNCE = (1 << 6)
}
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int load_module (void)
 
static int page_exec (struct ast_channel *chan, const char *data)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Page Multiple Phones" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static const char *const app_page = "Page"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_app_option page_opts [128] = { [ 'd' ] = { .flag = PAGE_DUPLEX }, [ 'q' ] = { .flag = PAGE_QUIET }, [ 'r' ] = { .flag = PAGE_RECORD }, [ 's' ] = { .flag = PAGE_SKIP }, [ 'i' ] = { .flag = PAGE_IGNORE_FORWARDS }, [ 'A' ] = { .flag = PAGE_ANNOUNCE , .arg_index = OPT_ARG_ANNOUNCE + 1 }, [ 'n' ] = { .flag = PAGE_NOCALLERANNOUNCE }, }
 

Detailed Description

page() - Paging application

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file app_page.c.

Enumeration Type Documentation

anonymous enum
Enumerator
OPT_ARG_ANNOUNCE 
OPT_ARG_ARRAY_SIZE 

Definition at line 124 of file app_page.c.

124  {
125  OPT_ARG_ANNOUNCE = 0,
126  OPT_ARG_ARRAY_SIZE = 1,
127 };
Enumerator
PAGE_DUPLEX 
PAGE_QUIET 
PAGE_RECORD 
PAGE_SKIP 
PAGE_IGNORE_FORWARDS 
PAGE_ANNOUNCE 
PAGE_NOCALLERANNOUNCE 

Definition at line 114 of file app_page.c.

114  {
115  PAGE_DUPLEX = (1 << 0),
116  PAGE_QUIET = (1 << 1),
117  PAGE_RECORD = (1 << 2),
118  PAGE_SKIP = (1 << 3),
119  PAGE_IGNORE_FORWARDS = (1 << 4),
120  PAGE_ANNOUNCE = (1 << 5),
121  PAGE_NOCALLERANNOUNCE = (1 << 6),
122 };

Function Documentation

static void __reg_module ( void  )
static

Definition at line 320 of file app_page.c.

static void __unreg_module ( void  )
static

Definition at line 320 of file app_page.c.

static int load_module ( void  )
static

Definition at line 315 of file app_page.c.

References ast_register_application_xml, and page_exec().

316 {
318 }
static const char *const app_page
Definition: app_page.c:112
static int page_exec(struct ast_channel *chan, const char *data)
Definition: app_page.c:140
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static int page_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 140 of file app_page.c.

References app, args, AST_APP_ARG, ast_app_parse_options(), ast_calloc, AST_CHANNEL_NAME, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_DEVICE_NOT_INUSE, AST_DEVICE_UNKNOWN, ast_devstate2str(), ast_dial_append(), ast_dial_create(), ast_dial_destroy(), ast_dial_hangup(), ast_dial_join(), AST_DIAL_OPTION_ANSWER_EXEC, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, ast_dial_option_global_enable(), ast_dial_run(), ast_dial_set_global_timeout(), ast_free, ast_log(), ast_random(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitstream(), ast_channel::language, LOG_ERROR, LOG_WARNING, ast_channel::name, OPT_ARG_ANNOUNCE, OPT_ARG_ARRAY_SIZE, ast_dial::options, PAGE_ANNOUNCE, PAGE_DUPLEX, PAGE_IGNORE_FORWARDS, PAGE_NOCALLERANNOUNCE, page_opts, PAGE_QUIET, PAGE_RECORD, PAGE_SKIP, parse(), pbx_exec(), pbx_findapp(), strsep(), and ast_dial::timeout.

Referenced by load_module().

141 {
142  char *tech, *resource, *tmp;
143  char meetmeopts[128], originator[AST_CHANNEL_NAME], *opts[OPT_ARG_ARRAY_SIZE];
144  struct ast_flags flags = { 0 };
145  unsigned int confid = ast_random();
146  struct ast_app *app;
147  int res = 0, pos = 0, i = 0;
148  struct ast_dial **dial_list;
149  unsigned int num_dials;
150  int timeout = 0;
151  char *parse;
152 
156  AST_APP_ARG(timeout);
157  );
158 
159  if (ast_strlen_zero(data)) {
160  ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
161  return -1;
162  }
163 
164  if (!(app = pbx_findapp("MeetMe"))) {
165  ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
166  return -1;
167  };
168 
169  parse = ast_strdupa(data);
170 
171  AST_STANDARD_APP_ARGS(args, parse);
172 
173  ast_copy_string(originator, chan->name, sizeof(originator));
174  if ((tmp = strchr(originator, '-'))) {
175  *tmp = '\0';
176  }
177 
178  if (!ast_strlen_zero(args.options)) {
179  ast_app_parse_options(page_opts, &flags, opts, args.options);
180  } else {
181  /* opts must be initialized if there wasn't an options string. */
182  for (i = 0; i < OPT_ARG_ARRAY_SIZE; i++) {
183  opts[i] = NULL;
184  }
185  }
186 
187  if (!ast_strlen_zero(args.timeout)) {
188  timeout = atoi(args.timeout);
189  }
190 
192  snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe,%ud,%s%sqxdw(5)G(%s)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
193  (ast_test_flag(&flags, PAGE_RECORD) ? "r" : ""), opts[OPT_ARG_ANNOUNCE] );
194  } else {
195  snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe,%ud,%s%sqxdw(5)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
196  (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
197  }
198 
199  /* Count number of extensions in list by number of ampersands + 1 */
200  num_dials = 1;
201  tmp = args.devices;
202  while (*tmp) {
203  if (*tmp == '&') {
204  num_dials++;
205  }
206  tmp++;
207  }
208 
209  if (!(dial_list = ast_calloc(num_dials, sizeof(struct ast_dial *)))) {
210  ast_log(LOG_ERROR, "Can't allocate %ld bytes for dial list\n", (long)(sizeof(struct ast_dial *) * num_dials));
211  return -1;
212  }
213 
214  /* Go through parsing/calling each device */
215  while ((tech = strsep(&args.devices, "&"))) {
216  int state = 0;
217  struct ast_dial *dial = NULL;
218 
219  /* don't call the originating device */
220  if (!strcasecmp(tech, originator))
221  continue;
222 
223  /* If no resource is available, continue on */
224  if (!(resource = strchr(tech, '/'))) {
225  ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
226  continue;
227  }
228 
229  /* Ensure device is not in use if skip option is enabled */
230  if (ast_test_flag(&flags, PAGE_SKIP)) {
231  state = ast_device_state(tech);
232  if (state == AST_DEVICE_UNKNOWN) {
233  ast_log(LOG_WARNING, "Destination '%s' has device state '%s'. Paging anyway.\n", tech, ast_devstate2str(state));
234  } else if (state != AST_DEVICE_NOT_INUSE) {
235  ast_log(LOG_WARNING, "Destination '%s' has device state '%s'.\n", tech, ast_devstate2str(state));
236  continue;
237  }
238  }
239 
240  *resource++ = '\0';
241 
242  /* Create a dialing structure */
243  if (!(dial = ast_dial_create())) {
244  ast_log(LOG_WARNING, "Failed to create dialing structure.\n");
245  continue;
246  }
247 
248  /* Append technology and resource */
249  if (ast_dial_append(dial, tech, resource) == -1) {
250  ast_log(LOG_ERROR, "Failed to add %s to outbound dial\n", tech);
251  ast_dial_destroy(dial);
252  continue;
253  }
254 
255  /* Set ANSWER_EXEC as global option */
257 
258  if (timeout) {
259  ast_dial_set_global_timeout(dial, timeout * 1000);
260  }
261 
262  if (ast_test_flag(&flags, PAGE_IGNORE_FORWARDS)) {
264  }
265 
266  /* Run this dial in async mode */
267  ast_dial_run(dial, chan, 1);
268 
269  /* Put in our dialing array */
270  dial_list[pos++] = dial;
271  }
272 
273  if (!ast_test_flag(&flags, PAGE_QUIET)) {
274  res = ast_streamfile(chan, "beep", chan->language);
275  if (!res)
276  res = ast_waitstream(chan, "");
277  }
278 
279  if (!res) {
280  /* Default behaviour */
281  snprintf(meetmeopts, sizeof(meetmeopts), "%ud,A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"),
282  (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
283  if (ast_test_flag(&flags, PAGE_ANNOUNCE) && !ast_strlen_zero(opts[OPT_ARG_ANNOUNCE]) &&
285  snprintf(meetmeopts, sizeof(meetmeopts), "%ud,A%s%sqxdG(%s)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"),
286  (ast_test_flag(&flags, PAGE_RECORD) ? "r" : ""), opts[OPT_ARG_ANNOUNCE] );
287  }
288  pbx_exec(chan, app, meetmeopts);
289  }
290 
291  /* Go through each dial attempt cancelling, joining, and destroying */
292  for (i = 0; i < pos; i++) {
293  struct ast_dial *dial = dial_list[i];
294 
295  /* We have to wait for the async thread to exit as it's possible Meetme won't throw them out immediately */
296  ast_dial_join(dial);
297 
298  /* Hangup all channels */
299  ast_dial_hangup(dial);
300 
301  /* Destroy dialing structure */
302  ast_dial_destroy(dial);
303  }
304 
305  ast_free(dial_list);
306 
307  return -1;
308 }
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Find devicestate as text message for output.
Definition: devicestate.c:215
ast_device_state
Device States.
Definition: devicestate.h:51
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:866
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
Enables an option globally.
Definition: dial.c:923
char * strsep(char **str, const char *delims)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
Main dialing structure. Contains global options, channels being dialed, and more! ...
Definition: dial.c:47
void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
Set the maximum time (globally) allowed for trying to ring phones.
Definition: dial.c:1053
#define ast_test_flag(p, flag)
Definition: utils.h:63
void ast_dial_hangup(struct ast_dial *dial)
Hangup channels.
Definition: dial.c:842
#define LOG_WARNING
Definition: logger.h:144
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device)
Append a channel.
Definition: dial.c:229
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
unsigned int flags
Definition: utils.h:201
void * options[AST_DIAL_OPTION_MAX]
Definition: dial.c:52
static const char app[]
Definition: app_adsiprog.c:49
enum ast_dial_result ast_dial_join(struct ast_dial *dial)
Cancel async thread.
Definition: dial.c:794
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
long int ast_random(void)
Definition: utils.c:1640
static struct ast_app_option page_opts[128]
Definition: app_page.c:137
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition: dial.c:714
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
#define ast_free(a)
Definition: astmm.h:97
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:201
#define AST_CHANNEL_NAME
Definition: channel.h:137
Structure used to handle boolean flags.
Definition: utils.h:200
char tech[OSP_SIZE_TECHSTR]
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
ast_app: A registered application
Definition: pbx.c:971
int timeout
Definition: dial.c:49
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
const ast_string_field language
Definition: channel.h:787
static int unload_module ( void  )
static

Definition at line 310 of file app_page.c.

References ast_unregister_application().

311 {
313 }
static const char *const app_page
Definition: app_page.c:112
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Page Multiple Phones" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 320 of file app_page.c.

const char* const app_page = "Page"
static

Definition at line 112 of file app_page.c.

Definition at line 320 of file app_page.c.

struct ast_app_option page_opts[128] = { [ 'd' ] = { .flag = PAGE_DUPLEX }, [ 'q' ] = { .flag = PAGE_QUIET }, [ 'r' ] = { .flag = PAGE_RECORD }, [ 's' ] = { .flag = PAGE_SKIP }, [ 'i' ] = { .flag = PAGE_IGNORE_FORWARDS }, [ 'A' ] = { .flag = PAGE_ANNOUNCE , .arg_index = OPT_ARG_ANNOUNCE + 1 }, [ 'n' ] = { .flag = PAGE_NOCALLERANNOUNCE }, }
static

Definition at line 137 of file app_page.c.

Referenced by page_exec().