12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001 |
- #include "asterisk.h"
- ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
- #include <math.h>
- #include <sys/wait.h>
- #include <sys/time.h>
- #include "asterisk/lock.h"
- #include "asterisk/file.h"
- #include "asterisk/channel.h"
- #include "asterisk/pbx.h"
- #include "asterisk/module.h"
- #include "asterisk/translate.h"
- #include "asterisk/app.h"
- #include "asterisk/dsp.h"
- #include "asterisk/config.h"
- #include "asterisk/localtime.h"
- #include "asterisk/callerid.h"
- #include "asterisk/astdb.h"
- #include "asterisk/utils.h"
- #include "asterisk/indications.h"
- #define ALMRCV_CONFIG "alarmreceiver.conf"
- #define UNKNOWN_FORMAT "UNKNOWN_FORMAT"
- #define ADEMCO_CONTACT_ID "ADEMCO_CONTACT_ID"
- #define ADEMCO_EXPRESS_4_1 "ADEMCO_EXPRESS_4_1"
- #define ADEMCO_EXPRESS_4_2 "ADEMCO_EXPRESS_4_2"
- #define ADEMCO_HIGH_SPEED "ADEMCO_HIGH_SPEED"
- #define ADEMCO_SUPER_FAST "ADEMCO_SUPER_FAST"
- #define ADEMCO_MSG_TYPE_1 "18"
- #define ADEMCO_MSG_TYPE_2 "98"
- #define ADEMCO_MSG_TYPE_3 "17"
- #define ADEMCO_MSG_TYPE_4 "27"
- #define ADEMCO_MSG_TYPE_5 "55"
- #define ADEMCO_MSG_TYPE_6 "56"
- #define ADEMCO_AUDIO_CALL_NEXT "606"
- struct {
- char digit;
- char weight;
- } digits_mapping[] = { {'0', 10}, {'1', 1} , {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5},
- {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'*', 11}, {'#', 12},
- {'A', 13}, {'B', 14}, {'C', 15} };
- struct event_node{
- char data[17];
- struct event_node *next;
- };
- typedef struct event_node event_node_t;
- struct timeval call_start_time;
- static const char app[] = "AlarmReceiver";
- static int fdtimeout = 2000;
- static int sdtimeout = 200;
- static int answait = 1250;
- static int toneloudness = 4096;
- static int log_individual_events = 0;
- static int no_group_meta = 0;
- static char event_spool_dir[128] = {'\0'};
- static char event_app[128] = {'\0'};
- static char db_family[128] = {'\0'};
- static char time_stamp_format[128] = {"%a %b %d, %Y @ %H:%M:%S %Z"};
- static char event_file[14] = "/event-XXXXXX";
- static void database_increment(char *key)
- {
- unsigned v;
- char value[16];
- if (ast_strlen_zero(db_family)) {
- return;
- }
- if (ast_db_get(db_family, key, value, sizeof(value) - 1)) {
- ast_verb(4, "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
-
- ast_db_put(db_family, key, "1");
- return;
- }
- sscanf(value, "%30u", &v);
- v++;
- ast_verb(4, "AlarmReceiver: New value for %s: %u\n", key, v);
- snprintf(value, sizeof(value), "%u", v);
- if (ast_db_put(db_family, key, value)) {
- ast_verb(4, "AlarmReceiver: database_increment write error\n");
- }
- return;
- }
- static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int buf_size, int expected, int *received)
- {
- int rtn = 0;
- int r;
- struct ast_frame *f;
- struct timeval lastdigittime;
- lastdigittime = ast_tvnow();
- while (*received < expected && *received < buf_size - 1) {
-
- if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((*received > 0) ? sdtimeout : fdtimeout)) {
- ast_verb(4, "AlarmReceiver: DTMF Digit Timeout on %s\n", ast_channel_name(chan));
- ast_debug(1, "AlarmReceiver: DTMF timeout on chan %s\n", ast_channel_name(chan));
- rtn = 1;
- break;
- }
- if ((r = ast_waitfor(chan, -1)) < 0) {
- ast_debug(1, "Waitfor returned %d\n", r);
- continue;
- }
- if ((f = ast_read(chan)) == NULL) {
- rtn = -1;
- break;
- }
-
- if ((f->frametype == AST_FRAME_CONTROL)
- && (f->subclass.integer == AST_CONTROL_HANGUP)) {
- if (f->data.uint32) {
- ast_channel_hangupcause_set(chan, f->data.uint32);
- }
- ast_frfree(f);
- rtn = -1;
- break;
- }
-
- if (f->frametype != AST_FRAME_DTMF) {
- ast_frfree(f);
- continue;
- }
-
- digit_string[(*received)++] = f->subclass.integer;
- ast_frfree(f);
- lastdigittime = ast_tvnow();
- }
-
- digit_string[*received] = '\0';
- return rtn;
- }
- static int write_metadata(FILE *logfile, char *signalling_type, struct ast_channel *chan, int no_checksum)
- {
- struct timeval t;
- struct ast_tm now;
- char *cl;
- char *cn;
- char workstring[80];
- char timestamp[80];
-
- ast_copy_string(workstring,
- S_COR(ast_channel_caller(chan)->id.number.valid,
- ast_channel_caller(chan)->id.number.str, ""), sizeof(workstring));
- ast_shrink_phone_number(workstring);
- if (ast_strlen_zero(workstring)) {
- cl = "<unknown>";
- } else {
- cl = workstring;
- }
- cn = S_COR(ast_channel_caller(chan)->id.name.valid,
- ast_channel_caller(chan)->id.name.str, "<unknown>");
-
- t = ast_tvnow();
- ast_localtime(&t, &now, NULL);
-
- ast_strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
- if (no_group_meta && fprintf(logfile, "PROTOCOL=%s\n"
- "CHECKSUM=%s\n"
- "CALLINGFROM=%s\n"
- "CALLERNAME=%s\n"
- "TIMESTAMP=%s\n\n",
- signalling_type, (!no_checksum) ? "yes" : "no", cl, cn, timestamp) > -1) {
- return 0;
- } else if (fprintf(logfile, "\n\n[metadata]\n\n"
- "PROTOCOL=%s\n"
- "CHECKSUM=%s\n"
- "CALLINGFROM=%s\n"
- "CALLERNAME=%s\n"
- "TIMESTAMP=%s\n\n"
- "[events]\n\n",
- signalling_type, (!no_checksum) ? "yes" : "no", cl, cn, timestamp) > -1) {
- return 0;
- }
- ast_verb(3, "AlarmReceiver: can't write metadata\n");
- ast_debug(1, "AlarmReceiver: can't write metadata\n");
- return -1;
- }
- static int write_event(FILE *logfile, event_node_t *event)
- {
- if (fprintf(logfile, "%s%s\n", no_group_meta ? "event=" : "", event->data) < 0) {
- return -1;
- }
- return 0;
- }
- static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event, int no_checksum)
- {
- char workstring[sizeof(event_spool_dir) + sizeof(event_file)] = "";
- int fd;
- FILE *logfile;
- event_node_t *elp = event;
- if (!ast_strlen_zero(event_spool_dir)) {
-
- ast_copy_string(workstring, event_spool_dir, sizeof(workstring));
- strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
-
- fd = mkstemp(workstring);
- if (fd == -1) {
- ast_verb(3, "AlarmReceiver: can't make temporary file\n");
- ast_debug(1, "AlarmReceiver: can't make temporary file\n");
- return -1;
- }
- if ((logfile = fdopen(fd, "w")) == NULL) {
- return -1;
- }
-
- if (write_metadata(logfile, signalling_type, chan, no_checksum)) {
- fflush(logfile);
- fclose(logfile);
- return -1;
- }
- while ((elp != NULL) && (write_event(logfile, elp) == 0)) {
- elp = elp->next;
- }
- fflush(logfile);
- fclose(logfile);
- }
- return 0;
- }
- static int ademco_verify_checksum(char *event, int expected)
- {
- int checksum = 0;
- int i, j;
- for (j = 0; j < expected; j++) {
- for (i = 0; i < ARRAY_LEN(digits_mapping); i++) {
- if (digits_mapping[i].digit == event[j]) {
- break;
- }
- }
- if (i >= ARRAY_LEN(digits_mapping)) {
- ast_verb(2, "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
- return -1;
- }
- checksum += digits_mapping[i].weight;
- }
-
- if (!(checksum % 15)) {
- return 0;
- }
- return -1;
- }
- static int send_tone_burst(struct ast_channel *chan, const char *tone_freq, int tone_duration, int delay)
- {
- if (delay && ast_safe_sleep(chan, delay)) {
- return -1;
- }
- if (ast_playtones_start(chan, toneloudness, tone_freq, 0)) {
- return -1;
- }
- if (ast_safe_sleep(chan, tone_duration)) {
- return -1;
- }
- ast_playtones_stop(chan);
- return 0;
- }
- static int ademco_check_valid(char *signalling_type, char *event)
- {
- if (!strcmp(signalling_type, UNKNOWN_FORMAT)) {
- return 1;
- }
- if (!strcmp(signalling_type, ADEMCO_CONTACT_ID)
- && strncmp(event + 4, ADEMCO_MSG_TYPE_1, 2)
- && strncmp(event + 4, ADEMCO_MSG_TYPE_2, 2)) {
- return -1;
- }
- if (!strcmp(signalling_type, ADEMCO_EXPRESS_4_1) && strncmp(event + 4, ADEMCO_MSG_TYPE_3, 2)) {
- return -1;
- }
- if (!strcmp(signalling_type, ADEMCO_EXPRESS_4_2) && strncmp(event + 4, ADEMCO_MSG_TYPE_4, 2)) {
- return -1;
- }
- if (!strcmp(signalling_type, ADEMCO_HIGH_SPEED) && strncmp(event + 4, ADEMCO_MSG_TYPE_5, 2)) {
- return -1;
- }
- if (!strcmp(signalling_type, ADEMCO_SUPER_FAST) && strncmp(event + 4, ADEMCO_MSG_TYPE_6, 2)) {
- return -1;
- }
- return 0;
- }
- static int ademco_detect_format(char *signalling_type, char *event, int *no_checksum)
- {
- int res = 16;
- if (!strncmp(event + 4, ADEMCO_MSG_TYPE_1, 2)
- || !strncmp(event + 4, ADEMCO_MSG_TYPE_2, 2)) {
- sprintf(signalling_type, "%s", ADEMCO_CONTACT_ID);
- }
- if (!strncmp(event + 4, ADEMCO_MSG_TYPE_3, 2)) {
- sprintf(signalling_type, "%s", ADEMCO_EXPRESS_4_1);
- res = 8;
- }
- if (!strncmp(event + 4, ADEMCO_MSG_TYPE_4, 2)) {
- sprintf(signalling_type, "%s", ADEMCO_EXPRESS_4_2);
- res = 9;
- }
- if (!strncmp(event + 4, ADEMCO_MSG_TYPE_5, 2)) {
- sprintf(signalling_type, "%s", ADEMCO_HIGH_SPEED);
- }
- if (!strncmp(event + 4, ADEMCO_MSG_TYPE_6, 2)) {
- sprintf(signalling_type, "%s", ADEMCO_SUPER_FAST);
- *no_checksum = 1;
- res = 15;
- }
- if (strcmp(signalling_type, UNKNOWN_FORMAT)) {
- ast_verb(4, "AlarmMonitoring: Detected format %s.\n", signalling_type);
- ast_debug(1, "AlarmMonitoring: Autodetected format %s.\n", signalling_type);
- }
- return res;
- }
- static int receive_ademco_event(struct ast_channel *chan, event_node_t **ehead, char *signalling_type, int *no_checksum)
- {
- int res = 0;
- const char *limit;
- char event[17];
- event_node_t *enew, *elp;
- int got_some_digits = 0;
- int events_received = 0;
- int ack_retries = 0;
- int limit_retries = 0;
- int expected_length = sizeof(event) - 1;
- database_increment("calls-received");
-
- ast_verb(4, "AlarmReceiver: Waiting for first event from panel...\n");
- while (res >= 0) {
- int digits_received = 0;
- res = 0;
- if (log_individual_events) {
- sprintf(signalling_type, "%s", UNKNOWN_FORMAT);
- expected_length = 16;
- *no_checksum = 0;
- }
- if (got_some_digits == 0) {
-
- ast_verb(4, "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
- res = send_tone_burst(chan, "1400", 100, 0);
- if (!res) {
- ast_verb(4, "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
- res = send_tone_burst(chan, "2300", 100, 100);
- }
- }
- if (res) {
- return -1;
- }
- res = receive_dtmf_digits(chan, event, sizeof(event), expected_length, &digits_received);
- if (res < 0) {
- if (events_received == 0) {
-
- database_increment("no-events-received");
- ast_verb(4, "AlarmReceiver: No events received!\n");
- } else {
- if (ack_retries) {
- database_increment("ack-retries");
- ast_verb(4, "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
- }
- }
- ast_verb(4, "AlarmReceiver: App exiting...\n");
- break;
- }
- if (!strcmp(signalling_type, UNKNOWN_FORMAT) && digits_received > 5) {
- expected_length = ademco_detect_format(signalling_type, event, no_checksum);
- if (res > 0) {
- if (digits_received == expected_length) {
- res = limit_retries = 0;
- } else if (digits_received == expected_length - 1
- && (!strcmp(signalling_type, ADEMCO_EXPRESS_4_2)
- || !strcmp(signalling_type, ADEMCO_EXPRESS_4_1))) {
-
- res = limit_retries = 0;
- expected_length--;
- *no_checksum = 1;
- ast_verb(4, "AlarmMonitoring: Skipping checksum for format %s.\n", signalling_type);
- ast_debug(1, "AlarmMonitoring: Skipping checksum for format %s.\n", signalling_type);
- }
- }
- }
- ast_channel_lock(chan);
- limit = pbx_builtin_getvar_helper(chan, "ALARMRECEIVER_CALL_LIMIT");
- if (!ast_strlen_zero(limit)) {
- if (ast_tvdiff_ms(ast_tvnow(), call_start_time) > atoi(limit)) {
- ast_channel_unlock(chan);
- return -1;
- }
- }
- limit = pbx_builtin_getvar_helper(chan, "ALARMRECEIVER_RETRIES_LIMIT");
- ast_channel_unlock(chan);
- if (!ast_strlen_zero(limit)) {
- if (limit_retries + 1 >= atoi(limit)) {
- return -1;
- }
- }
- if (res) {
-
- ast_verb(2, "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
- limit_retries++;
- if (!events_received && strcmp(signalling_type, UNKNOWN_FORMAT))
- {
- sprintf(signalling_type, "%s", UNKNOWN_FORMAT);
- expected_length = sizeof(event) - 1;
- }
- if (!got_some_digits) {
- got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0;
- ack_retries++;
- }
- continue;
- }
- got_some_digits = 1;
- ast_verb(2, "AlarmReceiver: Received Event %s\n", event);
- ast_debug(1, "AlarmReceiver: Received event: %s\n", event);
-
- if (!(*no_checksum) && ademco_verify_checksum(event, expected_length)) {
- database_increment("checksum-errors");
- ast_verb(2, "AlarmReceiver: Nonzero checksum\n");
- ast_debug(1, "AlarmReceiver: Nonzero checksum\n");
- continue;
- }
-
- if (ademco_check_valid(signalling_type, event)) {
- database_increment("format-errors");
- ast_verb(2, "AlarmReceiver: Wrong message type\n");
- ast_debug(1, "AlarmReceiver: Wrong message type\n");
- continue;
- }
- events_received++;
-
- if (!(enew = ast_calloc(1, sizeof(*enew)))) {
- return -1;
- }
- enew->next = NULL;
- ast_copy_string(enew->data, event, sizeof(enew->data));
-
- if (*ehead == NULL) {
- *ehead = enew;
- } else {
- for (elp = *ehead; elp->next != NULL; elp = elp->next) {
- ;
- }
- elp->next = enew;
- }
-
- if (log_individual_events && log_events(chan, signalling_type, enew, *no_checksum)) {
- return -1;
- }
-
- if (send_tone_burst(chan, "1400", 900, 200)) {
- return -1;
- }
-
- if (!strcmp(signalling_type, ADEMCO_CONTACT_ID)
- && !strncmp(event + 7, ADEMCO_AUDIO_CALL_NEXT, 3)) {
- ast_verb(4, "AlarmReceiver: App exiting... Audio call next!\n");
- return 0;
- }
- }
- return res;
- }
- static int alarmreceiver_exec(struct ast_channel *chan, const char *data)
- {
- int res = 0;
- int no_checksum = 0;
- event_node_t *elp, *efree;
- char signalling_type[64] = "";
- event_node_t *event_head = NULL;
- if (ast_channel_writeformat(chan)->id != AST_FORMAT_ALAW
- && ast_channel_writeformat(chan)->id != AST_FORMAT_ULAW) {
- ast_verb(4, "AlarmReceiver: Setting write format to Mu-law\n");
- if (ast_set_write_format_by_id(chan,AST_FORMAT_ULAW)) {
- ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",ast_channel_name(chan));
- return -1;
- }
- }
- if (ast_channel_readformat(chan)->id != AST_FORMAT_ALAW
- && ast_channel_readformat(chan)->id != AST_FORMAT_ULAW) {
- ast_verb(4, "AlarmReceiver: Setting read format to Mu-law\n");
- if (ast_set_read_format_by_id(chan,AST_FORMAT_ULAW)) {
- ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",ast_channel_name(chan));
- return -1;
- }
- }
-
- ast_copy_string(signalling_type, UNKNOWN_FORMAT, sizeof(signalling_type));
- call_start_time = ast_tvnow();
-
- if (ast_channel_state(chan) != AST_STATE_UP) {
- ast_verb(4, "AlarmReceiver: Answering channel\n");
- if (ast_answer(chan)) {
- return -1;
- }
- }
-
- ast_verb(4, "AlarmReceiver: Waiting for connection to stabilize\n");
- if (ast_safe_sleep(chan, answait)) {
- return -1;
- }
-
- receive_ademco_event(chan, &event_head, signalling_type, &no_checksum);
-
- if (!log_individual_events) {
- res = log_events(chan, signalling_type, event_head, no_checksum);
- }
-
- if ((!res) && (!ast_strlen_zero(event_app)) && (event_head)) {
- ast_debug(1,"Alarmreceiver: executing: %s\n", event_app);
- ast_safe_system(event_app);
- }
-
- for (elp = event_head; (elp != NULL);) {
- efree = elp;
- elp = elp->next;
- ast_free(efree);
- }
- return 0;
- }
- static int load_config(int reload)
- {
- struct ast_config *cfg;
- const char *value;
- struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
-
- cfg = ast_config_load(ALMRCV_CONFIG, config_flags);
- if (!cfg) {
- ast_verb(4, "AlarmReceiver: No config file\n");
- return 0;
- } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
- return 1;
- } else if (cfg == CONFIG_STATUS_FILEINVALID) {
- ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n",
- ALMRCV_CONFIG);
- return 0;
- }
- if ((value = ast_variable_retrieve(cfg, "general", "eventcmd")) != NULL) {
- ast_copy_string(event_app, value, sizeof(event_app));
- }
- if ((value = ast_variable_retrieve(cfg, "general", "loudness")) != NULL) {
- toneloudness = atoi(value);
- if (toneloudness < 100) {
- toneloudness = 100;
- } else if (toneloudness > 8192) {
- toneloudness = 8192;
- }
- }
- if ((value = ast_variable_retrieve(cfg, "general", "fdtimeout")) != NULL) {
- fdtimeout = atoi(value);
- if (fdtimeout < 1000) {
- fdtimeout = 1000;
- } else if (fdtimeout > 10000) {
- fdtimeout = 10000;
- }
- }
- if ((value = ast_variable_retrieve(cfg, "general", "sdtimeout")) != NULL) {
- sdtimeout = atoi(value);
- if (sdtimeout < 110) {
- sdtimeout = 110;
- } else if (sdtimeout > 4000) {
- sdtimeout = 4000;
- }
- }
- if ((value = ast_variable_retrieve(cfg, "general", "answait")) != NULL) {
- answait = atoi(value);
- if (answait < 500) {
- answait = 500;
- } else if (answait > 10000) {
- answait = 10000;
- }
- }
- if ((value = ast_variable_retrieve(cfg, "general", "no_group_meta")) != NULL) {
- no_group_meta = ast_true(value);
- }
- if ((value = ast_variable_retrieve(cfg, "general", "logindividualevents")) != NULL) {
- log_individual_events = ast_true(value);
- }
- if ((value = ast_variable_retrieve(cfg, "general", "eventspooldir")) != NULL) {
- ast_copy_string(event_spool_dir, value, sizeof(event_spool_dir));
- }
- if ((value = ast_variable_retrieve(cfg, "general", "timestampformat")) != NULL) {
- ast_copy_string(time_stamp_format, value, sizeof(time_stamp_format));
- }
- if ((value = ast_variable_retrieve(cfg, "general", "db-family")) != NULL) {
- ast_copy_string(db_family, value, sizeof(db_family));
- }
- ast_config_destroy(cfg);
- return 1;
- }
- static int unload_module(void)
- {
- return ast_unregister_application(app);
- }
- static int load_module(void)
- {
- if (load_config(0)) {
- if (ast_register_application_xml(app, alarmreceiver_exec)) {
- return AST_MODULE_LOAD_FAILURE;
- }
- return AST_MODULE_LOAD_SUCCESS;
- }
- return AST_MODULE_LOAD_DECLINE;
- }
- static int reload(void)
- {
- if (load_config(1)) {
- return AST_MODULE_LOAD_SUCCESS;
- }
- return AST_MODULE_LOAD_DECLINE;
- }
- AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Alarm Receiver for Asterisk",
- .load = load_module,
- .unload = unload_module,
- .reload = reload,
- );
|