[Asterisk-Dev] app_disa2: Feedback requested

Eric Wieling eric at fnords.org
Sun Nov 2 03:53:12 MST 2003


I'm working on rewriting app_disa and would like some feedback on my
code.  I pretty much don't know what I'm doing, so any Asterisk specific
comments would be greatly appreciated.  I'll try attaching the source,
it's not all that big.  Yes, a fair number of features are not
implemented (mostly password and config file features), but I wanted to
see if I can get some feedback before I go much further with it.

--Eric

/*
 * Asterisk -- A telephony toolkit for Linux.
 *
 * DISA -- Direct Inward System Access Application  11/01/2003
 * 
 * Copyright (C) 2003, Eric Wieling
 *
 * Eric Wieling <eric at fnords.org>
 *
 * This program is free software, distributed under the terms of
 * the GNU General Public License
 */

/*
	Valid parameters are:
  		password=NUMERIC-PASSWORD|no-password
	  	context=CONTEXT
	  	mailbox=MAILBOX[@VOICEMAIL-CONTEXT]
	  	callerid="NAME" <NUMBER>
		accountcode=ACCOUNTCODE
	  	config=FILE

	Parameters may be abbreviated by using the first 4 characters of the
	parameter name.

	Parameters are seperated by a , (comma) or a | (pipe symbol).  At a
	minimum the password= or config= parameter must be specified.  To specify
	no password, use password=no-password.  The mailbox= and callerid= are
	the only parameters that may have empty values.  If any parameter (except
	mailbox= or callerid=) is specified, it must have a value.
	
	If the mailbox= parameter is used and the specified mailbox has new
	voicemail, it will be indicated by an interrupted (stutter) dialtone
	after the password is entered.

	Passwords should be terminated by a # (pound).  If the user does not dial
	# at the end of their password they will have to wait for DigitTimeout.
	
	If a config file is specified, no other parameters are
	allowed.  In the config file a # (pound) sign as the first
	character of the line indicates a comment.

	Examples:
		DISA2(password=no-password)
		DISA2(config=/etc/asterisk/disa.conf)
		DISA(password=1234,context=extensions,mailbox=2000)

*/

#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>

#include <asterisk/app.h>
#include <asterisk/indications.h>
#include <asterisk/options.h>
                                                                                                                              
static char *tdesc = "DISA (Direct Inward System Access) Application";

static char *app = "DISA2";

static char *synopsis = "DISA (Direct Inward System Access)";

static char *descrip = 
	"A description of this application has not (yet) been written.\n";

STANDARD_LOCAL_USER;

LOCAL_USER_DECL;

static int disa_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	int len = 0;
	char *cmdline = NULL;
	char *_strtok_ptr = NULL;
	char *tmp = NULL;
	char *password = NULL;
	char *mailbox = NULL;
	char *context = NULL;
	char *callerid = NULL;
	char *accountcode = NULL;
	char exten[AST_MAX_EXTENSION] = "";
	struct localuser *u;
	struct tone_zone_sound *ts;
  
   /* Parse our parameters */
	cmdline = (char *) strdup(data);
	tmp = (char *) strtok_r(cmdline, "=|", &_strtok_ptr);
	while (tmp != NULL) {
		if (strcmp("password", tmp) == 0) {
			tmp = (char *) strtok_r(NULL, "=|", &_strtok_ptr);
			if (tmp == NULL) {
				ast_log(LOG_NOTICE, "DISA2: Password parameter, but no password value!  Exiting!\n");
				return -1;
			} else {
				password = (char *) strdup(tmp);
			}
		} else if (strcmp("context", tmp) == 0) {
			tmp = (char *) strtok_r(NULL, "=|", &_strtok_ptr);
			if (tmp == NULL) {
				ast_log(LOG_NOTICE, "DISA2: Context parameter, but no context value!  Exiting!\n");
				return -1;
			} else {
				context = (char *) strdup(tmp);
			}
		} else if (strcmp("accountcode", tmp) == 0) {
			tmp = (char *) strtok_r(NULL, "=|", &_strtok_ptr);
			if (tmp == NULL) {
				ast_log(LOG_NOTICE, "DISA2: Account code parameter, but no account code value!  Exiting!\n");
				return -1;
			} else {
				accountcode = (char *) strdup(tmp);
			}
		} else if (strcmp("mailbox", tmp) == 0) {
			tmp = (char *) strtok_r(NULL, "=|", &_strtok_ptr);
			if (tmp == NULL) {
				mailbox = NULL;
			} else {
				mailbox = (char *) strdup(tmp);
			}
		} else if (strcmp("callerid", tmp) == 0) {
			tmp = (char *) strtok_r(NULL, "=|", &_strtok_ptr);
			if (tmp == NULL) {
				callerid = NULL;
			} else {
				callerid = (char *) strdup(tmp);
			}
		}
		tmp = (char *) strtok_r(NULL, "=|", &_strtok_ptr);
	}
	if (password == NULL) {
		ast_log(LOG_NOTICE, "DISA2: No password specified!  Exiting!.\n");
		return -1;
	}
	if (context == NULL) {
	  ast_log(LOG_NOTICE, "DISA2: No context specified, setting to \"disa\".\n");
	  context = "disa";
	}
	if (accountcode == NULL) {
	  accountcode = chan->accountcode;
	}
	  
	ast_log(LOG_DEBUG, "DISA2: context=%s, mailbox=%s, password=%s, accountcode=%s, callerid=%s", context, mailbox, password, accountcode, callerid);

	LOCAL_USER_ADD(u);
   if (chan->_state != AST_STATE_UP) {
		res = ast_answer(chan);
		if (res != 0) {
			LOCAL_USER_REMOVE(u);
			return -1;
		}
	}

	if (mailbox != NULL) {
		if (ast_app_has_voicemail(mailbox)) {
			ts = ast_get_indication_tone(chan->zone, "dialrecall");
		} else {
			ts = ast_get_indication_tone(chan->zone, "dial");
		}
	} else {	
		ts = ast_get_indication_tone(chan->zone, "dial");
	}
	
	if (ts && ts->data[0]) {
		res = ast_playtones_start(chan, 0, ts->data, 0);
	} else {
		res = ast_playtones_start(chan, 0, "dial", 0);
	}
	if (res) {
		ast_log(LOG_NOTICE,"Unable to start playtones\n");
		return res;
	}
                                 
	while(len < AST_MAX_EXTENSION-1) {
		res = ast_waitfordigit(chan, 10000);
		if (res < 0) {
			ast_log(LOG_NOTICE, "Channel hung up.\n");
			LOCAL_USER_REMOVE(u);                     
			return -1;
		}
		if (res == 0) {
			ast_log(LOG_NOTICE, "Timeout waiting for digits.\n");
			break;
		}
	   ast_log(LOG_NOTICE, "Got digit = %c\n", (char) res);
		exten[len++] = res;
		exten[len] = '\0';
	   if (ast_ignore_pattern(context, exten) == 0) {
		   ast_log(LOG_NOTICE, "Stoping dialtone.\n");
			ast_playtones_stop(chan);
		} else {
		   ast_log(LOG_NOTICE, "Continueing dialtone.\n");
			ts = ast_get_indication_tone(chan->zone, "dial");
			if (ts && ts->data[0]) {
				res = ast_playtones_start(chan, 0, ts->data, 0);
			} else {
				res = ast_playtones_start(chan, 0, "dial", 0);
			}
			if (res) {
				ast_log(LOG_NOTICE,"Unable to start playtones\n");
				return res;
			}
		}
		if (ast_matchmore_extension(chan, context, exten, 1, NULL) == 0) {
			ast_log(LOG_NOTICE,"Extension %s will not match any more digits\n", exten);
			break;
		}
	}

	if (ast_exists_extension(chan, context, exten, 1, chan->callerid)) {
		ast_log(LOG_NOTICE,"Extension %s exists.\n", exten);
	} else {
		ast_log(LOG_NOTICE,"Extension %s does not exist.\n", exten);
		pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
		strcpy(chan->exten,"i");
		chan->priority = 0;
	   LOCAL_USER_REMOVE(u);                     
		return 0;
	}
	
	strcpy(chan->exten,exten);
	strcpy(chan->context,context);
	strcpy(chan->accountcode,accountcode);
	chan->priority = 0;

   LOCAL_USER_REMOVE(u);                     
	return 0;
}

int unload_module(void)
{
	STANDARD_HANGUP_LOCALUSERS;
	return ast_unregister_application(app);
}

int load_module(void)
{
	return ast_register_application(app, disa_exec, synopsis, descrip);
}

char *description(void)
{
	return tdesc;
}

int usecount(void)
{
	int res;
	STANDARD_USECOUNT(res);
	return res;
}

char *key()
{
	return ASTERISK_GPL_KEY;
}


-- 
Sample configs, scripts, more : http://www.fnords.org/~eric/asterisk/

BTEL Consulting 504-899-1387 or 850-484-4545 or 877-677-9643




More information about the asterisk-dev mailing list