Wed Jan 8 2020 09:49:39

Asterisk developer's documentation


app_alarmreceiver.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2005 Steve Rodgers
5  *
6  * Steve Rodgers <hwstar@rodgers.sdcoxmail.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  * \brief Central Station Alarm receiver for Ademco Contact ID
21  * \author Steve Rodgers <hwstar@rodgers.sdcoxmail.com>
22  *
23  * *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
24  *
25  * Use at your own risk. Please consult the GNU GPL license document included with Asterisk. *
26  *
27  * *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
28  *
29  * \ingroup applications
30  */
31 
32 /*** MODULEINFO
33  <support_level>extended</support_level>
34  ***/
35 
36 #include "asterisk.h"
37 
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
39 
40 #include <math.h>
41 #include <sys/wait.h>
42 #include <sys/time.h>
43 
44 #include "asterisk/lock.h"
45 #include "asterisk/file.h"
46 #include "asterisk/channel.h"
47 #include "asterisk/pbx.h"
48 #include "asterisk/module.h"
49 #include "asterisk/translate.h"
50 #include "asterisk/ulaw.h"
51 #include "asterisk/app.h"
52 #include "asterisk/dsp.h"
53 #include "asterisk/config.h"
54 #include "asterisk/localtime.h"
55 #include "asterisk/callerid.h"
56 #include "asterisk/astdb.h"
57 #include "asterisk/utils.h"
58 
59 #define ALMRCV_CONFIG "alarmreceiver.conf"
60 #define ADEMCO_CONTACT_ID "ADEMCO_CONTACT_ID"
61 
62 struct event_node{
63  char data[17];
64  struct event_node *next;
65 };
66 
67 typedef struct event_node event_node_t;
68 
69 static const char app[] = "AlarmReceiver";
70 /*** DOCUMENTATION
71  <application name="AlarmReceiver" language="en_US">
72  <synopsis>
73  Provide support for receiving alarm reports from a burglar or fire alarm panel.
74  </synopsis>
75  <syntax />
76  <description>
77  <para>This application should be called whenever there is an alarm panel calling in to dump its events.
78  The application will handshake with the alarm panel, and receive events, validate them, handshake them,
79  and store them until the panel hangs up. Once the panel hangs up, the application will run the system
80  command specified by the eventcmd setting in <filename>alarmreceiver.conf</filename> and pipe the
81  events to the standard input of the application.
82  The configuration file also contains settings for DTMF timing, and for the loudness of the
83  acknowledgement tones.</para>
84  <note><para>Only 1 signalling format is supported at this time: Ademco Contact ID.</para></note>
85  </description>
86  <see-also>
87  <ref type="filename">alarmreceiver.conf</ref>
88  </see-also>
89  </application>
90  ***/
91 
92 /* Config Variables */
93 static int fdtimeout = 2000;
94 static int sdtimeout = 200;
95 static int toneloudness = 4096;
96 static int log_individual_events = 0;
97 static char event_spool_dir[128] = {'\0'};
98 static char event_app[128] = {'\0'};
99 static char db_family[128] = {'\0'};
100 static char time_stamp_format[128] = {"%a %b %d, %Y @ %H:%M:%S %Z"};
101 
102 /* Misc variables */
103 static char event_file[14] = "/event-XXXXXX";
104 
105 /*
106 * Attempt to access a database variable and increment it,
107 * provided that the user defined db-family in alarmreceiver.conf
108 * The alarmreceiver app will write statistics to a few variables
109 * in this family if it is defined. If the new key doesn't exist in the
110 * family, then create it and set its value to 1.
111 */
112 static void database_increment( char *key )
113 {
114  int res = 0;
115  unsigned v;
116  char value[16];
117 
118 
119  if (ast_strlen_zero(db_family))
120  return; /* If not defined, don't do anything */
121 
122  res = ast_db_get(db_family, key, value, sizeof(value) - 1);
123 
124  if (res) {
125  ast_verb(4, "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
126  /* Guess we have to create it */
127  res = ast_db_put(db_family, key, "1");
128  return;
129  }
130 
131  sscanf(value, "%30u", &v);
132  v++;
133 
134  ast_verb(4, "AlarmReceiver: New value for %s: %u\n", key, v);
135 
136  snprintf(value, sizeof(value), "%u", v);
137 
138  res = ast_db_put(db_family, key, value);
139 
140  if (res)
141  ast_verb(4, "AlarmReceiver: database_increment write error\n");
142 
143  return;
144 }
145 
146 
147 /*
148 * Build a MuLaw data block for a single frequency tone
149 */
150 static void make_tone_burst(unsigned char *data, float freq, float loudness, int len, int *x)
151 {
152  int i;
153  float val;
154 
155  for (i = 0; i < len; i++) {
156  val = loudness * sin((freq * 2.0 * M_PI * (*x)++)/8000.0);
157  data[i] = AST_LIN2MU((int)val);
158  }
159 
160  /* wrap back around from 8000 */
161 
162  if (*x >= 8000)
163  *x = 0;
164  return;
165 }
166 
167 /*
168 * Send a single tone burst for a specifed duration and frequency.
169 * Returns 0 if successful
170 */
171 static int send_tone_burst(struct ast_channel *chan, float freq, int duration, int tldn)
172 {
173  int res = 0;
174  int i = 0;
175  int x = 0;
176  struct ast_frame *f, wf;
177 
178  struct {
179  unsigned char offset[AST_FRIENDLY_OFFSET];
180  unsigned char buf[640];
181  } tone_block;
182 
183  for (;;) {
184 
185  if (ast_waitfor(chan, -1) < 0) {
186  res = -1;
187  break;
188  }
189 
190  f = ast_read(chan);
191  if (!f) {
192  res = -1;
193  break;
194  }
195 
196  if (f->frametype == AST_FRAME_VOICE) {
200  wf.mallocd = 0;
201  wf.data.ptr = tone_block.buf;
202  wf.datalen = f->datalen;
203  wf.samples = wf.datalen;
204 
205  make_tone_burst(tone_block.buf, freq, (float) tldn, wf.datalen, &x);
206 
207  i += wf.datalen / 8;
208  if (i > duration) {
209  ast_frfree(f);
210  break;
211  }
212  if (ast_write(chan, &wf)) {
213  ast_verb(4, "AlarmReceiver: Failed to write frame on %s\n", chan->name);
214  ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
215  res = -1;
216  ast_frfree(f);
217  break;
218  }
219  }
220 
221  ast_frfree(f);
222  }
223  return res;
224 }
225 
226 /*
227 * Receive a string of DTMF digits where the length of the digit string is known in advance. Do not give preferential
228 * treatment to any digit value, and allow separate time out values to be specified for the first digit and all subsequent
229 * digits.
230 *
231 * Returns 0 if all digits successfully received.
232 * Returns 1 if a digit time out occurred
233 * Returns -1 if the caller hung up or there was a channel error.
234 *
235 */
236 static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
237 {
238  int res = 0;
239  int i = 0;
240  int r;
241  struct ast_frame *f;
242  struct timeval lastdigittime;
243 
244  lastdigittime = ast_tvnow();
245  for (;;) {
246  /* if outa time, leave */
247  if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((i > 0) ? sdto : fdto)) {
248  ast_verb(4, "AlarmReceiver: DTMF Digit Timeout on %s\n", chan->name);
249  ast_debug(1,"AlarmReceiver: DTMF timeout on chan %s\n",chan->name);
250  res = 1;
251  break;
252  }
253 
254  if ((r = ast_waitfor(chan, -1) < 0)) {
255  ast_debug(1, "Waitfor returned %d\n", r);
256  continue;
257  }
258 
259  f = ast_read(chan);
260 
261  if (f == NULL) {
262  res = -1;
263  break;
264  }
265 
266  /* If they hung up, leave */
268  if (f->data.uint32) {
269  chan->hangupcause = f->data.uint32;
270  }
271  ast_frfree(f);
272  res = -1;
273  break;
274  }
275 
276  /* if not DTMF, just do it again */
277  if (f->frametype != AST_FRAME_DTMF) {
278  ast_frfree(f);
279  continue;
280  }
281 
282  digit_string[i++] = f->subclass.integer; /* save digit */
283 
284  ast_frfree(f);
285 
286  /* If we have all the digits we expect, leave */
287  if(i >= length)
288  break;
289 
290  lastdigittime = ast_tvnow();
291  }
292 
293  digit_string[i] = '\0'; /* Nul terminate the end of the digit string */
294  return res;
295 }
296 
297 /*
298 * Write the metadata to the log file
299 */
300 static int write_metadata( FILE *logfile, char *signalling_type, struct ast_channel *chan)
301 {
302  int res = 0;
303  struct timeval t;
304  struct ast_tm now;
305  char *cl;
306  char *cn;
307  char workstring[80];
308  char timestamp[80];
309 
310  /* Extract the caller ID location */
311  ast_copy_string(workstring,
312  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
313  sizeof(workstring));
314  ast_shrink_phone_number(workstring);
315  if (ast_strlen_zero(workstring)) {
316  cl = "<unknown>";
317  } else {
318  cl = workstring;
319  }
320  cn = S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>");
321 
322  /* Get the current time */
323  t = ast_tvnow();
324  ast_localtime(&t, &now, NULL);
325 
326  /* Format the time */
327  ast_strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
328 
329  res = fprintf(logfile, "\n\n[metadata]\n\n");
330  if (res >= 0) {
331  res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
332  }
333  if (res >= 0) {
334  res = fprintf(logfile, "CALLINGFROM=%s\n", cl);
335  }
336  if (res >= 0) {
337  res = fprintf(logfile, "CALLERNAME=%s\n", cn);
338  }
339  if (res >= 0) {
340  res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
341  }
342  if (res >= 0) {
343  res = fprintf(logfile, "[events]\n\n");
344  }
345  if (res < 0) {
346  ast_verb(3, "AlarmReceiver: can't write metadata\n");
347  ast_debug(1,"AlarmReceiver: can't write metadata\n");
348  } else {
349  res = 0;
350  }
351 
352  return res;
353 }
354 
355 /*
356 * Write a single event to the log file
357 */
358 static int write_event( FILE *logfile, event_node_t *event)
359 {
360  int res = 0;
361 
362  if (fprintf(logfile, "%s\n", event->data) < 0)
363  res = -1;
364 
365  return res;
366 }
367 
368 /*
369 * If we are configured to log events, do so here.
370 *
371 */
372 static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event)
373 {
374 
375  int res = 0;
376  char workstring[sizeof(event_spool_dir)+sizeof(event_file)] = "";
377  int fd;
378  FILE *logfile;
379  event_node_t *elp = event;
380 
381  if (!ast_strlen_zero(event_spool_dir)) {
382 
383  /* Make a template */
384  ast_copy_string(workstring, event_spool_dir, sizeof(workstring));
385  strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
386 
387  /* Make the temporary file */
388  fd = mkstemp(workstring);
389 
390  if (fd == -1) {
391  ast_verb(3, "AlarmReceiver: can't make temporary file\n");
392  ast_debug(1,"AlarmReceiver: can't make temporary file\n");
393  res = -1;
394  }
395 
396  if (!res) {
397  logfile = fdopen(fd, "w");
398  if (logfile) {
399  /* Write the file */
400  res = write_metadata(logfile, signalling_type, chan);
401  if (!res)
402  while ((!res) && (elp != NULL)) {
403  res = write_event(logfile, elp);
404  elp = elp->next;
405  }
406  if (!res) {
407  if (fflush(logfile) == EOF)
408  res = -1;
409  if (!res) {
410  if (fclose(logfile) == EOF)
411  res = -1;
412  }
413  }
414  } else
415  res = -1;
416  }
417  }
418 
419  return res;
420 }
421 
422 /*
423 * This function implements the logic to receive the Ademco contact ID format.
424 *
425 * The function will return 0 when the caller hangs up, else a -1 if there was a problem.
426 */
427 static int receive_ademco_contact_id(struct ast_channel *chan, const void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
428 {
429  int i, j;
430  int res = 0;
431  int checksum;
432  char event[17];
433  event_node_t *enew, *elp;
434  int got_some_digits = 0;
435  int events_received = 0;
436  int ack_retries = 0;
437 
438  static char digit_map[15] = "0123456789*#ABC";
439  static unsigned char digit_weights[15] = {10,1,2,3,4,5,6,7,8,9,11,12,13,14,15};
440 
441  database_increment("calls-received");
442 
443  /* Wait for first event */
444  ast_verb(4, "AlarmReceiver: Waiting for first event from panel\n");
445 
446  while (res >= 0) {
447  if (got_some_digits == 0) {
448  /* Send ACK tone sequence */
449  ast_verb(4, "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
450  res = send_tone_burst(chan, 1400.0, 100, tldn);
451  if (!res)
452  res = ast_safe_sleep(chan, 100);
453  if (!res) {
454  ast_verb(4, "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
455  res = send_tone_burst(chan, 2300.0, 100, tldn);
456  }
457  }
458  if ( res >= 0)
459  res = receive_dtmf_digits(chan, event, sizeof(event) - 1, fdto, sdto);
460  if (res < 0) {
461  if (events_received == 0) {
462  /* Hangup with no events received should be logged in the DB */
463  database_increment("no-events-received");
464  } else {
465  if (ack_retries) {
466  ast_verb(4, "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
467  database_increment("ack-retries");
468  }
469  }
470  ast_verb(4, "AlarmReceiver: App exiting...\n");
471  res = -1;
472  break;
473  }
474 
475  if (res != 0) {
476  /* Didn't get all of the digits */
477  ast_verb(2, "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
478 
479  if (!got_some_digits) {
480  got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0;
481  ack_retries++;
482  }
483  continue;
484  }
485 
486  got_some_digits = 1;
487 
488  ast_verb(2, "AlarmReceiver: Received Event %s\n", event);
489  ast_debug(1, "AlarmReceiver: Received event: %s\n", event);
490 
491  /* Calculate checksum */
492 
493  for (j = 0, checksum = 0; j < 16; j++) {
494  for (i = 0; i < sizeof(digit_map); i++) {
495  if (digit_map[i] == event[j])
496  break;
497  }
498 
499  if (i == 16)
500  break;
501 
502  checksum += digit_weights[i];
503  }
504  if (i == 16) {
505  ast_verb(2, "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
506  continue; /* Bad character */
507  }
508 
509  /* Checksum is mod(15) of the total */
510 
511  checksum = checksum % 15;
512 
513  if (checksum) {
514  database_increment("checksum-errors");
515  ast_verb(2, "AlarmReceiver: Nonzero checksum\n");
516  ast_debug(1, "AlarmReceiver: Nonzero checksum\n");
517  continue;
518  }
519 
520  /* Check the message type for correctness */
521 
522  if (strncmp(event + 4, "18", 2)) {
523  if (strncmp(event + 4, "98", 2)) {
524  database_increment("format-errors");
525  ast_verb(2, "AlarmReceiver: Wrong message type\n");
526  ast_debug(1, "AlarmReceiver: Wrong message type\n");
527  continue;
528  }
529  }
530 
531  events_received++;
532 
533  /* Queue the Event */
534  if (!(enew = ast_calloc(1, sizeof(*enew)))) {
535  res = -1;
536  break;
537  }
538 
539  enew->next = NULL;
540  ast_copy_string(enew->data, event, sizeof(enew->data));
541 
542  /*
543  * Insert event onto end of list
544  */
545  if (*ehead == NULL)
546  *ehead = enew;
547  else {
548  for(elp = *ehead; elp->next != NULL; elp = elp->next)
549  ;
550  elp->next = enew;
551  }
552 
553  if (res > 0)
554  res = 0;
555 
556  /* Let the user have the option of logging the single event before sending the kissoff tone */
557  if ((res == 0) && (log_individual_events))
558  res = log_events(chan, ADEMCO_CONTACT_ID, enew);
559  /* Wait 200 msec before sending kissoff */
560  if (res == 0)
561  res = ast_safe_sleep(chan, 200);
562 
563  /* Send the kissoff tone */
564  if (res == 0)
565  res = send_tone_burst(chan, 1400.0, 900, tldn);
566  }
567 
568  return res;
569 }
570 
571 /*
572 * This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
573 * This function will always return 0.
574 */
575 static int alarmreceiver_exec(struct ast_channel *chan, const char *data)
576 {
577  int res = 0;
578  event_node_t *elp, *efree;
579  char signalling_type[64] = "";
580  event_node_t *event_head = NULL;
581 
582  /* Set write and read formats to ULAW */
583  ast_verb(4, "AlarmReceiver: Setting read and write formats to ULAW\n");
584 
586  ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
587  return -1;
588  }
589 
591  ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
592  return -1;
593  }
594 
595  /* Set default values for this invocation of the application */
596  ast_copy_string(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type));
597 
598  /* Answer the channel if it is not already */
599  ast_verb(4, "AlarmReceiver: Answering channel\n");
600  if (chan->_state != AST_STATE_UP) {
601  if ((res = ast_answer(chan)))
602  return -1;
603  }
604 
605  /* Wait for the connection to settle post-answer */
606  ast_verb(4, "AlarmReceiver: Waiting for connection to stabilize\n");
607  res = ast_safe_sleep(chan, 1250);
608 
609  /* Attempt to receive the events */
610  if (!res) {
611  /* Determine the protocol to receive in advance */
612  /* Note: Ademco contact is the only one supported at this time */
613  /* Others may be added later */
614  if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
615  receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head);
616  else
617  res = -1;
618  }
619 
620  /* Events queued by receiver, write them all out here if so configured */
621  if ((!res) && (log_individual_events == 0))
622  res = log_events(chan, signalling_type, event_head);
623 
624  /*
625  * Do we exec a command line at the end?
626  */
627  if ((!res) && (!ast_strlen_zero(event_app)) && (event_head)) {
628  ast_debug(1,"Alarmreceiver: executing: %s\n", event_app);
629  ast_safe_system(event_app);
630  }
631 
632  /*
633  * Free up the data allocated in our linked list
634  */
635  for (elp = event_head; (elp != NULL);) {
636  efree = elp;
637  elp = elp->next;
638  ast_free(efree);
639  }
640 
641  return 0;
642 }
643 
644 /*
645 * Load the configuration from the configuration file
646 */
647 static int load_config(void)
648 {
649  struct ast_config *cfg;
650  const char *p;
651  struct ast_flags config_flags = { 0 };
652 
653  /* Read in the config file */
654  cfg = ast_config_load(ALMRCV_CONFIG, config_flags);
655 
656  if (!cfg) {
657  ast_verb(4, "AlarmReceiver: No config file\n");
658  return 0;
659  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
660  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", ALMRCV_CONFIG);
661  return 0;
662  } else {
663  p = ast_variable_retrieve(cfg, "general", "eventcmd");
664  if (p) {
665  ast_copy_string(event_app, p, sizeof(event_app));
666  event_app[sizeof(event_app) - 1] = '\0';
667  }
668  p = ast_variable_retrieve(cfg, "general", "loudness");
669  if (p) {
670  toneloudness = atoi(p);
671  if(toneloudness < 100)
672  toneloudness = 100;
673  if(toneloudness > 8192)
674  toneloudness = 8192;
675  }
676  p = ast_variable_retrieve(cfg, "general", "fdtimeout");
677  if (p) {
678  fdtimeout = atoi(p);
679  if(fdtimeout < 1000)
680  fdtimeout = 1000;
681  if(fdtimeout > 10000)
682  fdtimeout = 10000;
683  }
684 
685  p = ast_variable_retrieve(cfg, "general", "sdtimeout");
686  if (p) {
687  sdtimeout = atoi(p);
688  if(sdtimeout < 110)
689  sdtimeout = 110;
690  if(sdtimeout > 4000)
691  sdtimeout = 4000;
692  }
693 
694  p = ast_variable_retrieve(cfg, "general", "logindividualevents");
695  if (p)
696  log_individual_events = ast_true(p);
697 
698  p = ast_variable_retrieve(cfg, "general", "eventspooldir");
699  if (p) {
700  ast_copy_string(event_spool_dir, p, sizeof(event_spool_dir));
701  event_spool_dir[sizeof(event_spool_dir) - 1] = '\0';
702  }
703 
704  p = ast_variable_retrieve(cfg, "general", "timestampformat");
705  if (p) {
706  ast_copy_string(time_stamp_format, p, sizeof(time_stamp_format));
707  time_stamp_format[sizeof(time_stamp_format) - 1] = '\0';
708  }
709 
710  p = ast_variable_retrieve(cfg, "general", "db-family");
711  if (p) {
712  ast_copy_string(db_family, p, sizeof(db_family));
713  db_family[sizeof(db_family) - 1] = '\0';
714  }
715  ast_config_destroy(cfg);
716  }
717  return 1;
718 }
719 
720 /*
721 * These functions are required to implement an Asterisk App.
722 */
723 static int unload_module(void)
724 {
725  return ast_unregister_application(app);
726 }
727 
728 static int load_module(void)
729 {
730  if (load_config()) {
734  } else
736 }
737 
738 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Alarm Receiver for Asterisk");
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
#define ALMRCV_CONFIG
union ast_frame_subclass subclass
Definition: frame.h:146
Main Channel structure associated with a channel.
Definition: channel.h:742
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
int ast_safe_system(const char *s)
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1077
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static char event_file[14]
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
int offset
Definition: frame.h:156
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
Definition: ast_expr2.c:325
int ast_db_get(const char *family, const char *key, char *out, int outlen)
Get key value specified by family/key.
Definition: db.c:348
Support for translation of data formats. translate.c.
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
void * ptr
Definition: frame.h:160
static int fdtimeout
static const char app[]
Convenient Signal Processing routines.
#define LOG_WARNING
Definition: logger.h:144
static int toneloudness
#define AST_FRAME_DTMF
Definition: frame.h:128
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
Configuration File Parser.
char * str
Subscriber name (Malloced)
Definition: channel.h:214
static int write_metadata(FILE *logfile, char *signalling_type, struct ast_channel *chan)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
format_t codec
Definition: frame.h:137
static int send_tone_burst(struct ast_channel *chan, float freq, int duration, int tldn)
static void database_increment(char *key)
int value
Definition: syslog.c:39
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static int receive_ademco_contact_id(struct ast_channel *chan, const void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
Utility functions.
#define M_PI
Custom localtime functions for multiple timezones.
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
static int alarmreceiver_exec(struct ast_channel *chan, const char *data)
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
u-Law to Signed linear conversion
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static void make_tone_burst(unsigned char *data, float freq, float loudness, int len, int *x)
int datalen
Definition: frame.h:148
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
struct event_node * next
Core PBX routines and definitions.
static char event_app[128]
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
#define AST_FORMAT_ULAW
Definition: frame.h:246
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
enum ast_channel_state _state
Definition: channel.h:839
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 int load_config(void)
#define ast_free(a)
Definition: astmm.h:97
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
Structure used to handle boolean flags.
Definition: utils.h:200
int mallocd
Definition: frame.h:152
static int load_module(void)
static int write_event(FILE *logfile, event_node_t *event)
static int log_individual_events
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
#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
#define ADEMCO_CONTACT_ID
static int sdtimeout
static char time_stamp_format[128]
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
Data structure associated with a single frame of data.
Definition: frame.h:142
int hangupcause
Definition: channel.h:849
static char event_spool_dir[128]
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:260
uint32_t uint32
Definition: frame.h:160
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event)
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()&#39;s, .&#39;s, and -&#39;s...
Definition: callerid.c:948
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
union ast_frame::@172 data
static char db_family[128]
Persistant data storage (akin to *doze registry)
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
#define AST_LIN2MU(a)
Definition: ulaw.h:49
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int samples
Definition: frame.h:150
static int unload_module(void)
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292