mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	Version 0.1.12 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@446 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|   | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
| @@ -131,7 +132,8 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char * | ||||
| 	memset(ext, 0, sizeof(ext)); | ||||
| 	ext[0] = digit; | ||||
| 	res = 0; | ||||
| 	if (ast_readstring(chan, ext + 1, NUMDIGITS, 3000, 3000, "#") < 0) res = -1; | ||||
| 	if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1; | ||||
| 	printf("Res: %d, ext: %s\n", res, ext); | ||||
| 	if (!res) { | ||||
| 		/* Search for all names which start with those digits */ | ||||
| 		v = ast_variable_browse(cfg, context); | ||||
| @@ -166,7 +168,7 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char * | ||||
| 			if (v) { | ||||
| 				/* We have a match -- play a greeting if they have it */ | ||||
| 				snprintf(fn, sizeof(fn), "%s/vm/%s/greet", AST_SPOOL_DIR, v->name); | ||||
| 				if (ast_fileexists(fn, NULL, chan->language)) { | ||||
| 				if (ast_fileexists(fn, NULL, chan->language) > 0) { | ||||
| 					res = ast_streamfile(chan, fn, chan->language); | ||||
| 					if (!res) | ||||
| 						res = ast_waitstream(chan, AST_DIGIT_ANY); | ||||
|   | ||||
							
								
								
									
										177
									
								
								apps/app_disa.c
									
									
									
									
									
								
							
							
						
						
									
										177
									
								
								apps/app_disa.c
									
									
									
									
									
								
							| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|   | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
| @@ -25,7 +26,9 @@ | ||||
| #include <pthread.h> | ||||
| #include <sys/time.h> | ||||
|  | ||||
| #define	TONE_BLOCK_SIZE 200 | ||||
| /* | ||||
| #define	TONE_BLOCK_SIZE 320 | ||||
| */ | ||||
|  | ||||
| static char *tdesc = "DISA (Direct Inward System Access) Application"; | ||||
|  | ||||
| @@ -72,19 +75,17 @@ STANDARD_LOCAL_USER; | ||||
|  | ||||
| LOCAL_USER_DECL; | ||||
|  | ||||
| static float loudness=8192.0; | ||||
| static float loudness=4096.0; | ||||
|  | ||||
| int firstdigittimeout = 10000; /* 10 seconds first digit timeout */ | ||||
| int digittimeout = 5000; /* 5 seconds subsequent digit timeout */ | ||||
| int firstdigittimeout = 20000; /* 20 seconds first digit timeout */ | ||||
| int digittimeout = 10000; /* 10 seconds subsequent digit timeout */ | ||||
|  | ||||
| static void make_tone_block(unsigned char *data, float f1, float f2, int *x); | ||||
|  | ||||
| static void make_tone_block(unsigned char *data, float f1, float f2, int *x) | ||||
| static void make_tone_block(unsigned char *data, float f1, float f2, int len, int *x) | ||||
| { | ||||
| int	i; | ||||
| float	val; | ||||
|  | ||||
| 	for(i = 0; i < TONE_BLOCK_SIZE; i++) | ||||
| 	for(i = 0; i < len; i++) | ||||
| 	{ | ||||
| 		val = loudness * sin((f1 * 2.0 * M_PI * (*x))/8000.0); | ||||
| 		val += loudness * sin((f2 * 2.0 * M_PI * (*x)++)/8000.0); | ||||
| @@ -109,12 +110,11 @@ static int disa_exec(struct ast_channel *chan, void *data) | ||||
| 	int i,j,k,x; | ||||
| 	struct localuser *u; | ||||
| 	char tmp[256],exten[AST_MAX_EXTENSION],acctcode[20]; | ||||
| 	unsigned char tone_block[TONE_BLOCK_SIZE],sil_block[TONE_BLOCK_SIZE]; | ||||
| 	unsigned char tone_block[640],sil_block[640]; | ||||
| 	char *ourcontext; | ||||
| 	struct ast_frame *f,wf; | ||||
| 	fd_set	readfds; | ||||
| 	int waitfor_notime; | ||||
| 	struct timeval notime = { 0,0 }, lastout, now, lastdigittime; | ||||
| 	struct timeval lastout, now, lastdigittime; | ||||
| 	int res; | ||||
| 	FILE *fp; | ||||
|  | ||||
| 	if (ast_set_write_format(chan,AST_FORMAT_ULAW)) | ||||
| @@ -129,7 +129,7 @@ static int disa_exec(struct ast_channel *chan, void *data) | ||||
| 	} | ||||
| 	lastout.tv_sec = lastout.tv_usec = 0; | ||||
| 	  /* make block of silence */ | ||||
| 	memset(sil_block,0x7f,TONE_BLOCK_SIZE); | ||||
| 	memset(sil_block,0x7f,sizeof(sil_block)); | ||||
| 	if (!data || !strlen((char *)data)) { | ||||
| 		ast_log(LOG_WARNING, "disa requires an argument (passcode/passcode file)\n"); | ||||
| 		return -1; | ||||
| @@ -165,33 +165,11 @@ static int disa_exec(struct ast_channel *chan, void *data) | ||||
| 				((k) ? "extension" : "password"),chan->name); | ||||
| 			goto reorder; | ||||
| 		} | ||||
| 		  /* if first digit or ignore, send dialtone */ | ||||
| 		if ((!i) || (ast_ignore_pattern(ourcontext,exten) && k))  | ||||
| 		{ | ||||
| 			gettimeofday(&now,NULL); | ||||
| 			if (lastout.tv_sec &&  | ||||
| 				(ms_diff(&now,&lastout) < 25)) continue; | ||||
| 			lastout.tv_sec = now.tv_sec; | ||||
| 			lastout.tv_usec = now.tv_usec; | ||||
| 			wf.frametype = AST_FRAME_VOICE; | ||||
| 			wf.subclass = AST_FORMAT_ULAW; | ||||
| 			wf.offset = AST_FRIENDLY_OFFSET; | ||||
| 			wf.mallocd = 0; | ||||
| 			wf.data = tone_block; | ||||
| 			wf.datalen = TONE_BLOCK_SIZE;				 | ||||
| 			/* make this tone block */ | ||||
| 			make_tone_block(tone_block,350.0,440.0,&x); | ||||
| 			wf.timelen = wf.datalen / 8; | ||||
| 		        if (ast_write(chan, &wf))  | ||||
| 			{ | ||||
| 		                ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name); | ||||
| 				LOCAL_USER_REMOVE(u); | ||||
| 				return -1; | ||||
| 			} | ||||
| 		if ((res = ast_waitfor(chan, -1) < 0)) { | ||||
| 			ast_log(LOG_DEBUG, "Waitfor returned %d\n", res); | ||||
| 			continue; | ||||
| 		} | ||||
| 		waitfor_notime = notime.tv_usec + notime.tv_sec * 1000; | ||||
| 		if (!ast_waitfor_nandfds(&chan, 1, &(chan->fds[0]), 1, NULL, NULL, | ||||
| 			&waitfor_notime)) continue; | ||||
| 			 | ||||
| 		f = ast_read(chan); | ||||
| 		if (f == NULL)  | ||||
| 		{ | ||||
| @@ -204,6 +182,27 @@ static int disa_exec(struct ast_channel *chan, void *data) | ||||
| 			ast_frfree(f); | ||||
| 			LOCAL_USER_REMOVE(u); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		if (f->frametype == AST_FRAME_VOICE) { | ||||
| 			if (!i || (ast_ignore_pattern(ourcontext, exten) && k)) { | ||||
| 				wf.frametype = AST_FRAME_VOICE; | ||||
| 				wf.subclass = AST_FORMAT_ULAW; | ||||
| 				wf.offset = AST_FRIENDLY_OFFSET; | ||||
| 				wf.mallocd = 0; | ||||
| 				wf.data = tone_block; | ||||
| 				wf.datalen = f->datalen; | ||||
| 				make_tone_block(tone_block, 350, 440, f->datalen, &x); | ||||
| 				wf.timelen = wf.datalen / 8; | ||||
| 				ast_frfree(f); | ||||
| 			    if (ast_write(chan, &wf))  | ||||
| 				{ | ||||
| 			        ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name); | ||||
| 					LOCAL_USER_REMOVE(u); | ||||
| 					return -1; | ||||
| 				} | ||||
| 			} else | ||||
| 				ast_frfree(f); | ||||
| 			continue; | ||||
| 		} | ||||
| 		  /* if not DTMF, just do it again */ | ||||
| 		if (f->frametype != AST_FRAME_DTMF)  | ||||
| @@ -211,8 +210,10 @@ static int disa_exec(struct ast_channel *chan, void *data) | ||||
| 			ast_frfree(f); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		j = f->subclass;  /* save digit */ | ||||
| 		ast_frfree(f); | ||||
| 		 | ||||
| 		gettimeofday(&lastdigittime,NULL); | ||||
| 		  /* got a DTMF tone */ | ||||
| 		if (i < AST_MAX_EXTENSION) /* if still valid number of digits */ | ||||
| @@ -258,6 +259,7 @@ static int disa_exec(struct ast_channel *chan, void *data) | ||||
|  | ||||
| 					} | ||||
| 					 /* password good, set to dial state */ | ||||
| 						ast_log(LOG_WARNING,"DISA on chan %s password is good\n",chan->name); | ||||
| 					k = 1; | ||||
| 					i = 0;  /* re-set buffer pointer */ | ||||
| 					exten[sizeof(acctcode)] = 0; | ||||
| @@ -285,95 +287,46 @@ static int disa_exec(struct ast_channel *chan, void *data) | ||||
| 			if (ast_canmatch_extension(chan,ourcontext,exten,1, chan->callerid)) continue; | ||||
| 		} | ||||
| reorder: | ||||
| 		 | ||||
| 		/* something is invalid, give em reorder forever */ | ||||
| 		x = 0; | ||||
| 		k = 0;	/* k = 0 means busy tone, k = 1 means silence) */ | ||||
| 		i = 0;	/* Number of samples we've done */ | ||||
| 		for(;;) | ||||
| 		{ | ||||
| 			for(i = 0; i < 10; i++) | ||||
| 			{ | ||||
| 				do gettimeofday(&now,NULL); | ||||
| 				while (lastout.tv_sec &&  | ||||
| 					(ms_diff(&now,&lastout) < 25)) ; | ||||
| 				lastout.tv_sec = now.tv_sec; | ||||
| 				lastout.tv_usec = now.tv_usec; | ||||
| 			if (ast_waitfor(chan, -1) < 0) | ||||
| 				break; | ||||
| 			f = ast_read(chan); | ||||
| 			if (!f) | ||||
| 				break; | ||||
| 			if (f->frametype == AST_FRAME_VOICE) { | ||||
| 				wf.frametype = AST_FRAME_VOICE; | ||||
| 				wf.subclass = AST_FORMAT_ULAW; | ||||
| 				wf.offset = AST_FRIENDLY_OFFSET; | ||||
| 				wf.mallocd = 0; | ||||
| 				wf.data = tone_block; | ||||
| 				wf.datalen = TONE_BLOCK_SIZE; | ||||
| 				/* make this tone block */ | ||||
| 				make_tone_block(tone_block,480.0,620.0,&x); | ||||
| 				wf.datalen = f->datalen; | ||||
| 				wf.timelen = wf.datalen / 8; | ||||
| 			        if (ast_write(chan, &wf))  | ||||
| 				if (k)  | ||||
| 					memset(tone_block, 0x7f, wf.datalen); | ||||
| 				else | ||||
| 					make_tone_block(tone_block,480.0, 620.0,wf.datalen, &x); | ||||
| 				i += wf.datalen / 8; | ||||
| 				if (i > 250) { | ||||
| 					i = 0; | ||||
| 					k = !k; | ||||
| 				} | ||||
| 			    if (ast_write(chan, &wf))  | ||||
| 				{ | ||||
| 			                ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name); | ||||
| 			        ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name); | ||||
| 					LOCAL_USER_REMOVE(u); | ||||
| 					return -1; | ||||
| 				} | ||||
| 				FD_ZERO(&readfds); | ||||
| 				FD_SET(chan->fds[0],&readfds); | ||||
| 				  /* if no read avail, do send again */ | ||||
| 				if (select(chan->fds[0] + 1,&readfds,NULL, | ||||
| 					NULL,¬ime) < 1) continue; | ||||
| 				  /* read frame */ | ||||
| 				f = ast_read(chan); | ||||
| 				if (f == NULL)  | ||||
| 				{ | ||||
| 					LOCAL_USER_REMOVE(u); | ||||
| 					return -1; | ||||
| 				} | ||||
| 				if ((f->frametype == AST_FRAME_CONTROL) && | ||||
| 				    (f->subclass == AST_CONTROL_HANGUP)) | ||||
| 				{ | ||||
| 					ast_frfree(f); | ||||
| 					LOCAL_USER_REMOVE(u); | ||||
| 					return -1; | ||||
| 				} | ||||
| 				ast_frfree(f); | ||||
| 			} | ||||
| 			for(i = 0; i < 10; i++) | ||||
| 			{ | ||||
| 				do gettimeofday(&now,NULL); | ||||
| 				while (lastout.tv_sec &&  | ||||
| 					(ms_diff(&now,&lastout) < 25)) ; | ||||
| 				lastout.tv_sec = now.tv_sec; | ||||
| 				lastout.tv_usec = now.tv_usec; | ||||
| 				wf.frametype = AST_FRAME_VOICE; | ||||
| 				wf.subclass = AST_FORMAT_ULAW; | ||||
| 				wf.offset = AST_FRIENDLY_OFFSET; | ||||
| 				wf.mallocd = 0; | ||||
| 				wf.data = sil_block; | ||||
| 				wf.datalen = TONE_BLOCK_SIZE; | ||||
| 				wf.timelen = wf.datalen / 8; | ||||
| 			        if (ast_write(chan, &wf))  | ||||
| 				{ | ||||
| 			                ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name); | ||||
| 					LOCAL_USER_REMOVE(u); | ||||
| 					return -1; | ||||
| 				} | ||||
| 				FD_ZERO(&readfds); | ||||
| 				FD_SET(chan->fds[0],&readfds); | ||||
| 				  /* if no read avail, do send again */ | ||||
| 				if (select(chan->fds[0] + 1,&readfds,NULL, | ||||
| 					NULL,¬ime) < 1) continue; | ||||
| 				  /* read frame */ | ||||
| 				f = ast_read(chan); | ||||
| 				if (f == NULL)  | ||||
| 				{ | ||||
| 					LOCAL_USER_REMOVE(u); | ||||
| 					return -1; | ||||
| 				} | ||||
| 				if ((f->frametype == AST_FRAME_CONTROL) && | ||||
| 				    (f->subclass == AST_CONTROL_HANGUP)) | ||||
| 				{ | ||||
| 					ast_frfree(f); | ||||
| 					LOCAL_USER_REMOVE(u); | ||||
| 					return -1; | ||||
| 				} | ||||
| 				ast_frfree(f); | ||||
| 			} | ||||
| 			ast_frfree(f); | ||||
| 		} | ||||
| 		LOCAL_USER_REMOVE(u); | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|  | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
| @@ -47,7 +48,10 @@ static int echo_exec(struct ast_channel *chan, void *data) | ||||
| 	ast_set_write_format(chan, ast_best_codec(chan->nativeformats)); | ||||
| 	ast_set_read_format(chan, ast_best_codec(chan->nativeformats)); | ||||
| 	/* Do our thing here */ | ||||
| 	while((f = ast_read(chan))) { | ||||
| 	while(ast_waitfor(chan, -1) > -1) { | ||||
| 		f = ast_read(chan); | ||||
| 		if (!f) | ||||
| 			break; | ||||
| 		if (f->frametype == AST_FRAME_VOICE) { | ||||
| 			if (ast_write(chan, f))  | ||||
| 				break; | ||||
|   | ||||
							
								
								
									
										149
									
								
								apps/app_getcpeid.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										149
									
								
								apps/app_getcpeid.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| /* | ||||
|  * Asterisk -- A telephony toolkit for Linux. | ||||
|  * | ||||
|  * Execute arbitrary system commands | ||||
|  *  | ||||
|  * Copyright (C) 1999, Mark Spencer | ||||
|  * | ||||
|  * Mark Spencer <markster@linux-support.net> | ||||
|  * | ||||
|  * This program is free software, distributed under the terms of | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|  | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
| #include <asterisk/pbx.h> | ||||
| #include <asterisk/module.h> | ||||
| #include <asterisk/adsi.h> | ||||
| #include <asterisk/options.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include <pthread.h> | ||||
|  | ||||
|  | ||||
| static char *tdesc = "Get ADSI CPE ID"; | ||||
|  | ||||
| static char *app = "GetCPEID"; | ||||
|  | ||||
| static char *synopsis = "Get ADSI CPE ID"; | ||||
|  | ||||
| static char *descrip = | ||||
| "  GetCPEID: Obtains and displays CPE ID and other information in order to\n" | ||||
| "properly setup zapata.conf for on-hook operations.  Returns -1 on hanup\n" | ||||
| "only."; | ||||
|  | ||||
| STANDARD_LOCAL_USER; | ||||
|  | ||||
| LOCAL_USER_DECL; | ||||
|  | ||||
| static int cpeid_setstatus(struct ast_channel *chan, char *stuff[], int voice) | ||||
| { | ||||
| 	int justify[5] = { ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_JUST_LEFT, ADSI_JUST_LEFT }; | ||||
| 	char *tmp[5]; | ||||
| 	int x; | ||||
| 	for (x=0;x<4;x++) | ||||
| 		tmp[x] = stuff[x]; | ||||
| 	tmp[4] = NULL; | ||||
| 	return adsi_print(chan, tmp, justify, voice); | ||||
| } | ||||
|  | ||||
| static int cpeid_exec(struct ast_channel *chan, void *idata) | ||||
| { | ||||
| 	int res=0; | ||||
| 	struct localuser *u; | ||||
| 	unsigned char cpeid[4]; | ||||
| 	int gotgeometry = 0; | ||||
| 	int gotcpeid = 0; | ||||
| 	int width, height, buttons; | ||||
| 	char data[4][80]; | ||||
| 	char *stuff[4]; | ||||
|  | ||||
| 	LOCAL_USER_ADD(u); | ||||
| 	stuff[0] = data[0]; | ||||
| 	stuff[1] = data[1]; | ||||
| 	stuff[2] = data[2]; | ||||
| 	stuff[3] = data[3]; | ||||
| 	memset(data, 0, sizeof(data)); | ||||
| 	strcpy(stuff[0], "** CPE Info **"); | ||||
| 	strcpy(stuff[1], "Identifying CPE..."); | ||||
| 	strcpy(stuff[2], "Please wait..."); | ||||
| 	res = adsi_load_session(chan, NULL, 0, 1); | ||||
| 	if (res > 0) { | ||||
| 		cpeid_setstatus(chan, stuff, 0); | ||||
| 		res = adsi_get_cpeid(chan, cpeid, 0); | ||||
| 		if (res > 0) { | ||||
| 			gotcpeid = 1; | ||||
| 			if (option_verbose > 2) | ||||
| 				ast_verbose(VERBOSE_PREFIX_3 "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", cpeid[0], cpeid[1], cpeid[2], cpeid[3], chan->name); | ||||
| 		} | ||||
| 		if (res > -1) { | ||||
| 			strcpy(stuff[1], "Measuring CPE..."); | ||||
| 			strcpy(stuff[2], "Please wait..."); | ||||
| 			cpeid_setstatus(chan, stuff, 0); | ||||
| 			res = adsi_get_cpeinfo(chan, &width, &height, &buttons, 0); | ||||
| 			if (res > -1) { | ||||
| 				if (option_verbose > 2) | ||||
| 					ast_verbose(VERBOSE_PREFIX_3 "CPE has %d lines, %d columns, and %d buttons on '%s'\n", height, width, buttons, chan->name); | ||||
| 				gotgeometry = 1; | ||||
| 			} | ||||
| 		} | ||||
| 		if (res > -1) { | ||||
| 			if (gotcpeid) | ||||
| 				sprintf(stuff[1], "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]); | ||||
| 			else | ||||
| 				strcpy(stuff[1], "CPEID Unknown"); | ||||
| 			if (gotgeometry)  | ||||
| 				sprintf(stuff[2], "Geom: %dx%d, %d buttons", width, height, buttons); | ||||
| 			else | ||||
| 				strcpy(stuff[2], "Geometry unknown"); | ||||
| 			strcpy(stuff[3], "Press # to exit"); | ||||
| 			cpeid_setstatus(chan, stuff, 1); | ||||
| 			for(;;) { | ||||
| 				res = ast_waitfordigit(chan, 1000); | ||||
| 				if (res < 0) | ||||
| 					break; | ||||
| 				if (res == '#') { | ||||
| 					res = 0; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			adsi_unload_session(chan); | ||||
| 		} | ||||
| 	} | ||||
| 	LOCAL_USER_REMOVE(u); | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| int unload_module(void) | ||||
| { | ||||
| 	STANDARD_HANGUP_LOCALUSERS; | ||||
| 	return ast_unregister_application(app); | ||||
| } | ||||
|  | ||||
| int load_module(void) | ||||
| { | ||||
| 	return ast_register_application(app, cpeid_exec, synopsis, descrip); | ||||
| } | ||||
|  | ||||
| char *description(void) | ||||
| { | ||||
| 	return tdesc; | ||||
| } | ||||
|  | ||||
| int usecount(void) | ||||
| { | ||||
| 	int res; | ||||
| 	STANDARD_USECOUNT(res); | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| char *key() | ||||
| { | ||||
| 	return ASTERISK_GPL_KEY; | ||||
| } | ||||
| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|   | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|   | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/frame.h> | ||||
| #include <asterisk/logger.h> | ||||
| @@ -47,7 +48,7 @@ STANDARD_LOCAL_USER; | ||||
|  | ||||
| LOCAL_USER_DECL; | ||||
|  | ||||
| static pthread_mutex_t sound_lock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t sound_lock = AST_MUTEX_INITIALIZER; | ||||
| static int sound = -1; | ||||
|  | ||||
| static int write_audio(short *data, int len) | ||||
|   | ||||
							
								
								
									
										501
									
								
								apps/app_meetme.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										501
									
								
								apps/app_meetme.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,501 @@ | ||||
| /* | ||||
|  * Asterisk -- A telephony toolkit for Linux. | ||||
|  * | ||||
|  * Meet me conference bridge | ||||
|  *  | ||||
|  * Copyright (C) 1999, Mark Spencer | ||||
|  * | ||||
|  * Mark Spencer <markster@linux-support.net> | ||||
|  * | ||||
|  * This program is free software, distributed under the terms of | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|  | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
| #include <asterisk/pbx.h> | ||||
| #include <asterisk/module.h> | ||||
| #include <asterisk/config.h> | ||||
| #include <asterisk/app.h> | ||||
| #include <asterisk/options.h> | ||||
| #include <asterisk/cli.h> | ||||
| #include <asterisk/say.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <sys/ioctl.h> | ||||
|  | ||||
| #include <pthread.h> | ||||
| #include <linux/zaptel.h> | ||||
|  | ||||
| static char *tdesc = "Simple MeetMe conference bridge"; | ||||
|  | ||||
| static char *app = "MeetMe"; | ||||
| static char *app2 = "MeetMeCount"; | ||||
|  | ||||
| static char *synopsis = "Simple MeetMe conference bridge"; | ||||
| static char *synopsis2 = "MeetMe participant count"; | ||||
|  | ||||
| static char *descrip = | ||||
| "  MeetMe(confno): Enters the user into a specified MeetMe conference.\n" | ||||
| "If the conference number is omitted, the user will be prompted to enter\n" | ||||
| "one.  This application always returns -1. A ZAPTEL INTERFACE MUST BE\n" | ||||
| "INSTALLED FOR CONFERENCING FUNCTIONALITY.\n"; | ||||
|  | ||||
| static char *descrip2 = | ||||
| "  MeetMe2(confno): Plays back the number of users in the specified MeetMe\n" | ||||
| "conference.  Returns 0 on success or -1 on a hangup.  A ZAPTEL INTERFACE\n" | ||||
| "MUST BE INSTALLED FOR CONFERENCING FUNCTIONALITY.\n"; | ||||
|  | ||||
| STANDARD_LOCAL_USER; | ||||
|  | ||||
| LOCAL_USER_DECL; | ||||
|  | ||||
| static struct conf { | ||||
| 	char confno[80];		/* Conference */ | ||||
| 	int fd;				/* Announcements fd */ | ||||
| 	int zapconf;			/* Zaptel Conf # */ | ||||
| 	int users;			/* Number of active users */ | ||||
| 	time_t start;			/* Start time (s) */ | ||||
| 	struct conf *next; | ||||
| } *confs; | ||||
|  | ||||
| static pthread_mutex_t conflock = AST_MUTEX_INITIALIZER; | ||||
|  | ||||
| #include "enter.h" | ||||
| #include "leave.h" | ||||
|  | ||||
| #define ENTER	0 | ||||
| #define LEAVE	1 | ||||
|  | ||||
| #define CONF_SIZE 160 | ||||
|  | ||||
| static int careful_write(int fd, unsigned char *data, int len) | ||||
| { | ||||
| 	int res; | ||||
| 	while(len) { | ||||
| 		res = write(fd, data, len); | ||||
| 		if (res < 1) { | ||||
| 			if (errno != EAGAIN) { | ||||
| 				ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); | ||||
| 				return -1; | ||||
| 			} else | ||||
| 				return 0; | ||||
| 		} | ||||
| 		len -= res; | ||||
| 		data += res; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void conf_play(struct conf *conf, int sound) | ||||
| { | ||||
| 	unsigned char *data; | ||||
| 	int len; | ||||
| 	ast_pthread_mutex_lock(&conflock); | ||||
| 	switch(sound) { | ||||
| 	case ENTER: | ||||
| 		data = enter; | ||||
| 		len = sizeof(enter); | ||||
| 		break; | ||||
| 	case LEAVE: | ||||
| 		data = leave; | ||||
| 		len = sizeof(leave); | ||||
| 		break; | ||||
| 	default: | ||||
| 		data = NULL; | ||||
| 		len = 0; | ||||
| 	} | ||||
| 	if (data)  | ||||
| 		careful_write(conf->fd, data, len); | ||||
| 	pthread_mutex_unlock(&conflock); | ||||
| } | ||||
|  | ||||
| static struct conf *build_conf(char *confno, int make) | ||||
| { | ||||
| 	struct conf *cnf; | ||||
| 	struct zt_confinfo ztc; | ||||
| 	ast_pthread_mutex_lock(&conflock); | ||||
| 	cnf = confs; | ||||
| 	while(cnf) { | ||||
| 		if (!strcmp(confno, cnf->confno))  | ||||
| 			break; | ||||
| 		cnf = cnf->next; | ||||
| 	} | ||||
| 	if (!cnf && make) { | ||||
| 		cnf = malloc(sizeof(struct conf)); | ||||
| 		if (cnf) { | ||||
| 			/* Make a new one */ | ||||
| 			memset(cnf, 0, sizeof(struct conf)); | ||||
| 			strncpy(cnf->confno, confno, sizeof(cnf->confno) - 1); | ||||
| 			cnf->fd = open("/dev/zap/pseudo", O_RDWR); | ||||
| 			if (cnf->fd < 0) { | ||||
| 				ast_log(LOG_WARNING, "Unable to open pseudo channel\n"); | ||||
| 				free(cnf); | ||||
| 				cnf = NULL; | ||||
| 				goto cnfout; | ||||
| 			} | ||||
| 			memset(&ztc, 0, sizeof(ztc)); | ||||
| 			/* Setup a new zap conference */ | ||||
| 			ztc.chan = 0;	 | ||||
| 			ztc.confno = -1; | ||||
| 			ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; | ||||
| 			if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) { | ||||
| 				ast_log(LOG_WARNING, "Error setting conference\n"); | ||||
| 				close(cnf->fd); | ||||
| 				free(cnf); | ||||
| 				cnf = NULL; | ||||
| 				goto cnfout; | ||||
| 			} | ||||
| 			cnf->start = time(NULL); | ||||
| 			cnf->zapconf = ztc.confno; | ||||
| 			if (option_verbose > 2) | ||||
| 				ast_verbose(VERBOSE_PREFIX_3 "Crated ZapTel conference %d for conference '%s'\n", cnf->zapconf, cnf->confno); | ||||
| 			cnf->next = confs; | ||||
| 			confs = cnf; | ||||
| 		} else	 | ||||
| 			ast_log(LOG_WARNING, "Out of memory\n"); | ||||
| 	} | ||||
| cnfout: | ||||
| 	if (cnf && make)  | ||||
| 		cnf->users++; | ||||
| 	ast_pthread_mutex_unlock(&conflock); | ||||
| 	return cnf; | ||||
| } | ||||
|  | ||||
| static int confs_show(int fd, int argc, char **argv) | ||||
| { | ||||
| 	struct conf *conf; | ||||
| 	int hr, min, sec; | ||||
| 	time_t now; | ||||
|  | ||||
| 	now = time(NULL); | ||||
| 	if (argc != 2) | ||||
| 		return RESULT_SHOWUSAGE; | ||||
| 	conf = confs; | ||||
| 	if (!conf) {	 | ||||
| 		ast_cli(fd, "No active conferences.\n"); | ||||
| 		return RESULT_SUCCESS; | ||||
| 	} | ||||
| 	ast_cli(fd, "Conf Num    Parties          Activity\n"); | ||||
| 	while(conf) { | ||||
| 		hr = (now - conf->start) / 3600; | ||||
| 		min = ((now - conf->start) % 3600) / 60; | ||||
| 		sec = (now - conf->start) % 60; | ||||
|  | ||||
| 		ast_cli(fd, "%-12.12s   %4.4d          %02d:%02d:%02d\n",  | ||||
| 			conf->confno, conf->users, hr, min, sec); | ||||
| 		conf = conf->next; | ||||
| 	} | ||||
| 	return RESULT_SUCCESS; | ||||
| } | ||||
|  | ||||
| static char show_confs_usage[] =  | ||||
| "Usage: show conferences\n" | ||||
| "       Provides summary information on conferences with active\n" | ||||
| "       participation.\n"; | ||||
|  | ||||
| static struct ast_cli_entry cli_show_confs = { | ||||
| 	{ "show", "conferences", NULL }, confs_show,  | ||||
| 	"Show status of conferences", show_confs_usage, NULL }; | ||||
|  | ||||
| static void conf_run(struct ast_channel *chan, struct conf *conf) | ||||
| { | ||||
| 	struct conf *prev=NULL, *cur; | ||||
| 	int fd; | ||||
| 	struct zt_confinfo ztc; | ||||
| 	struct ast_frame *f; | ||||
| 	struct ast_channel *c; | ||||
| 	struct ast_frame fr; | ||||
| 	int outfd; | ||||
| 	int ms; | ||||
| 	int nfds; | ||||
| 	int res; | ||||
| 	int flags; | ||||
| 	int retryzap=0; | ||||
|  | ||||
| 	ZT_BUFFERINFO bi; | ||||
| 	char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; | ||||
| 	char *buf = __buf + AST_FRIENDLY_OFFSET; | ||||
|  | ||||
| 	/* Set it into U-law mode (write) */ | ||||
| 	if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) { | ||||
| 		ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name); | ||||
| 		goto outrun; | ||||
| 	} | ||||
|  | ||||
| 	/* Set it into U-law mode (read) */ | ||||
| 	if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) { | ||||
| 		ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name); | ||||
| 		goto outrun; | ||||
| 	} | ||||
| zapretry: | ||||
|  | ||||
| 	if (retryzap || strcasecmp(chan->type, "Zap")) { | ||||
| 		fd = open("/dev/zap/pseudo", O_RDWR); | ||||
| 		if (fd < 0) { | ||||
| 			ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); | ||||
| 			goto outrun; | ||||
| 		} | ||||
| 		/* Make non-blocking */ | ||||
| 		flags = fcntl(fd, F_GETFL); | ||||
| 		if (flags < 0) { | ||||
| 			ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); | ||||
| 			close(fd); | ||||
| 			goto outrun; | ||||
| 		} | ||||
| 		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { | ||||
| 			ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); | ||||
| 			close(fd); | ||||
| 			goto outrun; | ||||
| 		} | ||||
| 		/* Setup buffering information */ | ||||
| 		memset(&bi, 0, sizeof(bi)); | ||||
| 		bi.bufsize = CONF_SIZE; | ||||
| 		bi.txbufpolicy = ZT_POLICY_IMMEDIATE; | ||||
| 		bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; | ||||
| 		bi.numbufs = 4; | ||||
| 		if (ioctl(fd, ZT_SET_BUFINFO, &bi)) { | ||||
| 			ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); | ||||
| 			close(fd); | ||||
| 			goto outrun; | ||||
| 		} | ||||
| 		nfds = 1; | ||||
| 	} else { | ||||
| 		/* XXX Make sure we're not running on a pseudo channel XXX */ | ||||
| 		fd = chan->fds[0]; | ||||
| 		nfds = 0; | ||||
| 	} | ||||
| 	memset(&ztc, 0, sizeof(ztc)); | ||||
| 	/* Check to see if we're in a conference... */ | ||||
| 	ztc.chan = 0;	 | ||||
| 	if (ioctl(fd, ZT_GETCONF, &ztc)) { | ||||
| 		ast_log(LOG_WARNING, "Error getting conference\n"); | ||||
| 		close(fd); | ||||
| 		goto outrun; | ||||
| 	} | ||||
| 	if (ztc.confmode) { | ||||
| 		/* Whoa, already in a conference...  Retry... */ | ||||
| 		if (!retryzap) { | ||||
| 			ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n"); | ||||
| 			retryzap = 1; | ||||
| 			goto zapretry; | ||||
| 		} | ||||
| 	} | ||||
| 	memset(&ztc, 0, sizeof(ztc)); | ||||
| 	/* Add us to the conference */ | ||||
| 	ztc.chan = 0;	 | ||||
| 	ztc.confno = conf->zapconf; | ||||
| 	ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; | ||||
| 	if (ioctl(fd, ZT_SETCONF, &ztc)) { | ||||
| 		ast_log(LOG_WARNING, "Error setting conference\n"); | ||||
| 		close(fd); | ||||
| 		goto outrun; | ||||
| 	} | ||||
| 	ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf); | ||||
| 	/* Run the conference enter tone... */ | ||||
| 	conf_play(conf, ENTER); | ||||
|  | ||||
| 	for(;;) { | ||||
| 		outfd = -1; | ||||
| 		ms = -1; | ||||
| 		c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); | ||||
| 		if (c) { | ||||
| 			f = ast_read(c); | ||||
| 			if (!f)  | ||||
| 				break; | ||||
| 			if (fd != chan->fds[0]) { | ||||
| 				if (f->frametype == AST_FRAME_VOICE) { | ||||
| 					if (f->subclass == AST_FORMAT_ULAW) { | ||||
| 						/* Carefully write */ | ||||
| 						careful_write(fd, f->data, f->datalen); | ||||
| 					} else | ||||
| 						ast_log(LOG_WARNING, "Huh?  Got a non-ulaw (%d) frame in the conference\n", f->subclass); | ||||
| 				} | ||||
| 			} | ||||
| 			ast_frfree(f); | ||||
| 		} else if (outfd > -1) { | ||||
| 			res = read(outfd, buf, CONF_SIZE); | ||||
| 			if (res > 0) { | ||||
| 				memset(&fr, 0, sizeof(fr)); | ||||
| 				fr.frametype = AST_FRAME_VOICE; | ||||
| 				fr.subclass = AST_FORMAT_ULAW; | ||||
| 				fr.datalen = res; | ||||
| 				fr.timelen = res / 8; | ||||
| 				fr.data = buf; | ||||
| 				fr.offset = AST_FRIENDLY_OFFSET; | ||||
| 				if (ast_write(chan, &fr) < 0) { | ||||
| 					ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno)); | ||||
| 					/* break; */ | ||||
| 				} | ||||
| 			} else  | ||||
| 				ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); | ||||
| 		} | ||||
| 	} | ||||
| 	if (fd != chan->fds[0]) | ||||
| 		close(fd); | ||||
|  | ||||
| 	conf_play(conf, LEAVE); | ||||
|  | ||||
| outrun: | ||||
|  | ||||
| 	ast_pthread_mutex_lock(&conflock); | ||||
| 	/* Clean up */ | ||||
| 	conf->users--; | ||||
| 	if (!conf->users) { | ||||
| 		/* No more users -- close this one out */ | ||||
| 		cur = confs; | ||||
| 		while(cur) { | ||||
| 			if (cur == conf) { | ||||
| 				if (prev) | ||||
| 					prev->next = conf->next; | ||||
| 				else | ||||
| 					confs = conf->next; | ||||
| 				break; | ||||
| 			} | ||||
| 			prev = cur; | ||||
| 			cur = cur->next; | ||||
| 		} | ||||
| 		if (!cur)  | ||||
| 			ast_log(LOG_WARNING, "Conference not found\n"); | ||||
| 		close(conf->fd); | ||||
| 		free(conf); | ||||
| 	} | ||||
| 	pthread_mutex_unlock(&conflock); | ||||
| } | ||||
|  | ||||
| static struct conf *find_conf(char *confno, int make) | ||||
| { | ||||
| 	struct ast_config *cfg; | ||||
| 	struct ast_variable *var; | ||||
| 	struct conf *cnf = NULL; | ||||
| 	cfg = ast_load("meetme.conf"); | ||||
| 	if (!cfg) { | ||||
| 		ast_log(LOG_WARNING, "No meetme.conf file :(\n"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	var = ast_variable_browse(cfg, "rooms"); | ||||
| 	while(var) { | ||||
| 		if (!strcasecmp(var->name, "conf") && | ||||
| 		    !strcasecmp(var->value, confno)) { | ||||
| 			/* Bingo it's a valid conference */ | ||||
| 			cnf = build_conf(confno, make); | ||||
| 			break; | ||||
| 		} | ||||
| 		var = var->next; | ||||
| 	} | ||||
| 	if (!var) { | ||||
| 		ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno); | ||||
| 	} | ||||
| 	ast_destroy(cfg); | ||||
| 	return cnf; | ||||
| } | ||||
|  | ||||
| static int count_exec(struct ast_channel *chan, void *data) | ||||
| { | ||||
| 	struct localuser *u; | ||||
| 	int res = 0; | ||||
| 	struct conf *conf; | ||||
| 	int cnt; | ||||
| 	if (!data || !strlen(data)) { | ||||
| 		ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	LOCAL_USER_ADD(u); | ||||
| 	conf = find_conf(data, 0); | ||||
| 	if (conf) | ||||
| 		cnt = conf->users; | ||||
| 	else | ||||
| 		cnt = 0; | ||||
| 	if (chan->state != AST_STATE_UP) | ||||
| 		ast_answer(chan); | ||||
| 	res = ast_say_number(chan, cnt, "", chan->language); | ||||
| 	LOCAL_USER_REMOVE(u); | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| static int conf_exec(struct ast_channel *chan, void *data) | ||||
| { | ||||
| 	int res=-1; | ||||
| 	struct localuser *u; | ||||
| 	char confno[80] = ""; | ||||
| 	int allowretry = 0; | ||||
| 	int retrycnt = 0; | ||||
| 	struct conf *cnf; | ||||
|  | ||||
| 	if (!data || !strlen(data)) { | ||||
| 		allowretry = 1; | ||||
| 		data = ""; | ||||
| 	} | ||||
| 	LOCAL_USER_ADD(u); | ||||
| 	if (chan->state != AST_STATE_UP) | ||||
| 		ast_answer(chan); | ||||
| retry: | ||||
| 	/* Parse out the stuff */ | ||||
| 	strncpy(confno, data, sizeof(confno) - 1); | ||||
|  | ||||
| 	while(!strlen(confno) && (++retrycnt < 4)) { | ||||
| 		/* Prompt user for conference number */ | ||||
| 		res = ast_app_getdata(chan, "conf-getconfno",confno, sizeof(confno) - 1, 0); | ||||
| 		if (res <0) goto out; | ||||
| 	} | ||||
| 	if (strlen(confno)) { | ||||
| 		/* Check the validity of the conference */ | ||||
| 		cnf = find_conf(confno, 1); | ||||
| 		if (!cnf) { | ||||
| 			res = ast_streamfile(chan, "conf-invalid", chan->language); | ||||
| 			if (res < 0) | ||||
| 				goto out; | ||||
| 			if (!res) | ||||
| 				res = ast_waitstream(chan, ""); | ||||
| 			res = -1; | ||||
| 			if (allowretry) { | ||||
| 				strcpy(confno, ""); | ||||
| 				goto retry; | ||||
| 			} | ||||
| 		} else { | ||||
| 			/* Run the conference */ | ||||
| 			conf_run(chan, cnf); | ||||
| 			res = -1; | ||||
| 		} | ||||
| 	} | ||||
| out: | ||||
| 	/* Do the conference */ | ||||
| 	LOCAL_USER_REMOVE(u); | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| int unload_module(void) | ||||
| { | ||||
| 	STANDARD_HANGUP_LOCALUSERS; | ||||
| 	ast_cli_unregister(&cli_show_confs); | ||||
| 	ast_unregister_application(app2); | ||||
| 	return ast_unregister_application(app); | ||||
| } | ||||
|  | ||||
| int load_module(void) | ||||
| { | ||||
| 	ast_cli_register(&cli_show_confs); | ||||
| 	ast_register_application(app2, count_exec, synopsis2, descrip2); | ||||
| 	return ast_register_application(app, conf_exec, synopsis, descrip); | ||||
| } | ||||
|  | ||||
| char *description(void) | ||||
| { | ||||
| 	return tdesc; | ||||
| } | ||||
|  | ||||
| int usecount(void) | ||||
| { | ||||
| 	int res; | ||||
| 	STANDARD_USECOUNT(res); | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| char *key() | ||||
| { | ||||
| 	return ASTERISK_GPL_KEY; | ||||
| } | ||||
| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|   | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|   | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
|   | ||||
| @@ -16,13 +16,14 @@ | ||||
|  * The queue is a directory containing files with the call request information | ||||
|  * as a single line of text as follows: | ||||
|  *  | ||||
|  * Dialstring Caller-ID Extension Maxsecs Identifier [Required-response] | ||||
|  * Dialstring Caller-ID Extension Maxsecs [Identifier] [Required-response] | ||||
|  * | ||||
|  *  Dialstring -- A Dial String (The number to be called) in the | ||||
|  *  format Technology/Number, such IAX/mysys/1234 or Zap/g1/1234 | ||||
|  *  | ||||
|  *  Caller-ID -- A Standard nomalized representation of the Caller-ID of | ||||
|  *  the number being dialed (generally 10 digits in the US). | ||||
|  *  the number being dialed (generally 10 digits in the US). Leave as | ||||
|  *  "asreceived" to use the default Caller*ID | ||||
|  * | ||||
|  *  Extension -- The Extension (optionally Extension@context) that the | ||||
|  *  user should be "transferred" to after acceptance of the call. | ||||
| @@ -36,7 +37,7 @@ | ||||
|  *  (generally a "thank you" recording), is the specified string with "-ok"  | ||||
|  *  added to the end. So, if you specify "foo" as the identifier, your first | ||||
|  *  prompt file that will be played will be "foo" and the second one will be | ||||
|  *  "foo-ok". | ||||
|  *  "foo-ok".  If omitted no prompt is given | ||||
|  * | ||||
|  *  Required-Response (Optional) -- Specify a digit string to be used as the | ||||
|  *  acceptance "code" if you desire it to be something other then "1". This | ||||
| @@ -49,6 +50,7 @@ | ||||
|  * | ||||
|  */ | ||||
|   | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
| @@ -78,7 +80,7 @@ STANDARD_LOCAL_USER; | ||||
| LOCAL_USER_DECL; | ||||
|  | ||||
| #define	OLDESTOK	14400		/* not any more then this number of secs old */ | ||||
| #define	INITIALONE	20		/* initial wait before the first one in secs */ | ||||
| #define	INITIALONE	1		/* initial wait before the first one in secs */ | ||||
| #define	NEXTONE		600		/* wait before trying it again in secs */ | ||||
| #define	MAXWAITFORANSWER 45000		/* max call time before answer */ | ||||
| /* define either one or both of these two if your application requires it */ | ||||
| @@ -132,7 +134,8 @@ pthread_attr_t attr; | ||||
| 			  /* if not yet .... */ | ||||
| 			if (mystat.st_atime == mystat.st_ctime) | ||||
| 			   {  /* first time */ | ||||
| 				if ((mystat.st_atime + INITIALONE) > t) continue; | ||||
| 				if ((mystat.st_atime + INITIALONE) > t)  | ||||
| 					continue; | ||||
| 			   } | ||||
| 			else | ||||
| 			   { /* already looked at once */ | ||||
| @@ -195,8 +198,9 @@ time_t	t; | ||||
| 		pthread_exit(NULL); | ||||
| 	   } | ||||
| 	strcpy(reqinp,"1");  /* default required input for acknowledgement */ | ||||
| 	strcpy(ident, "");	/* default no ident */ | ||||
| 	if (fscanf(fp,"%s %s %s %d %s %s",dialstr,clid, | ||||
| 		extstr,&maxsecs,ident,reqinp) < 5) | ||||
| 		extstr,&maxsecs,ident,reqinp) < 4) | ||||
| 	   { | ||||
| 		fprintf(stderr,"qcall_do:file line invalid in file %s:\n",fname); | ||||
| 		pthread_exit(NULL); | ||||
| @@ -216,10 +220,12 @@ time_t	t; | ||||
| 	   { | ||||
| 		ast_set_read_format(channel,AST_FORMAT_SLINEAR); | ||||
| 		ast_set_write_format(channel,AST_FORMAT_SLINEAR); | ||||
| 		channel->callerid = NULL; | ||||
| 		channel->ani = NULL; | ||||
| #ifdef	OURCLID | ||||
| 		if (channel->callerid) | ||||
| 			free(channel->callerid); | ||||
| 		channel->callerid = strdup(OURCLID); | ||||
| 		if (channel->ani) | ||||
| 			free(channel->ani); | ||||
| 		channel->ani = strdup(OURCLID); | ||||
| #endif		 | ||||
| 		channel->whentohangup = 0; | ||||
| @@ -235,10 +241,12 @@ time_t	t; | ||||
| 		fprintf(stderr,"qcall_do:Sorry unable to obtain channel\n"); | ||||
| 		pthread_exit(NULL); | ||||
| 	   } | ||||
| 	if (channel->callerid) free(channel->callerid); | ||||
| 	channel->callerid = NULL; | ||||
| 	if (channel->ani) free(channel->ani); | ||||
| 	channel->ani = NULL; | ||||
| 	if (strcasecmp(clid, "asreceived")) { | ||||
| 		if (channel->callerid) free(channel->callerid); | ||||
| 		channel->callerid = NULL; | ||||
| 		if (channel->ani) free(channel->ani); | ||||
| 		channel->ani = NULL; | ||||
| 	} | ||||
| 	if (channel->state == AST_STATE_UP) | ||||
| 	if (debug) printf("@@@@ Autodial:Line is Up\n"); | ||||
| 	if (option_verbose > 2) | ||||
| @@ -251,7 +259,6 @@ time_t	t; | ||||
| 		if (!f) | ||||
| 		   { | ||||
| 			if (debug) printf("@@@@ qcall_do:Hung Up\n"); | ||||
| 			ast_frfree(f); | ||||
| 			unlink(fname); | ||||
| 			break; | ||||
| 		   } | ||||
| @@ -274,22 +281,24 @@ time_t	t; | ||||
| 						ast_verbose(VERBOSE_PREFIX_3 "Qcall got answer on %s\n", | ||||
| 							channel->name); | ||||
| 					usleep(1500000); | ||||
| 					ast_streamfile(channel,ident,0); | ||||
| 					if (ast_readstring(channel,buf,strlen(reqinp),10000,5000,"#")) | ||||
| 					   { | ||||
| 					if (strlen(ident)) { | ||||
| 						ast_streamfile(channel,ident,0); | ||||
| 						if (ast_readstring(channel,buf,strlen(reqinp),10000,5000,"#")) | ||||
| 						{ | ||||
| 							ast_stopstream(channel); | ||||
| 							if (debug) printf("@@@@ qcall_do: timeout or hangup in dtmf read\n"); | ||||
| 							ast_frfree(f); | ||||
| 							break; | ||||
| 						} | ||||
| 						ast_stopstream(channel); | ||||
| 						if (debug) printf("@@@@ qcall_do: timeout or hangup in dtmf read\n"); | ||||
| 						if (strcmp(buf,reqinp)) /* if not match */ | ||||
| 						{ | ||||
| 							if (debug) printf("@@@@ qcall_do: response (%s) does not match required (%s)\n",buf,reqinp); | ||||
| 							ast_frfree(f); | ||||
| 							break; | ||||
| 						} | ||||
| 						ast_frfree(f); | ||||
| 						break; | ||||
| 					   } | ||||
| 					ast_stopstream(channel); | ||||
| 					if (strcmp(buf,reqinp)) /* if not match */ | ||||
| 					   { | ||||
| 						if (debug) printf("@@@@ qcall_do: response (%s) does not match required (%s)\n",buf,reqinp); | ||||
| 						ast_frfree(f); | ||||
| 						break; | ||||
| 					   } | ||||
| 					ast_frfree(f); | ||||
| 					} | ||||
| 					/* okay, now we go for it */ | ||||
| 					context = strchr(extstr,'@'); | ||||
| 					if (!context) context = "default"; | ||||
| @@ -297,15 +306,19 @@ time_t	t; | ||||
| 					if (option_verbose > 2) | ||||
| 						ast_verbose(VERBOSE_PREFIX_3 "Qcall got accept, now putting through to %s@%s on %s\n", | ||||
| 							extstr,context,channel->name); | ||||
| 					strcat(ident,"-ok"); | ||||
| 					  /* if file existant, play it */ | ||||
| 					if (!ast_streamfile(channel,ident,0)) | ||||
| 					   { | ||||
| 						ast_waitstream(channel,""); | ||||
| 						ast_stopstream(channel); | ||||
| 					   } | ||||
| 					channel->callerid = strdup(clid); | ||||
| 					channel->ani = strdup(clid); | ||||
| 					if (strlen(ident)) { | ||||
| 						strcat(ident,"-ok"); | ||||
| 						/* if file existant, play it */ | ||||
| 						if (!ast_streamfile(channel,ident,0)) | ||||
| 						{ | ||||
| 							ast_waitstream(channel,""); | ||||
| 							ast_stopstream(channel); | ||||
| 						} | ||||
| 					} | ||||
| 					if (strcasecmp(clid, "asreceived")) { | ||||
| 						channel->callerid = strdup(clid); | ||||
| 						channel->ani = strdup(clid); | ||||
| 					} | ||||
| 					channel->language[0] = 0; | ||||
| 					channel->dnid = strdup(extstr); | ||||
| #ifdef	AMAFLAGS | ||||
| @@ -324,6 +337,7 @@ time_t	t; | ||||
| 					strcpy(channel->exten,extstr); | ||||
| 					strcpy(channel->context,context); | ||||
| 					channel->priority = 1; | ||||
| 					printf("Caller ID is %s\n", channel->callerid); | ||||
| 					ast_pbx_run(channel); | ||||
| 					pthread_exit(NULL); | ||||
| 				} | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|   | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|  | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/channel.h> | ||||
| @@ -125,7 +126,7 @@ static void run_ras(struct ast_channel *chan, char *args) | ||||
| 			if (!res) { | ||||
| 				/* Check for hangup */ | ||||
| 				if (chan->softhangup && !signalled) { | ||||
| 					ast_log(LOG_DEBUG, "Channel hungup.  Signalling RAS at %d to die...\n", pid); | ||||
| 					ast_log(LOG_DEBUG, "Channel '%s' hungup.  Signalling RAS at %d to die...\n", chan->name, pid); | ||||
| 					kill(pid, SIGTERM); | ||||
| 					signalled=1; | ||||
| 				} | ||||
| @@ -147,7 +148,7 @@ static void run_ras(struct ast_channel *chan, char *args) | ||||
| 				} | ||||
| 			} | ||||
| 			/* Throw back into audio mode */ | ||||
| 			x = 0; | ||||
| 			x = 1; | ||||
| 			ioctl(chan->fds[0], ZT_AUDIOMODE, &x); | ||||
|  | ||||
| 			/* Double check buffering too */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user