Sat Aug 6 00:39:19 2011

Asterisk developer's documentation


app_alarmreceiver.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C)  2004 - 2005 Steve Rodgers
00005  *
00006  * Steve Rodgers <hwstar@rodgers.sdcoxmail.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  * \brief Central Station Alarm receiver for Ademco Contact ID  
00021  * \author Steve Rodgers <hwstar@rodgers.sdcoxmail.com>
00022  * 
00023  * *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** 
00024  *
00025  * Use at your own risk. Please consult the GNU GPL license document included with Asterisk.         *
00026  *
00027  * *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
00028  *
00029  * \ingroup applications
00030  */ 
00031  
00032 #include "asterisk.h"
00033 
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211528 $")
00035 
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include <stdio.h>
00039 #include <math.h>
00040 #include <sys/wait.h>
00041 #include <unistd.h>
00042 #include <sys/time.h>
00043 
00044 #include "asterisk/lock.h"
00045 #include "asterisk/file.h"
00046 #include "asterisk/logger.h"
00047 #include "asterisk/channel.h"
00048 #include "asterisk/pbx.h"
00049 #include "asterisk/module.h"
00050 #include "asterisk/translate.h"
00051 #include "asterisk/ulaw.h"
00052 #include "asterisk/options.h"
00053 #include "asterisk/app.h"
00054 #include "asterisk/dsp.h"
00055 #include "asterisk/config.h"
00056 #include "asterisk/localtime.h"
00057 #include "asterisk/callerid.h"
00058 #include "asterisk/astdb.h"
00059 #include "asterisk/utils.h"
00060 
00061 #define ALMRCV_CONFIG "alarmreceiver.conf"
00062 #define ADEMCO_CONTACT_ID "ADEMCO_CONTACT_ID"
00063 
00064 struct event_node{
00065    char data[17];
00066    struct event_node *next;
00067 };
00068 
00069 typedef struct event_node event_node_t;
00070 
00071 static char *app = "AlarmReceiver";
00072 
00073 static char *synopsis = "Provide support for receiving alarm reports from a burglar or fire alarm panel";
00074 static char *descrip =
00075 "  AlarmReceiver(): Only 1 signalling format is supported at this time: Ademco\n"
00076 "Contact ID. This application should be called whenever there is an alarm\n"
00077 "panel calling in to dump its events. The application will handshake with the\n"
00078 "alarm panel, and receive events, validate them, handshake them, and store them\n"
00079 "until the panel hangs up. Once the panel hangs up, the application will run the\n"
00080 "system command specified by the eventcmd setting in alarmreceiver.conf and pipe\n"
00081 "the events to the standard input of the application. The configuration file also\n"
00082 "contains settings for DTMF timing, and for the loudness of the acknowledgement\n" 
00083 "tones.\n";
00084 
00085 /* Config Variables */
00086 
00087 static int fdtimeout = 2000;
00088 static int sdtimeout = 200; 
00089 static int toneloudness = 4096;
00090 static int log_individual_events = 0;
00091 static char event_spool_dir[128] = {'\0'};
00092 static char event_app[128] = {'\0'};
00093 static char db_family[128] = {'\0'};
00094 static char time_stamp_format[128] = {"%a %b %d, %Y @ %H:%M:%S %Z"};
00095 
00096 /* Misc variables */
00097    
00098 static char event_file[14] = "/event-XXXXXX";
00099 
00100 /*
00101 * Attempt to access a database variable and increment it,
00102 * provided that the user defined db-family in alarmreceiver.conf
00103 * The alarmreceiver app will write statistics to a few variables
00104 * in this family if it is defined. If the new key doesn't exist in the
00105 * family, then create it and set its value to 1.
00106 */
00107 
00108 static void database_increment( char *key )
00109 {
00110    int res = 0;
00111    unsigned v;
00112    char value[16];
00113    
00114    
00115    if (ast_strlen_zero(db_family))
00116       return; /* If not defined, don't do anything */
00117    
00118    res = ast_db_get(db_family, key, value, sizeof(value) - 1);
00119    
00120    if(res){
00121       if(option_verbose >= 4)
00122          ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
00123       /* Guess we have to create it */
00124       res = ast_db_put(db_family, key, "1");
00125       return;
00126    }
00127    
00128    sscanf(value, "%30u", &v);
00129    v++;
00130    
00131    if(option_verbose >= 4)
00132       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: New value for %s: %u\n", key, v);
00133       
00134    snprintf(value, sizeof(value), "%u", v);
00135    
00136    res = ast_db_put(db_family, key, value);
00137    
00138    if((res)&&(option_verbose >= 4))
00139       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: database_increment write error\n");
00140    
00141    return;  
00142 }
00143 
00144 
00145 /*
00146 * Build a MuLaw data block for a single frequency tone
00147 */
00148 
00149 static void make_tone_burst(unsigned char *data, float freq, float loudness, int len, int *x)
00150 {
00151    int     i;
00152    float   val;
00153                                                                                                                                     
00154         for(i = 0; i < len; i++){
00155       val = loudness * sin((freq * 2.0 * M_PI * (*x)++)/8000.0);
00156       data[i] = AST_LIN2MU((int)val);
00157    }
00158 
00159    /* wrap back around from 8000 */
00160 
00161    if (*x >= 8000) *x = 0;
00162    return;
00163 }
00164 
00165 /*
00166 * Send a single tone burst for a specifed duration and frequency. 
00167 * Returns 0 if successful
00168 */
00169 
00170 static int send_tone_burst(struct ast_channel *chan, float freq, int duration, int tldn)
00171 {
00172    int res = 0;
00173    int i = 0;
00174    int x = 0;
00175    struct ast_frame *f, wf;
00176    
00177    struct {
00178       unsigned char offset[AST_FRIENDLY_OFFSET];
00179       unsigned char buf[640];
00180    } tone_block;
00181 
00182    for(;;)
00183    {
00184    
00185       if (ast_waitfor(chan, -1) < 0){
00186          res = -1;
00187          break;
00188       }
00189       
00190       f = ast_read(chan);
00191       if (!f){
00192          res = -1;
00193          break;
00194       }
00195       
00196       if (f->frametype == AST_FRAME_VOICE) {
00197          wf.frametype = AST_FRAME_VOICE;
00198          wf.subclass = AST_FORMAT_ULAW;
00199          wf.offset = AST_FRIENDLY_OFFSET;
00200          wf.mallocd = 0;
00201          wf.data = tone_block.buf;
00202          wf.datalen = f->datalen;
00203          wf.samples = wf.datalen;
00204          
00205          make_tone_burst(tone_block.buf, freq, (float) tldn, wf.datalen, &x);
00206 
00207          i += wf.datalen / 8;
00208          if (i > duration) {
00209             ast_frfree(f);
00210             break;
00211          }
00212          if (ast_write(chan, &wf)){
00213             if(option_verbose >= 4)
00214                ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Failed to write frame on %s\n", chan->name);
00215             ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
00216             res = -1;
00217             ast_frfree(f);
00218             break;
00219          }
00220       }
00221       
00222       ast_frfree(f);
00223    }
00224    return res;
00225 }
00226 
00227 /*
00228 * Receive a string of DTMF digits where the length of the digit string is known in advance. Do not give preferential
00229 * treatment to any digit value, and allow separate time out values to be specified for the first digit and all subsequent
00230 * digits.
00231 *
00232 * Returns 0 if all digits successfully received.
00233 * Returns 1 if a digit time out occurred
00234 * Returns -1 if the caller hung up or there was a channel error.
00235 *
00236 */
00237 
00238 static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
00239 {
00240    int res = 0;
00241    int i = 0;
00242    int r;
00243    struct ast_frame *f;
00244    struct timeval lastdigittime;
00245    
00246    lastdigittime = ast_tvnow();
00247    for(;;){
00248         /* if outa time, leave */
00249       if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) >
00250           ((i > 0) ? sdto : fdto)){
00251          if(option_verbose >= 4)
00252             ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: DTMF Digit Timeout on %s\n", chan->name);
00253             
00254          ast_log(LOG_DEBUG,"AlarmReceiver: DTMF timeout on chan %s\n",chan->name);
00255             
00256          res = 1;
00257          break;
00258       }
00259       
00260       if ((r = ast_waitfor(chan, -1) < 0)) {
00261          ast_log(LOG_DEBUG, "Waitfor returned %d\n", r);
00262          continue;
00263       }
00264          
00265       f = ast_read(chan);
00266       
00267       if (f == NULL){
00268          res = -1;
00269          break;
00270       }
00271       
00272       /* If they hung up, leave */
00273       if ((f->frametype == AST_FRAME_CONTROL) &&
00274           (f->subclass == AST_CONTROL_HANGUP)){
00275          ast_frfree(f);
00276          res = -1;
00277          break;
00278       }
00279       
00280       /* if not DTMF, just do it again */
00281       if (f->frametype != AST_FRAME_DTMF){
00282          ast_frfree(f);
00283          continue;
00284       }
00285 
00286       digit_string[i++] = f->subclass;  /* save digit */
00287       
00288       ast_frfree(f);
00289       
00290       /* If we have all the digits we expect, leave */
00291       if(i >= length)
00292          break;
00293       
00294       lastdigittime = ast_tvnow();
00295    }
00296    
00297    digit_string[i] = '\0'; /* Nul terminate the end of the digit string */
00298    return res;
00299 
00300 }
00301 
00302 /*
00303 * Write the metadata to the log file
00304 */
00305 
00306 static int write_metadata( FILE *logfile, char *signalling_type, struct ast_channel *chan)
00307 {
00308    int res = 0;
00309    time_t t;
00310    struct tm now;
00311    char *cl,*cn;
00312    char workstring[80];
00313    char timestamp[80];
00314    
00315    /* Extract the caller ID location */
00316    if (chan->cid.cid_num)
00317       ast_copy_string(workstring, chan->cid.cid_num, sizeof(workstring));
00318    workstring[sizeof(workstring) - 1] = '\0';
00319    
00320    ast_callerid_parse(workstring, &cn, &cl);
00321    if (cl) 
00322       ast_shrink_phone_number(cl);
00323                 
00324 
00325    /* Get the current time */
00326       
00327    time(&t);
00328    ast_localtime(&t, &now, NULL);
00329    
00330    /* Format the time */
00331    
00332    strftime(timestamp, sizeof(timestamp), time_stamp_format, &now); 
00333 
00334    
00335    res = fprintf(logfile, "\n\n[metadata]\n\n");
00336    
00337    if(res >= 0)
00338       res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
00339       
00340    if(res >= 0)   
00341       res = fprintf(logfile, "CALLINGFROM=%s\n", (!cl) ? "<unknown>" : cl);
00342       
00343    if(res >- 0)
00344       res = fprintf(logfile, "CALLERNAME=%s\n", (!cn) ? "<unknown>" : cn);
00345       
00346    if(res >= 0)
00347       res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
00348    
00349    if(res >= 0)
00350       res = fprintf(logfile, "[events]\n\n");
00351    
00352    if(res < 0){
00353       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't write metadata\n");  
00354       
00355       ast_log(LOG_DEBUG,"AlarmReceiver: can't write metadata\n");
00356    }
00357    else
00358       res = 0;
00359 
00360    return res;
00361 }
00362 
00363 /*
00364 * Write a single event to the log file
00365 */
00366 
00367 static int write_event( FILE *logfile,  event_node_t *event)
00368 {
00369    int res = 0;
00370 
00371    if( fprintf(logfile, "%s\n", event->data) < 0)
00372       res = -1;
00373          
00374    return res;
00375 }
00376 
00377 
00378 /*
00379 * If we are configured to log events, do so here.
00380 *
00381 */
00382 
00383 static int log_events(struct ast_channel *chan,  char *signalling_type, event_node_t *event)
00384 {
00385 
00386    int res = 0;
00387    char workstring[sizeof(event_spool_dir)+sizeof(event_file)] = "";
00388    int fd;
00389    FILE *logfile;
00390    event_node_t *elp = event;
00391    
00392    if (!ast_strlen_zero(event_spool_dir)) {
00393       
00394       /* Make a template */
00395       
00396       ast_copy_string(workstring, event_spool_dir, sizeof(workstring));
00397       strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
00398       
00399       /* Make the temporary file */
00400       
00401       fd = mkstemp(workstring);
00402       
00403       if(fd == -1){
00404          ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't make temporary file\n");   
00405          ast_log(LOG_DEBUG,"AlarmReceiver: can't make temporary file\n");
00406          res = -1;
00407       }
00408       
00409       if(!res){
00410          logfile = fdopen(fd, "w");
00411          if(logfile){
00412             /* Write the file */
00413             res = write_metadata(logfile, signalling_type, chan);
00414             if(!res)
00415                while((!res) && (elp != NULL)){
00416                   res = write_event(logfile, elp);
00417                   elp = elp->next;
00418                }
00419             if(!res){
00420                if(fflush(logfile) == EOF)
00421                   res = -1;
00422                if(!res){
00423                   if(fclose(logfile) == EOF)
00424                      res = -1;
00425                }           
00426             }
00427          }
00428          else
00429             res = -1;
00430       }
00431    }
00432 
00433    return res; 
00434 }
00435 
00436 /*
00437 * This function implements the logic to receive the Ademco contact ID  format.
00438 *
00439 * The function will return 0 when the caller hangs up, else a -1 if there was a problem.
00440 */
00441 
00442 static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
00443 {
00444    int i,j;
00445    int res = 0;
00446    int checksum;
00447    char event[17];
00448    event_node_t *enew, *elp;
00449    int got_some_digits = 0;
00450    int events_received = 0;
00451    int ack_retries = 0;
00452    
00453    static char digit_map[15] = "0123456789*#ABC";
00454         static unsigned char digit_weights[15] = {10,1,2,3,4,5,6,7,8,9,11,12,13,14,15};
00455                                                                                                                       
00456    database_increment("calls-received");
00457 
00458    /* Wait for first event */
00459 
00460    if(option_verbose >= 4)
00461       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for first event from panel\n");
00462 
00463    while(res >= 0){
00464 
00465       if(got_some_digits == 0){
00466 
00467             /* Send ACK tone sequence */
00468                         
00469                                                                                                                           
00470             if(option_verbose >= 4)
00471                      ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
00472                                                                                                                                             
00473                                                                                                                                             
00474             res = send_tone_burst(chan, 1400.0, 100, tldn);
00475                                                                                                                                             
00476             if(!res)
00477                      res = ast_safe_sleep(chan, 100);
00478                                                                                                                                             
00479             if(!res){
00480                      if(option_verbose >= 4)
00481                               ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
00482                                                                                                                                             
00483                      res = send_tone_burst(chan, 2300.0, 100, tldn);
00484             }
00485                                                                                                                                             
00486       }
00487 
00488       if( res >= 0)
00489          res = receive_dtmf_digits(chan, event, sizeof(event) - 1, fdto, sdto);
00490       
00491       if (res < 0){
00492       
00493          if(events_received == 0)
00494             /* Hangup with no events received should be logged in the DB */
00495             database_increment("no-events-received");
00496          else{
00497             if(ack_retries){
00498                if(option_verbose >= 4)
00499                   ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
00500                
00501                database_increment("ack-retries");
00502             }
00503          }
00504          if(option_verbose >= 4)
00505             ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: App exiting...\n");
00506          res = -1;
00507          break;
00508       }
00509       
00510       if(res != 0){
00511           /* Didn't get all of the digits */
00512          if(option_verbose >= 2)
00513             ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
00514 
00515          if(!got_some_digits){
00516             got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0;
00517             ack_retries++;
00518          }
00519          continue;   
00520       }     
00521       
00522       got_some_digits = 1;
00523 
00524       if(option_verbose >= 2)
00525          ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Received Event %s\n", event);
00526       ast_log(LOG_DEBUG, "AlarmReceiver: Received event: %s\n", event);
00527       
00528       /* Calculate checksum */
00529       
00530       for(j = 0, checksum = 0; j < 16; j++){
00531          for(i = 0 ; i < sizeof(digit_map) ; i++){
00532             if(digit_map[i] == event[j])
00533                break;
00534          }
00535          
00536          if(i == 16)
00537             break;
00538             
00539          checksum += digit_weights[i];
00540       }
00541       
00542       if(i == 16){
00543          if(option_verbose >= 2)
00544             ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
00545          continue; /* Bad character */
00546       }
00547 
00548       /* Checksum is mod(15) of the total */
00549 
00550       checksum = checksum % 15;
00551 
00552       if (checksum) {
00553          database_increment("checksum-errors");
00554          if (option_verbose >= 2)
00555             ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Nonzero checksum\n");
00556          ast_log(LOG_DEBUG, "AlarmReceiver: Nonzero checksum\n");
00557          continue;
00558       }
00559 
00560       /* Check the message type for correctness */
00561 
00562       if(strncmp(event + 4, "18", 2)){
00563          if(strncmp(event + 4, "98", 2)){
00564             database_increment("format-errors");
00565             if(option_verbose >= 2)
00566                ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Wrong message type\n");
00567             ast_log(LOG_DEBUG, "AlarmReceiver: Wrong message type\n");
00568          continue;
00569          }
00570       }
00571 
00572       events_received++;
00573       
00574       /* Queue the Event */      
00575       if (!(enew = ast_calloc(1, sizeof(*enew)))) {
00576          res = -1;
00577          break;
00578       }
00579       
00580       enew->next = NULL;
00581       ast_copy_string(enew->data, event, sizeof(enew->data));
00582 
00583       /*
00584       * Insert event onto end of list
00585       */
00586       
00587       if(*ehead == NULL){
00588          *ehead = enew;
00589       }
00590       else{
00591          for(elp = *ehead; elp->next != NULL; elp = elp->next)
00592          ;
00593          
00594          elp->next = enew;
00595       }
00596       
00597       if(res > 0)
00598          res = 0;
00599       
00600       /* Let the user have the option of logging the single event before sending the kissoff tone */
00601 
00602       if((res == 0) && (log_individual_events))
00603          res = log_events(chan, ADEMCO_CONTACT_ID, enew);
00604    
00605       /* Wait 200 msec before sending kissoff */   
00606          
00607       if(res == 0)   
00608          res = ast_safe_sleep(chan, 200);
00609 
00610       /* Send the kissoff tone */
00611 
00612       if(res == 0)      
00613          res = send_tone_burst(chan, 1400.0, 900, tldn);
00614    }
00615 
00616    
00617    return res;
00618 }
00619 
00620 
00621 /*
00622 * This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
00623 * This function will always return 0.
00624 */
00625 
00626 static int alarmreceiver_exec(struct ast_channel *chan, void *data)
00627 {
00628    int res = 0;
00629    struct ast_module_user *u;
00630    event_node_t *elp, *efree;
00631    char signalling_type[64] = "";
00632 
00633    event_node_t *event_head = NULL;
00634 
00635    u = ast_module_user_add(chan);
00636 
00637    /* Set write and read formats to ULAW */
00638 
00639    if(option_verbose >= 4)
00640       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Setting read and write formats to ULAW\n");
00641 
00642    if (ast_set_write_format(chan,AST_FORMAT_ULAW)){
00643       ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
00644       ast_module_user_remove(u);
00645       return -1;
00646    }
00647    
00648    if (ast_set_read_format(chan,AST_FORMAT_ULAW)){
00649       ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
00650       ast_module_user_remove(u);
00651       return -1;
00652    }
00653 
00654    /* Set default values for this invokation of the application */
00655    
00656    ast_copy_string(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type));
00657 
00658 
00659    /* Answer the channel if it is not already */
00660 
00661    if(option_verbose >= 4)
00662       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Answering channel\n");
00663 
00664    if (chan->_state != AST_STATE_UP) {
00665    
00666       res = ast_answer(chan);
00667       
00668       if (res) {
00669          ast_module_user_remove(u);
00670          return -1;
00671       }
00672    }
00673 
00674    /* Wait for the connection to settle post-answer */
00675 
00676    if(option_verbose >= 4)
00677       ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for connection to stabilize\n");
00678 
00679    res = ast_safe_sleep(chan, 1250);
00680 
00681    /* Attempt to receive the events */
00682 
00683    if(!res){
00684    
00685       /* Determine the protocol to receive in advance */
00686       /* Note: Ademco contact is the only one supported at this time */
00687       /* Others may be added later */
00688       
00689       if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
00690          receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head);
00691       else
00692          res = -1;
00693    }
00694    
00695       
00696    
00697    /* Events queued by receiver, write them all out here if so configured */
00698 
00699    if((!res) && (log_individual_events == 0)){
00700       res = log_events(chan, signalling_type, event_head);
00701 
00702    }
00703 
00704    /*
00705    * Do we exec a command line at the end?
00706    */
00707    
00708    if((!res) && (!ast_strlen_zero(event_app)) && (event_head)){
00709       ast_log(LOG_DEBUG,"Alarmreceiver: executing: %s\n", event_app);
00710       ast_safe_system(event_app);
00711    }
00712 
00713    /*
00714    * Free up the data allocated in our linked list
00715    */
00716       
00717    for(elp = event_head; (elp != NULL);){
00718       efree = elp;
00719       elp = elp->next;
00720       free(efree);
00721    }
00722 
00723 
00724    ast_module_user_remove(u);
00725 
00726    return 0;
00727 }
00728 
00729 /* 
00730 * Load the configuration from the configuration file
00731 */
00732 
00733 static int load_config(void)
00734 {
00735    struct ast_config *cfg;
00736    const char *p;
00737 
00738    /* Read in the config file */
00739 
00740    cfg = ast_config_load(ALMRCV_CONFIG);
00741                                                                                                                                   
00742    if(!cfg){
00743    
00744       if(option_verbose >= 4)
00745          ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: No config file\n");
00746       return 0;
00747    }
00748    else{
00749 
00750       
00751       p = ast_variable_retrieve(cfg, "general", "eventcmd");
00752       
00753       if(p){
00754          ast_copy_string(event_app, p, sizeof(event_app));
00755          event_app[sizeof(event_app) - 1] = '\0';
00756       }
00757       
00758       p = ast_variable_retrieve(cfg, "general", "loudness");
00759       if(p){
00760          toneloudness = atoi(p);
00761          if(toneloudness < 100)
00762             toneloudness = 100;
00763          if(toneloudness > 8192)
00764             toneloudness = 8192;
00765       }
00766       p = ast_variable_retrieve(cfg, "general", "fdtimeout");
00767       if(p){
00768          fdtimeout = atoi(p);
00769          if(fdtimeout < 1000)
00770             fdtimeout = 1000;
00771          if(fdtimeout > 10000)
00772             fdtimeout = 10000;   
00773       }
00774       
00775       p = ast_variable_retrieve(cfg, "general", "sdtimeout");
00776       if(p){
00777          sdtimeout = atoi(p);
00778          if(sdtimeout < 110)
00779             sdtimeout = 110;
00780          if(sdtimeout > 4000)
00781             sdtimeout = 4000;       
00782 
00783       }
00784       
00785       p = ast_variable_retrieve(cfg, "general", "logindividualevents");
00786       if(p){
00787          log_individual_events = ast_true(p);
00788 
00789       }
00790       
00791       p = ast_variable_retrieve(cfg, "general", "eventspooldir");
00792          
00793       if(p){
00794          ast_copy_string(event_spool_dir, p, sizeof(event_spool_dir));
00795          event_spool_dir[sizeof(event_spool_dir) - 1] = '\0';
00796       }
00797       
00798       p = ast_variable_retrieve(cfg, "general", "timestampformat");
00799          
00800       if(p){
00801          ast_copy_string(time_stamp_format, p, sizeof(time_stamp_format));
00802          time_stamp_format[sizeof(time_stamp_format) - 1] = '\0';
00803       }
00804 
00805       p = ast_variable_retrieve(cfg, "general", "db-family");
00806                                                                                                                                             
00807       if(p){
00808          ast_copy_string(db_family, p, sizeof(db_family));
00809          db_family[sizeof(db_family) - 1] = '\0';
00810       }
00811       ast_config_destroy(cfg);
00812    }
00813    return 1;
00814 
00815 }
00816 
00817 /*
00818 * These functions are required to implement an Asterisk App.
00819 */
00820 
00821 
00822 static int unload_module(void)
00823 {
00824    int res;
00825 
00826    res = ast_unregister_application(app);
00827 
00828    ast_module_user_hangup_all();
00829 
00830    return res;
00831 }
00832 
00833 static int load_module(void)
00834 {
00835    if(load_config())
00836       return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
00837    else
00838       return AST_MODULE_LOAD_DECLINE;
00839 }
00840 
00841 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Alarm Receiver for Asterisk");

Generated on Sat Aug 6 00:39:19 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7