From 6cef720265d690adb0270c833a0b05a515bad810 Mon Sep 17 00:00:00 2001 From: matteo Date: Fri, 7 Mar 2003 06:00:13 +0000 Subject: Fri Mar 7 07:00:00 CET 2003 git-svn-id: http://svn.digium.com/svn/asterisk/trunk@634 f38db490-d61c-443f-a65b-d21fe96a405b --- CREDITS | 1 + apps/Makefile | 2 +- apps/app_db.c | 312 +++++++++++++++++++++++++++++++++++++++++++++++++ apps/app_disa.c | 11 +- apps/app_voicemail.c | 2 +- channels/chan_mgcp.c | 7 ++ channels/chan_sip.c | 2 + channels/chan_zap.c | 1 + codecs/codec_gsm.c | 52 +++++++-- formats/msgsm.h | 6 +- include/asterisk/rtp.h | 2 + pbx.c | 35 +++++- rtp.c | 11 ++ 13 files changed, 419 insertions(+), 25 deletions(-) create mode 100755 apps/app_db.c diff --git a/CREDITS b/CREDITS index a520bc6a0..67e780779 100755 --- a/CREDITS +++ b/CREDITS @@ -32,6 +32,7 @@ James Golovch - Various contributions You can find him and asterisk-perl at http://asterisk.gnuinter.net Steven Critchfield - Seek and Trunc functions for playback and recording critch@basesys.com +Jefferson Noxon - app_lookupcidname, app_db, and various other contributions === OTHER SOURCE CODE IN ASTERISK === diff --git a/apps/Makefile b/apps/Makefile index de77cfd30..48087f76c 100755 --- a/apps/Makefile +++ b/apps/Makefile @@ -19,7 +19,7 @@ APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_intercom. app_queue.so app_senddtmf.so app_parkandannounce.so app_striplsd.so \ app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \ app_authenticate.so app_softhangup.so app_lookupblacklist.so \ - app_waitforring.so app_privacy.so + app_waitforring.so app_privacy.so app_db.so #APPS+=app_sql_postgres.so #APPS+=app_sql_odbc.so diff --git a/apps/app_db.c b/apps/app_db.c new file mode 100755 index 000000000..1ca43e869 --- /dev/null +++ b/apps/app_db.c @@ -0,0 +1,312 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Database access functions + * + * Copyright (C) 1999, Mark Spencer + * Copyright (C) 2003, Jefferson Noxon + * + * Mark Spencer + * Jefferson Noxon + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static char *tdesc = "Database access functions for Asterisk extension logic"; + +static char *g_descrip = + " DBget(varname=family/key): Retrieves a value from the Asterisk\n" + "database and stores it in the given variable. Always returns 0. If the\n" + "requested key is not found, jumps to priority n+101 if available.\n"; + +static char *p_descrip = + " DBput(family/key=value): Stores the given value in the Asterisk\n" + "database. Always returns 0.\n"; + +static char *d_descrip = + " DBdel(family/key): Deletes a key from the Asterisk database. Always\n" + "returns 0.\n"; + +static char *dt_descrip = + " DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n" + "database. Always returns 0.\n"; + +static char *g_app = "DBget"; +static char *p_app = "DBput"; +static char *d_app = "DBdel"; +static char *dt_app = "DBdeltree"; + +static char *g_synopsis = "Retrieve a value from the database"; +static char *p_synopsis = "Store a value in the database"; +static char *d_synopsis = "Delete a key from the database"; +static char *dt_synopsis = "Delete a family or keytree from the database"; + +STANDARD_LOCAL_USER; + +LOCAL_USER_DECL; + + +static int +deltree_exec (struct ast_channel *chan, void *data) +{ + int arglen; + char *argv, *family, *keytree; + + arglen = strlen (data); + argv = alloca (arglen + 1); + if (!argv) /* Why would this fail? */ + { + ast_log (LOG_DEBUG, "Memory allocation failed\n"); + return 0; + } + memcpy (argv, data, arglen + 1); + + if (strchr (argv, '/')) + { + family = strsep (&argv, "/"); + keytree = strsep (&argv, "\0"); + if (!family || !keytree) + { + ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n"); + return 0; + } + if (!strlen (keytree)) + keytree = 0; + } + else + { + family = argv; + keytree = 0; + } + + if (option_verbose > 2) + if (keytree) + ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n", + family, keytree); + else + ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family); + + if (ast_db_deltree (family, keytree)) + { + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 + "DBdeltree: Error deleting key from database.\n"); + } + + return 0; +} + + +static int +del_exec (struct ast_channel *chan, void *data) +{ + int arglen; + char *argv, *family, *key; + + arglen = strlen (data); + argv = alloca (arglen + 1); + if (!argv) /* Why would this fail? */ + { + ast_log (LOG_DEBUG, "Memory allocation failed\n"); + return 0; + } + memcpy (argv, data, arglen + 1); + + if (strchr (argv, '/')) + { + family = strsep (&argv, "/"); + key = strsep (&argv, "\0"); + if (!family || !key) + { + ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n"); + return 0; + } + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 + "DBdel: family=%s, key=%s\n", family, key); + if (ast_db_del (family, key)) + { + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 + "DBdel: Error deleting key from database.\n"); + } + } + else + { + ast_log (LOG_DEBUG, "Ignoring, no parameters\n"); + } + + return 0; +} + +static int +put_exec (struct ast_channel *chan, void *data) +{ + int arglen; + char *argv, *value, *family, *key; + + arglen = strlen (data); + argv = alloca (arglen + 1); + if (!argv) /* Why would this fail? */ + { + ast_log (LOG_DEBUG, "Memory allocation failed\n"); + return 0; + } + memcpy (argv, data, arglen + 1); + + if (strchr (argv, '/') && strchr (argv, '=')) + { + family = strsep (&argv, "/"); + key = strsep (&argv, "="); + value = strsep (&argv, "\0"); + if (!value || !family || !key) + { + ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n"); + return 0; + } + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 + "DBput: family=%s, key=%s, value=%s\n", family, key, + value); + if (ast_db_put (family, key, value)) + { + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 + "DBput: Error writing value to database.\n"); + } + + } + else + { + ast_log (LOG_DEBUG, "Ignoring, no parameters\n"); + } + + return 0; +} + +static int +get_exec (struct ast_channel *chan, void *data) +{ + int arglen; + char *argv, *varname, *family, *key; + char dbresult[256]; + + arglen = strlen (data); + argv = alloca (arglen + 1); + if (!argv) /* Why would this fail? */ + { + ast_log (LOG_DEBUG, "Memory allocation failed\n"); + return 0; + } + memcpy (argv, data, arglen + 1); + + if (strchr (argv, '=') && strchr (argv, '/')) + { + varname = strsep (&argv, "="); + family = strsep (&argv, "/"); + key = strsep (&argv, "\0"); + if (!varname || !family || !key) + { + ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n"); + return 0; + } + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 + "DBget: varname=%s, family=%s, key=%s\n", varname, + family, key); + if (!ast_db_get (family, key, dbresult, sizeof (dbresult) - 1)) + { + pbx_builtin_setvar_helper (chan, varname, dbresult); + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 + "DBget: set variable %s to %s\n", varname, dbresult); + } + else + { + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 + "DBget: Value not found in database.\n"); + /* Send the call to n+101 priority, where n is the current priority */ + if (ast_exists_extension + (chan, chan->context, chan->exten, chan->priority + 101, + chan->callerid)) + chan->priority += 100; + } + + } + else + { + ast_log (LOG_DEBUG, "Ignoring, no parameters\n"); + } + + return 0; +} + +int +unload_module (void) +{ + int retval; + + STANDARD_HANGUP_LOCALUSERS; + retval = ast_unregister_application (dt_app); + retval |= ast_unregister_application (d_app); + retval |= ast_unregister_application (p_app); + retval |= ast_unregister_application (g_app); + + return retval; +} + +int +load_module (void) +{ + int retval; + + retval = ast_register_application (g_app, get_exec, g_synopsis, g_descrip); + if (!retval) + retval = + ast_register_application (p_app, put_exec, p_synopsis, p_descrip); + if (!retval) + retval = + ast_register_application (d_app, del_exec, d_synopsis, d_descrip); + if (!retval) + retval = + ast_register_application (dt_app, deltree_exec, dt_synopsis, + dt_descrip); + + return retval; +} + +char * +description (void) +{ + return tdesc; +} + +int +usecount (void) +{ + int res; + STANDARD_USECOUNT (res); + return res; +} + +char * +key () +{ + return ASTERISK_GPL_KEY; +} diff --git a/apps/app_disa.c b/apps/app_disa.c index 89d956deb..978336936 100755 --- a/apps/app_disa.c +++ b/apps/app_disa.c @@ -251,7 +251,7 @@ static int disa_exec(struct ast_channel *chan, void *data) tmp[0] = 0; while(fgets(tmp,sizeof(tmp) - 1,fp)) { - char *stringp=NULL; + char *stringp=NULL,*stringp2; if (!tmp[0]) continue; if (tmp[strlen(tmp) - 1] == '\n') tmp[strlen(tmp) - 1] = 0; @@ -261,9 +261,12 @@ static int disa_exec(struct ast_channel *chan, void *data) if (tmp[0] == ';') continue; stringp=tmp; strsep(&stringp, "|"); - /* save 2nd arg as clid */ - ourcallerid = arg2; - ourcontext = strsep(&stringp, "|"); + stringp2=strsep(&stringp, "|"); + if (stringp2) { + ourcontext=stringp2; + stringp2=strsep(&stringp, "|"); + if (stringp2) ourcallerid=stringp2; + } /* password must be in valid format (numeric) */ if (sscanf(tmp,"%d",&j) < 1) continue; /* if we got it */ diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 191b21a2c..13ddcd8cb 100755 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -1583,7 +1583,7 @@ static int play_and_record(struct ast_channel *chan, char *playfile, char *recor if (maxtime) time(&start); for (x=0;xrtp = ast_rtp_new(NULL, NULL); if (p->rtp && p->owner) p->owner->fds[0] = ast_rtp_fd(p->rtp); + if (p->rtp) + ast_rtp_setnat(p->rtp, p->nat); #if 0 ast_rtp_set_callback(p->rtp, rtpready); ast_rtp_set_data(p->rtp, p); @@ -1445,6 +1448,7 @@ struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) char context[AST_MAX_EXTENSION] = "default"; char language[80] = ""; char callerid[AST_MAX_EXTENSION] = ""; + int nat = 0; gw = malloc(sizeof(struct mgcp_gateway)); if (gw) { @@ -1463,6 +1467,8 @@ struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) gw->addr.sin_port = htons(atoi(v->value)); } else if (!strcasecmp(v->name, "context")) { strncpy(context, v->value, sizeof(context) - 1); + } else if (!strcasecmp(v->name, "nat")) { + nat = ast_true(v->value); } else if (!strcasecmp(v->name, "callerid")) { if (!strcasecmp(v->value, "asreceived")) strcpy(callerid, ""); @@ -1482,6 +1488,7 @@ struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v) strncpy(e->language, language, sizeof(e->language) - 1); e->capability = capability; e->parent = gw; + e->nat = nat; strncpy(e->name, v->value, sizeof(e->name) - 1); if (!strcasecmp(v->name, "trunk")) e->type = TYPE_TRUNK; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 726218f0a..059709e5d 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2516,6 +2516,8 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha while(user) { if (!strcasecmp(user->name, of)) { p->nat = user->nat; + if (p->rtp) + ast_rtp_setnat(p->rtp, p->nat); if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, cmd, uri))) { strncpy(p->context, user->context, sizeof(p->context) - 1); if (strlen(user->callerid) && strlen(p->callerid)) diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 86548238a..4d308c3c4 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/codecs/codec_gsm.c b/codecs/codec_gsm.c index 42d70f432..68efbf92b 100755 --- a/codecs/codec_gsm.c +++ b/codecs/codec_gsm.c @@ -33,6 +33,7 @@ #include #include "gsm/inc/gsm.h" +#include "../formats/msgsm.h" /* Sample frame data */ #include "slin_gsm_ex.h" @@ -57,7 +58,7 @@ struct ast_translator_pvt { #define gsm_coder_pvt ast_translator_pvt -static struct ast_translator_pvt *gsm_new() +static struct ast_translator_pvt *gsm_new(void) { struct gsm_coder_pvt *tmp; tmp = malloc(sizeof(struct gsm_coder_pvt)); @@ -72,7 +73,7 @@ static struct ast_translator_pvt *gsm_new() return tmp; } -static struct ast_frame *lintogsm_sample() +static struct ast_frame *lintogsm_sample(void) { static struct ast_frame f; f.frametype = AST_FRAME_VOICE; @@ -87,7 +88,7 @@ static struct ast_frame *lintogsm_sample() return &f; } -static struct ast_frame *gsmtolin_sample() +static struct ast_frame *gsmtolin_sample(void) { static struct ast_frame f; f.frametype = AST_FRAME_VOICE; @@ -128,20 +129,47 @@ static int gsmtolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f) /* Assuming there's space left, decode into the current buffer at the tail location. Read in as many frames as there are */ int x; - if (f->datalen % 33) { - ast_log(LOG_WARNING, "Huh? A GSM frame that isn't a multiple of 33 bytes long from %s (%d)?\n", f->src, f->datalen); + unsigned char data[66]; + int msgsm=0; + + if ((f->datalen % 33) && (f->datalen % 65)) { + ast_log(LOG_WARNING, "Huh? A GSM frame that isn't a multiple of 33 or 65 bytes long from %s (%d)?\n", f->src, f->datalen); return -1; } - for (x=0;xdatalen;x+=33) { - if (tmp->tail + 160 < sizeof(tmp->buf)/2) { - if (gsm_decode(tmp->gsm, f->data + x, tmp->buf + tmp->tail)) { - ast_log(LOG_WARNING, "Invalid GSM data\n"); + + if (f->datalen % 65 == 0) + msgsm = 1; + + for (x=0;xdatalen;x+=(msgsm ? 65 : 33)) { + if (msgsm) { + /* Translate MSGSM format to Real GSM format before feeding in */ + conv65(f->data + x, data); + if (tmp->tail + 320 < sizeof(tmp->buf)/2) { + if (gsm_decode(tmp->gsm, data, tmp->buf + tmp->tail)) { + ast_log(LOG_WARNING, "Invalid GSM data (1)\n"); + return -1; + } + tmp->tail+=160; + if (gsm_decode(tmp->gsm, data + 33, tmp->buf + tmp->tail)) { + ast_log(LOG_WARNING, "Invalid GSM data (2)\n"); + return -1; + } + tmp->tail+=160; + } else { + ast_log(LOG_WARNING, "Out of (MS) buffer space\n"); return -1; } - tmp->tail+=160; } else { - ast_log(LOG_WARNING, "Out of buffer space\n"); - return -1; + if (tmp->tail + 160 < sizeof(tmp->buf)/2) { + if (gsm_decode(tmp->gsm, f->data + x, tmp->buf + tmp->tail)) { + ast_log(LOG_WARNING, "Invalid GSM data\n"); + return -1; + } + tmp->tail+=160; + } else { + ast_log(LOG_WARNING, "Out of buffer space\n"); + return -1; + } } } return 0; diff --git a/formats/msgsm.h b/formats/msgsm.h index 2513e72b1..de0464a8b 100755 --- a/formats/msgsm.h +++ b/formats/msgsm.h @@ -2,7 +2,9 @@ #define GSM_MAGIC 0xD +#ifndef GSM_H typedef unsigned char gsm_byte; +#endif typedef unsigned char wav_byte; typedef unsigned int uword; @@ -109,7 +111,7 @@ typedef unsigned int uword; xmc[51] = *c & 0x7; /* 33 */ \ } -static void conv66(gsm_byte * d, wav_byte * c) { +static inline void conv66(gsm_byte * d, wav_byte * c) { gsm_byte frame_chain; unsigned int sr; unsigned int LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; @@ -450,7 +452,7 @@ static void conv66(gsm_byte * d, wav_byte * c) { | (xmc[51] & 0x7); \ } -static void conv65( wav_byte * c, gsm_byte * d){ +static inline void conv65( wav_byte * c, gsm_byte * d){ unsigned int sr = 0; unsigned int frame_chain; diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h index 30639a5cd..d9530a7db 100755 --- a/include/asterisk/rtp.h +++ b/include/asterisk/rtp.h @@ -61,6 +61,8 @@ int ast_rtp_senddigit(struct ast_rtp *rtp, char digit); int ast_rtp_settos(struct ast_rtp *rtp, int tos); +void ast_rtp_setnat(struct ast_rtp *rtp, int nat); + int ast2rtp(int id); int rtp2ast(int id); diff --git a/pbx.c b/pbx.c index 9e9a3ecaf..a78a09d5d 100755 --- a/pbx.c +++ b/pbx.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "asterisk.h" /* @@ -1102,10 +1104,22 @@ int ast_pbx_run(struct ast_channel *c) if (option_debug) ast_log(LOG_DEBUG, "PBX_THREAD(%s)\n", c->name); else if (option_verbose > 1) { - if (c->callerid) - ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s' (%s)\n", c->name, c->callerid); - else - ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s'\n", c->name); + struct timeval tv; + struct tm tm; + FILE *LOG; + + gettimeofday(&tv,NULL); + localtime_r(&(tv.tv_sec),&tm); + LOG = fopen(AST_SPOOL_DIR "/call.log","a"); + + if (c->callerid) { + ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s' (%s) at %02d-%02d %02d:%02d\n", c->name, c->callerid, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min); + fprintf(LOG,"%04d-%02d-%02d %02d:%02d:%02d - %s - %s\n",tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, c->name, c->callerid); + } else { + ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s' at %02d-%02d %02d:%02d\n", c->name, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min); + fprintf(LOG,"%04d-%02d-%02d %02d:%02d:%02d - %s\n",tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, c->name); + } + fclose(LOG); } /* Start by trying whatever the channel is set to */ @@ -1156,10 +1170,18 @@ int ast_pbx_run(struct ast_channel *c) c->_softhangup =0; break; } + /* atimeout */ + if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { + break; + } goto out; } } - if (c->_softhangup) { + if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) { + strncpy(c->exten,"T",sizeof(c->exten) - 1); + /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ + c->whentohangup = 0; + } else if (c->_softhangup) { ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", c->exten, c->priority); goto out; @@ -1179,6 +1201,9 @@ int ast_pbx_run(struct ast_channel *c) c->name, c->exten, c->context); goto out; } + } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { + /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ + c->_softhangup = 0; } else { /* Done, wait for an extension */ if (digit) diff --git a/rtp.c b/rtp.c index 7dd6e997c..54b7e945b 100755 --- a/rtp.c +++ b/rtp.c @@ -50,6 +50,7 @@ struct ast_rtp { int lasttxformat; int lastrxformat; int dtmfcount; + int nat; struct sockaddr_in us; struct sockaddr_in them; struct timeval rxcore; @@ -114,6 +115,11 @@ void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback) rtp->callback = callback; } +void ast_rtp_setnat(struct ast_rtp *rtp, int nat) +{ + rtp->nat = nat; +} + static struct ast_frame *send_dtmf(struct ast_rtp *rtp) { ast_log(LOG_DEBUG, "Sending dtmf: %d (%c)\n", rtp->resp, rtp->resp); @@ -262,6 +268,7 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp) res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len); + rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); if (res < 0) { ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno)); @@ -273,6 +280,10 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp) ast_log(LOG_WARNING, "RTP Read too short\n"); return &null_frame; } + if (rtp->nat) { + /* Send to whoever sent to us */ + memcpy(&rtp->them, &sin, sizeof(rtp->them)); + } /* Get fields */ seqno = ntohl(rtpheader[0]); payloadtype = (seqno & 0x7f0000) >> 16; -- cgit v1.2.3