[Asterisk-Users] Custom Application For Asterisk

Gulzar Hussain gulzar10 at yahoo.com
Thu Aug 25 03:36:12 MST 2005


Hi All

I just completed a custom application for Asterisk (i
m not a C guru so i just copy codes from other
application and alter according to my needs) 

attached files is the source file

this application is working fine but still i need you
people to give suggestion to improve it

Primary task of this application is to get a parameter
from extensions.conf, query sql server and play a
files according to the result

Thanks


(I have changed some code to make my code secure ;) )


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
-------------- next part --------------
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/pbx.h>
#include <asterisk/app.h>
#include <asterisk/say.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

#include <libpq-fe.h>
#include <asterisk/translate.h>
#include <asterisk/musiconhold.h>
#include <asterisk/callerid.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <netinet/in.h>

#include <sys/types.h>
#include <asterisk/config.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>
#include "../asterisk.h"

#include <unistd.h>
#include <time.h>
#include <math.h>

#include <tds.h>
#include <tdsconvert.h>
#include <ctype.h>

#if !defined(TDS_INT_EXIT) 
#define TDS_PRE_0_62
	#warning "You have older TDS, you should upgrade!"
#endif

#define DATE_FORMAT "%Y/%m/%d %T"

static char *config = "abcd.conf";
static char *tdesc = "abcd Application";
static char *app = "abcd";
static char *synopsis = "abcd New";
static char *descrip =
  " abcd-IVR: Requires a user to enter a"
  " number. and announce number according to query result\n";
  

static char abcdhostname[30] = "";
static char abcddbname[30] = "";
static char abcddbuser[30] = "";
static char abcdpassword[30] = "";
static char abcdcharset[30] = "";
static char abcdlanguage[30] = "";

#define DEFAULTCHARSET "iso_1"
#define DEFAULTLANGUAGE "us_english"
static int connected = 0;

static int mssql_connect(void);
static int mssql_disconnect(void);
static int play_file(struct ast_channel *chan, char *filename);

AST_MUTEX_DEFINE_STATIC(tdslock);
static TDSSOCKET *tds;
static TDSLOGIN *login;
static TDSCONTEXT *context;

STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
struct abcd_user {
	char moh[80];			
	char announce[80];		
	char context[80];		
	int handled;			
	time_t start;			
	int queuetimeout;               
	struct ast_channel *chan;	
	struct queue_ent *next;		
};

static int abcd_exec(struct ast_channel *chan, void *data)
{
	int retried = 0;
	int res = 0;
	int res_type;
	int tdsret;
	int rowtype;
	int computeid;
	int i;
	int sucs = 0;
	struct localuser *u;
	char mysqlcmd[1024];
	char myretnumber[6];
	const void *value;
	char resulttype[4];
	if (!data) {
		ast_log(LOG_WARNING, "abcd requires an argument (number)\n");
		return -1;
	}
	LOCAL_USER_ADD(u);
	ast_mutex_lock(&tdslock);
	memset(mysqlcmd, 0, sizeof(mysqlcmd));
	sprintf(mysqlcmd, "Select MyFunction(\'%s\') As result",((char *) data));
	do {
		if (!connected) {
			if (mssql_connect())
				ast_log(LOG_ERROR, "Failed to reconnect to SQL database.\n");
			else
				ast_log(LOG_WARNING, "Reconnected to SQL database.\n");
			retried = 1;
		}
		if (!connected || (tds_submit_query(tds, mysqlcmd) != TDS_SUCCEED))
		{
			ast_verbose(VERBOSE_PREFIX_3 "Failed to query database.\n");
			mssql_disconnect();
		}
	} while (!connected && !retried);
	if (!connected) {
		res = -1;
		ast_mutex_unlock(&tdslock);
		LOCAL_USER_REMOVE(u);
		return res;
	}
	tdsret = tds_process_result_tokens(tds, &res_type, NULL);
	switch (tdsret) {
		case TDS_SUCCEED:
			switch(res_type){
				case TDS_DONE_RESULT:
					break;
				case TDS_DONEPROC_RESULT:
					break;
				case TDS_DONEINPROC_RESULT:
					break;
				case TDS_ROWFMT_RESULT:
					while ((res=tds_process_row_tokens(tds, &rowtype, &computeid))==TDS_SUCCEED) {
						for (i=0; i<tds->res_info->num_cols; i++) {
							value  = ((tds->res_info->current_row) + (tds->res_info->columns[i]->column_offset));
							memset(resulttype, 0, sizeof(resulttype));
							strncpy(resulttype, (const char *) value, 3);
							memset(myretnumber, 0, sizeof(myretnumber));
							strncpy(myretnumber, (const char *) (value+4), strlen((const char *) value)-4);
						}
					}
					if(!strcmp(resulttype,"NEW")){
						sprintf(mysqlcmd, "Execute MyStoredProc \'%s\'\0",((char *) data));
						if ((tds_submit_query(tds, mysqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) {
							ast_verbose(VERBOSE_PREFIX_3 "Failed to query database.\n");
							ast_mutex_unlock(&tdslock);
							res = -1;
							return res;
						}
						sprintf(mysqlcmd, "Select MyFunction(\'%s\') As result \0",((char *) data));
						if ((tds_submit_query(tds, mysqlcmd) == TDS_SUCCEED)) {
							tdsret = tds_process_result_tokens(tds, &res_type, NULL);
							if(tdsret == TDS_SUCCEED && res_type == TDS_ROWFMT_RESULT) {
								while ((res=tds_process_row_tokens(tds, &rowtype, &computeid))==TDS_SUCCEED) {
									for (i=0; i<tds->res_info->num_cols; i++) {
										value  = ((tds->res_info->current_row) + (tds->res_info->columns[i]->column_offset));
										strncpy(resulttype, (const char *) value, 3);
										strncpy(myretnumber, (const char *) (value+4), strlen((const char *) value)-4);
									}
								}
							}else {
								ast_verbose(VERBOSE_PREFIX_3 "!TDS_ROWFMT_RESULT %d\n",tdsret);
							}
						}else {
							ast_verbose(VERBOSE_PREFIX_3 "Failed to query database.\n");
						}                                
						ast_mutex_unlock(&tdslock);
						sucs = 1;
						res = play_file(chan, "abcd_yournumbernois");
						res = ast_say_number(chan, atoi(myretnumber), AST_DIGIT_ANY, chan->language, (char *) NULL);
					} else if(!strcmp(resulttype,"ALD")){
						ast_mutex_unlock(&tdslock);
						sucs = 1;
						res = play_file(chan, "abcd_alreadynumber");
						res = ast_say_number(chan, atoi(myretnumber), AST_DIGIT_ANY, chan->language, (char *) NULL);
					} else if(!strcmp(resulttype,"WRG")){
						ast_mutex_unlock(&tdslock);
						sucs = 1;
						ast_moh_stop(chan);
						res = play_file(chan, "abcd_wrongnumber");
					} else if(!strcmp(resulttype,"TMP")){
						ast_mutex_unlock(&tdslock);
						sucs = 1;
						ast_moh_stop(chan);
						res = play_file(chan, "abcd_numberclosed");
					}
					break;                
				case TDS_COMPUTEFMT_RESULT:
					break;                
				case TDS_ROW_RESULT:
					break;                
				case TDS_COMPUTE_RESULT:
					break;                
				case TDS_PARAM_RESULT:
					break;                
				case TDS_STATUS_RESULT:
					break;                
				default:
					break;                          
			}        
			break;
		case TDS_NO_MORE_RESULTS:
			ast_verbose(VERBOSE_PREFIX_3 "TDS_NO_MORE_RESULTS \n");
			break;
		case TDS_FAIL:
			ast_verbose(VERBOSE_PREFIX_3 "tds_process_result_tokens failed. \n");
			res = -1;
			ast_mutex_unlock(&tdslock);
			return res;
	}
	if(sucs == 0) ast_mutex_unlock(&tdslock);
	LOCAL_USER_REMOVE(u);
	return res;
}

static int mssql_connect(void)
{
	TDSCONNECTINFO *connection = NULL;
	char query[128];
	if (!(login = tds_alloc_login()))
	{
		ast_log(LOG_ERROR, "tds_alloc_login() failed.\n");
		return -1;
	}
	tds_set_server(login, abcdhostname);
	tds_set_user(login, abcddbuser);
	tds_set_passwd(login, abcdpassword);
	tds_set_app(login, "TSQL");
	tds_set_library(login, "TDS-Library");
#ifndef TDS_PRE_0_62
	tds_set_client_charset(login, abcdcharset);
#endif
	tds_set_language(login, abcdlanguage);
	tds_set_packet(login, 512);
	tds_set_version(login, 7, 0);
	if (!(context = tds_alloc_context())) {
		ast_log(LOG_ERROR, "tds_alloc_context() failed.\n");
		goto connect_fail;
	}
	if (!(tds = tds_alloc_socket(context, 512))) {
		ast_log(LOG_ERROR, "tds_alloc_socket() failed.\n");
		goto connect_fail;
	}
	tds_set_parent(tds, NULL);
	connection = tds_read_config_info(tds, login, context->locale);
	if (!connection) {
		ast_log(LOG_ERROR, "tds_read_config() failed.\n");
		goto connect_fail;
	}
	if (tds_connect(tds, connection) == TDS_FAIL) {
		ast_log(LOG_ERROR, "Failed to connect to MSSQL server.\n");
		tds = NULL;	
		tds_free_connect(connection);
		connection = NULL;
		goto connect_fail;
	}
	tds_free_connect(connection);
	connection = NULL;
	sprintf(query, "USE %s", abcddbname);
#ifdef TDS_PRE_0_62
	if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) {
#else
	if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) {
#endif
		ast_log(LOG_ERROR, "Could not change database (%s)\n", abcddbname);
		goto connect_fail;
	}
	connected = 1;
	return 0;

connect_fail:
	mssql_disconnect();
	return -1;
}

static int mssql_disconnect(void)
{
	if (tds) {
		tds_free_socket(tds);
		tds = NULL;
	}
	if (context) {
		tds_free_context(context);
		context = NULL;
	}
	if (login) {
		tds_free_login(login);
		login = NULL;
	}
	connected = 0;
	return 0;
}


static int play_file(struct ast_channel *chan, char *filename)
{
	int res;
	ast_stopstream(chan);
	res = ast_streamfile(chan, filename, chan->language);
	if (!res)
		res = ast_waitstream(chan, "");
	else
		res = 0;
	if (res) {
		ast_log(LOG_WARNING, "ast_streamfile failed on %s \n", chan->name);
		res = 0;
	}
	ast_stopstream(chan);
	return res;
}

int load_module(void)
{
	struct ast_config *cfg;
	char *s;
	int res = 0;
	cfg = ast_load(config);
	if (!cfg) {
		ast_log(LOG_NOTICE, "Unable to load config for abcd %s\n", config);
		return 0;
	}
	
	
	if (!(s=ast_variable_retrieve(cfg, "global", "hostname"))) {
		ast_log(LOG_ERROR,"abcd Database Server Hostname not specified.\n");
	} else {
		strncpy(abcdhostname, s, sizeof(abcdhostname) - 1);
	}
	
	if (!(s=ast_variable_retrieve(cfg, "global", "dbname"))) {
		ast_log(LOG_ERROR,"abcd Database Name not specified.\n");
	} else {
		strncpy(abcddbname, s, sizeof(abcddbname) - 1);
	}
	
	if (!(s=ast_variable_retrieve(cfg, "global", "user"))) {
		ast_log(LOG_ERROR,"abcd Database User Name not specified.\n");
	} else {
		strncpy(abcddbuser, s, sizeof(abcddbuser) - 1);
	}
	
	if (!(s=ast_variable_retrieve(cfg, "global", "password"))) {
		ast_log(LOG_ERROR,"abcd Database User Password not specified.\n");
	} else {
		strncpy(abcdpassword, s, sizeof(abcdpassword) - 1);
	}
	
	if (!(s=ast_variable_retrieve(cfg, "global", "charset"))) {
		strncpy(abcdcharset, DEFAULTCHARSET, sizeof(abcdcharset) - 1);		
	} else {
		strncpy(abcdcharset, s, sizeof(abcdcharset) - 1);
	}
	
	if (!(s=ast_variable_retrieve(cfg, "global", "language"))) {
		strncpy(abcdlanguage, DEFAULTLANGUAGE, sizeof(abcdlanguage) - 1);		
	} else {
		strncpy(abcdlanguage, s, sizeof(abcdlanguage) - 1);
	}
	
	ast_destroy(cfg);
	mssql_connect();
	res = ast_register_application(app, abcd_exec, synopsis, descrip);
	if (res){
		ast_log(LOG_ERROR, "Unable to register abcd MSSQL handling\n");
	}
	return res;
}

int unload_module(void)
{
	STANDARD_HANGUP_LOCALUSERS;
	mssql_disconnect();
	ast_unregister_application(app);
	if (abcdhostname) free(abcdhostname);
	if (abcddbname) free(abcddbname);
	if (abcddbuser) free(abcddbuser);
	if (abcdpassword) free(abcdpassword);
	if (abcdcharset) free(abcdcharset);
	if (abcdlanguage) free(abcdlanguage);
	return 0;
}

int reload(void)
{
	unload_module();
	return load_module();
}

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

char *description(void) { return tdesc;}
char *key() {	return ASTERISK_GPL_KEY; }


More information about the asterisk-users mailing list