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@465 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		
							
								
								
									
										63
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								Makefile
									
									
									
									
									
								
							| @@ -11,7 +11,6 @@ | ||||
| # the GNU General Public License | ||||
| # | ||||
|  | ||||
|  | ||||
| .EXPORT_ALL_VARIABLES: | ||||
|  | ||||
| INSTALL_PREFIX= | ||||
| @@ -22,14 +21,20 @@ AGI_DIR=$(INSTALL_PREFIX)/var/lib/asterisk/agi-bin | ||||
| # Pentium Pro Optimize | ||||
| #PROC=i686 | ||||
| # Pentium Optimize | ||||
| PROC=i586 | ||||
| #PROC=i586 | ||||
| #PROC=k6 | ||||
| #PROC=ppc | ||||
| PROC=$(shell uname -m) | ||||
|  | ||||
| DEBUG=-g #-pg | ||||
| INCLUDE=-Iinclude -I../include | ||||
| CFLAGS=-pipe  -Wall -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT | ||||
| CFLAGS=-pipe  -Wall -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE | ||||
| #CFLAGS+=-Werror | ||||
| CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi) | ||||
| CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi) | ||||
|  | ||||
| ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; fi) | ||||
| HTTPDIR=$(shell if [ -d /var/www ]; then echo "/var/www"; else echo "/home/httpd"; fi) | ||||
| RPMVERSION=$(shell sed 's/[-\/:]/_/g' .version) | ||||
| CFLAGS+=-DASTERISK_VERSION=\"$(ASTERISKVERSION)\" | ||||
| # Optional debugging parameters | ||||
| @@ -38,11 +43,11 @@ CFLAGS+= -DDO_CRASH -DDEBUG_THREADS | ||||
| #CLFAGS+= -DTRACE_FRAMES | ||||
| CFLAGS+=# -fomit-frame-pointer  | ||||
| SUBDIRS=res channels pbx apps codecs formats agi cdr | ||||
| LIBS=-ldl -lpthread -lreadline -lncurses -lm | ||||
| LIBS=-ldl -lpthread -lreadline -lncurses -lm #-lnjamd | ||||
| OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \ | ||||
| 	translate.o file.o say.o pbx.o cli.o md5.o \ | ||||
| 	translate.o file.o say.o pbx.o cli.o md5.o term.o \ | ||||
| 	ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \ | ||||
| 	cdr.o tdd.o asterisk.o  | ||||
| 	cdr.o tdd.o acl.o rtp.o asterisk.o  | ||||
| CC=gcc | ||||
| INSTALL=install | ||||
|  | ||||
| @@ -81,9 +86,10 @@ datafiles: all | ||||
| 	for x in sounds/digits/*; do \ | ||||
| 		install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds/digits ; \ | ||||
| 	done | ||||
| 	for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-*; do \ | ||||
| 	for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-*; do \ | ||||
| 		install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds ; \ | ||||
| 	done | ||||
| 	mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/mohmp3 | ||||
| 	mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/images | ||||
| 	for x in images/*.jpg; do \ | ||||
| 		install $$x $(INSTALL_PREFIX)/var/lib/asterisk/images ; \ | ||||
| @@ -93,8 +99,10 @@ datafiles: all | ||||
| install: all datafiles | ||||
| 	mkdir -p $(MODULES_DIR) | ||||
| 	mkdir -p $(INSTALL_PREFIX)/usr/sbin | ||||
| 	mkdir -p $(INSTALL_PREFIX)/etc/asterisk | ||||
| 	install -m 755 asterisk $(INSTALL_PREFIX)/usr/sbin/ | ||||
| 	install -m 755 astgenkey $(INSTALL_PREFIX)/usr/sbin/ | ||||
| 	install -m 755 safe_asterisk $(INSTALL_PREFIX)/usr/sbin/ | ||||
| 	for x in $(SUBDIRS); do $(MAKE) -C $$x install || exit 1 ; done | ||||
| 	install -d $(INSTALL_PREFIX)/usr/include/asterisk | ||||
| 	install include/asterisk/*.h $(INSTALL_PREFIX)/usr/include/asterisk | ||||
| @@ -128,7 +136,15 @@ install: all datafiles | ||||
| 	@echo " + **Note** This requires that you have      +" | ||||
| 	@echo " + doxygen installed on your local system    +" | ||||
| 	@echo " +-------------------------------------------+" | ||||
| samples: all datafiles | ||||
| adsi: all | ||||
| 	mkdir -p /etc/asterisk | ||||
| 	for x in configs/*.adsi; do \ | ||||
| 		if ! [ -f $(INSTALL_PREFIX)/etc/asterisk/$$x ]; then \ | ||||
| 			install -m 644 $$x $(INSTALL_PREFIX)/etc/asterisk/`basename $$x` ; \ | ||||
| 		fi ; \ | ||||
| 	done | ||||
|  | ||||
| samples: all datafiles adsi | ||||
| 	mkdir -p $(INSTALL_PREFIX)/etc/asterisk | ||||
| 	for x in configs/*.sample; do \ | ||||
| 		if [ -f $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample` ]; then \ | ||||
| @@ -139,6 +155,9 @@ samples: all datafiles | ||||
| 	for x in sounds/demo-*; do \ | ||||
| 		install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds; \ | ||||
| 	done | ||||
| 	for x in sounds/*.mp3; do \ | ||||
| 		install $$x $(INSTALL_PREFIX)/var/lib/asterisk/mohmp3 ; \ | ||||
| 	done | ||||
| 	mkdir -p $(INSTALL_PREFIX)/var/spool/asterisk/vm/1234/INBOX | ||||
| 	:> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/unavail.gsm | ||||
| 	for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isunavail; do \ | ||||
| @@ -149,6 +168,24 @@ samples: all datafiles | ||||
| 		cat $(INSTALL_PREFIX)/var/lib/asterisk/sounds/$$x.gsm >> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/busy.gsm ; \ | ||||
| 	done | ||||
|  | ||||
| webvmail: | ||||
| 	@[ -d $(HTTPDIR) ] || ( echo "No HTTP directory" && exit 1 ) | ||||
| 	@[ -d $(HTTPDIR)/html ] || ( echo "No http directory" && exit 1 ) | ||||
| 	@[ -d $(HTTPDIR)/cgi-bin ] || ( echo "No cgi-bin directory" && exit 1 ) | ||||
| 	install -m 4755 -o root -g root vmail.cgi $(HTTPDIR)/cgi-bin/vmail.cgi | ||||
| 	mkdir -p $(HTTPDIR)/html/_asterisk | ||||
| 	for x in images/*.gif; do \ | ||||
| 		install -m 644 $$x $(HTTPDIR)/html/_asterisk/; \ | ||||
| 	done | ||||
| 	@echo " +--------- Asterisk Web Voicemail ----------+"   | ||||
| 	@echo " +                                           +" | ||||
| 	@echo " + Asterisk Web Voicemail is installed in    +" | ||||
| 	@echo " + your cgi-bin directory.  IT USES A SETUID +" | ||||
| 	@echo " + ROOT PERL SCRIPT, SO IF YOU DON'T LIKE    +" | ||||
| 	@echo " + THAT, UNINSTALL IT!                       +" | ||||
| 	@echo " +                                           +" | ||||
| 	@echo " +-------------------------------------------+"   | ||||
|  | ||||
| mailbox: | ||||
| 	./addmailbox  | ||||
| 	 | ||||
| @@ -171,3 +208,13 @@ __rpm: _version | ||||
|  | ||||
| progdocs: | ||||
| 	doxygen asterisk-ng-doxygen | ||||
|  | ||||
| config: | ||||
| 	if [ -d /etc/rc.d/init.d ]; then \ | ||||
| 		install -m 755 init.asterisk /etc/rc.d/init.d/asterisk; \ | ||||
| 		/sbin/chkconfig --add asterisk; \ | ||||
| 	elif [ -d /etc/init.d ]; then \ | ||||
| 		install -m 755 init.asterisk /etc/init.d/asterisk; \ | ||||
| 	fi  | ||||
|  | ||||
| 	 | ||||
|   | ||||
							
								
								
									
										1567
									
								
								apps/app_adsiprog.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1567
									
								
								apps/app_adsiprog.c
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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> | ||||
| @@ -53,10 +54,10 @@ static int skel_exec(struct ast_channel *chan, void *data) | ||||
| 	/* Do our thing here */ | ||||
| 	res = system((char *)data); | ||||
| 	if (res < 0) { | ||||
| 		ast_log(LOG_WARNING, "Unable to execute '%s'\n", data); | ||||
| 		ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data); | ||||
| 		res = -1; | ||||
| 	} else if (res == 127) { | ||||
| 		ast_log(LOG_WARNING, "Unable to execute '%s'\n", data); | ||||
| 		ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data); | ||||
| 		res = -1; | ||||
| 	} else { | ||||
| 		if (res && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))  | ||||
|   | ||||
							
								
								
									
										449
									
								
								channel.c
									
									
									
									
									
								
							
							
						
						
									
										449
									
								
								channel.c
									
									
									
									
									
								
							| @@ -18,7 +18,9 @@ | ||||
| #include <sys/time.h> | ||||
| #include <signal.h> | ||||
| #include <errno.h> | ||||
| #include <asterisk/lock.h> | ||||
| #include <unistd.h> | ||||
| #include <math.h>			/* For PI */ | ||||
| #include <asterisk/frame.h> | ||||
| #include <asterisk/sched.h> | ||||
| #include <asterisk/options.h> | ||||
| @@ -28,6 +30,7 @@ | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/translate.h> | ||||
|  | ||||
| static int shutting_down = 0; | ||||
|  | ||||
| /* XXX Lock appropriately in more functions XXX */ | ||||
|  | ||||
| @@ -62,7 +65,7 @@ struct ast_channel *channels = NULL; | ||||
| /* Protect the channel list (highly unlikely that two things would change | ||||
|    it at the same time, but still! */ | ||||
|     | ||||
| static pthread_mutex_t chlock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t chlock = AST_MUTEX_INITIALIZER; | ||||
|  | ||||
| int ast_check_hangup(struct ast_channel *chan) | ||||
| { | ||||
| @@ -79,6 +82,45 @@ time_t	myt; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| void ast_begin_shutdown(int hangup) | ||||
| { | ||||
| 	struct ast_channel *c; | ||||
| 	shutting_down = 1; | ||||
| 	if (hangup) { | ||||
| 		PTHREAD_MUTEX_LOCK(&chlock); | ||||
| 		c = channels; | ||||
| 		while(c) { | ||||
| 			c->softhangup = 1; | ||||
| 			c = c->next; | ||||
| 		} | ||||
| 		PTHREAD_MUTEX_UNLOCK(&chlock); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int ast_active_channels(void) | ||||
| { | ||||
| 	struct ast_channel *c; | ||||
| 	int cnt = 0; | ||||
| 	PTHREAD_MUTEX_LOCK(&chlock); | ||||
| 	c = channels; | ||||
| 	while(c) { | ||||
| 		cnt++; | ||||
| 		c = c->next; | ||||
| 	} | ||||
| 	PTHREAD_MUTEX_UNLOCK(&chlock); | ||||
| 	return cnt; | ||||
| } | ||||
|  | ||||
| void ast_cancel_shutdown(void) | ||||
| { | ||||
| 	shutting_down = 0; | ||||
| } | ||||
|  | ||||
| int ast_shutting_down(void) | ||||
| { | ||||
| 	return shutting_down; | ||||
| } | ||||
|  | ||||
| void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset) | ||||
| { | ||||
| time_t	myt; | ||||
| @@ -189,11 +231,15 @@ int ast_best_codec(int fmts) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct ast_channel *ast_channel_alloc(void) | ||||
| struct ast_channel *ast_channel_alloc(int needqueue) | ||||
| { | ||||
| 	struct ast_channel *tmp; | ||||
| 	struct ast_channel_pvt *pvt; | ||||
| 	int x; | ||||
| 	int flags; | ||||
| 	/* If shutting down, don't allocate any new channels */ | ||||
| 	if (shutting_down) | ||||
| 		return NULL; | ||||
| 	PTHREAD_MUTEX_LOCK(&chlock); | ||||
| 	tmp = malloc(sizeof(struct ast_channel)); | ||||
| 	memset(tmp, 0, sizeof(struct ast_channel)); | ||||
| @@ -203,24 +249,43 @@ struct ast_channel *ast_channel_alloc(void) | ||||
| 			memset(pvt, 0, sizeof(struct ast_channel_pvt)); | ||||
| 			tmp->sched = sched_context_create(); | ||||
| 			if (tmp->sched) { | ||||
| 				for (x=0;x<AST_MAX_FDS;x++) | ||||
| 				for (x=0;x<AST_MAX_FDS - 1;x++) | ||||
| 					tmp->fds[x] = -1; | ||||
| 				strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1); | ||||
| 				tmp->pvt = pvt; | ||||
| 				tmp->state = AST_STATE_DOWN; | ||||
| 				tmp->stack = -1; | ||||
| 				tmp->streamid = -1; | ||||
| 				tmp->appl = NULL; | ||||
| 				tmp->data = NULL; | ||||
| 				pthread_mutex_init(&tmp->lock, NULL); | ||||
| 				strncpy(tmp->context, "default", sizeof(tmp->context)-1); | ||||
| 				strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1); | ||||
| 				strncpy(tmp->exten, "s", sizeof(tmp->exten)-1); | ||||
| 				tmp->priority=1; | ||||
| 				tmp->amaflags = ast_default_amaflags; | ||||
| 				strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1); | ||||
| 				tmp->next = channels; | ||||
| 				channels= tmp; | ||||
| 				if (needqueue &&   | ||||
| 					pipe(pvt->alertpipe)) { | ||||
| 					ast_log(LOG_WARNING, "Alert pipe creation failed!\n"); | ||||
| 					free(pvt); | ||||
| 					free(tmp); | ||||
| 					tmp = NULL; | ||||
| 					pvt = NULL; | ||||
| 				} else { | ||||
| 					/* Make sure we've got it done right if they don't */ | ||||
| 					if (needqueue) { | ||||
| 						flags = fcntl(pvt->alertpipe[0], F_GETFL); | ||||
| 						fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK); | ||||
| 						flags = fcntl(pvt->alertpipe[1], F_GETFL); | ||||
| 						fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK); | ||||
| 					} else | ||||
| 						pvt->alertpipe[0] = pvt->alertpipe[1] = -1; | ||||
| 					/* Always watch the alertpipe */ | ||||
| 					tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0]; | ||||
| 					strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1); | ||||
| 					tmp->pvt = pvt; | ||||
| 					tmp->state = AST_STATE_DOWN; | ||||
| 					tmp->stack = -1; | ||||
| 					tmp->streamid = -1; | ||||
| 					tmp->appl = NULL; | ||||
| 					tmp->data = NULL; | ||||
| 					ast_pthread_mutex_init(&tmp->lock); | ||||
| 					strncpy(tmp->context, "default", sizeof(tmp->context)-1); | ||||
| 					strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1); | ||||
| 					strncpy(tmp->exten, "s", sizeof(tmp->exten)-1); | ||||
| 					tmp->priority=1; | ||||
| 					tmp->amaflags = ast_default_amaflags; | ||||
| 					strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1); | ||||
| 					tmp->next = channels; | ||||
| 					channels= tmp; | ||||
| 				} | ||||
| 			} else { | ||||
| 				ast_log(LOG_WARNING, "Unable to create schedule context\n"); | ||||
| 				free(tmp); | ||||
| @@ -237,6 +302,56 @@ struct ast_channel *ast_channel_alloc(void) | ||||
| 	return tmp; | ||||
| } | ||||
|  | ||||
| int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock) | ||||
| { | ||||
| 	struct ast_frame *f; | ||||
| 	struct ast_frame *prev, *cur; | ||||
| 	int blah = 1; | ||||
| 	int qlen = 0; | ||||
| 	f = ast_frdup(fin); | ||||
| 	if (!f) { | ||||
| 		ast_log(LOG_WARNING, "Unable to duplicate frame\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (lock) | ||||
| 		ast_pthread_mutex_lock(&chan->lock); | ||||
| 	prev = NULL; | ||||
| 	cur = chan->pvt->readq; | ||||
| 	while(cur) { | ||||
| 		prev = cur; | ||||
| 		cur = cur->next; | ||||
| 		qlen++; | ||||
| 	} | ||||
| 	if (prev) | ||||
| 		prev->next = f; | ||||
| 	else | ||||
| 		chan->pvt->readq = f; | ||||
| 	if (chan->pvt->alertpipe[1] > -1) { | ||||
| 		if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) | ||||
| 			ast_log(LOG_WARNING, "Unable to write to alert pipe, frametype/subclass %d/%d (qlen = %d): %s!\n", | ||||
| 				f->frametype, f->subclass, qlen, strerror(errno)); | ||||
| 	} | ||||
| 	if (qlen  > 128) { | ||||
| 		ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name); | ||||
| 	} | ||||
| 	if (lock) | ||||
| 		ast_pthread_mutex_unlock(&chan->lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int ast_queue_hangup(struct ast_channel *chan, int lock) | ||||
| { | ||||
| 	struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP }; | ||||
| 	return ast_queue_frame(chan, &f, lock); | ||||
| } | ||||
|  | ||||
| int ast_queue_control(struct ast_channel *chan, int control, int lock) | ||||
| { | ||||
| 	struct ast_frame f = { AST_FRAME_CONTROL, }; | ||||
| 	f.subclass = control; | ||||
| 	return ast_queue_frame(chan, &f, lock); | ||||
| } | ||||
|  | ||||
| int ast_channel_defer_dtmf(struct ast_channel *chan) | ||||
| { | ||||
| 	int pre = 0; | ||||
| @@ -272,9 +387,28 @@ struct ast_channel *ast_channel_walk(struct ast_channel *prev) | ||||
| 	 | ||||
| } | ||||
|  | ||||
| int ast_safe_sleep(struct ast_channel *chan, int ms) | ||||
| { | ||||
| 	struct ast_frame *f; | ||||
| 	while(ms > 0) { | ||||
| 		ms = ast_waitfor(chan, ms); | ||||
| 		if (ms <0) | ||||
| 			return -1; | ||||
| 		if (ms > 0) { | ||||
| 			f = ast_read(chan); | ||||
| 			if (!f) | ||||
| 				return -1; | ||||
| 			ast_frfree(f); | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void ast_channel_free(struct ast_channel *chan) | ||||
| { | ||||
| 	struct ast_channel *last=NULL, *cur; | ||||
| 	int fd; | ||||
| 	struct ast_frame *f, *fp; | ||||
| 	PTHREAD_MUTEX_LOCK(&chlock); | ||||
| 	cur = channels; | ||||
| 	while(cur) { | ||||
| @@ -306,6 +440,17 @@ void ast_channel_free(struct ast_channel *chan) | ||||
| 	if (chan->ani) | ||||
| 		free(chan->ani); | ||||
| 	pthread_mutex_destroy(&chan->lock); | ||||
| 	/* Close pipes if appropriate */ | ||||
| 	if ((fd = chan->pvt->alertpipe[0]) > -1) | ||||
| 		close(fd); | ||||
| 	if ((fd = chan->pvt->alertpipe[1]) > -1) | ||||
| 		close(fd); | ||||
| 	f = chan->pvt->readq; | ||||
| 	while(f) { | ||||
| 		fp = f; | ||||
| 		f = f->next; | ||||
| 		ast_frfree(fp); | ||||
| 	} | ||||
| 	free(chan->pvt); | ||||
| 	free(chan); | ||||
| 	PTHREAD_MUTEX_UNLOCK(&chlock); | ||||
| @@ -359,6 +504,11 @@ int ast_hangup(struct ast_channel *chan) | ||||
| 		ast_stopstream(chan); | ||||
| 	if (chan->sched) | ||||
| 		sched_context_destroy(chan->sched); | ||||
| 	/* Clear any tone stuff remaining */ | ||||
| 	if (chan->generatordata) | ||||
| 		chan->generator->release(chan, chan->generatordata); | ||||
| 	chan->generatordata = NULL; | ||||
| 	chan->generator = NULL; | ||||
| 	if (chan->cdr) { | ||||
| 		/* End the CDR if it hasn't already */ | ||||
| 		ast_cdr_end(chan->cdr); | ||||
| @@ -434,6 +584,29 @@ int ast_answer(struct ast_channel *chan) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void ast_deactivate_generator(struct ast_channel *chan) | ||||
| { | ||||
| 	if (chan->generatordata) { | ||||
| 		chan->generator->release(chan, chan->generatordata); | ||||
| 		chan->generatordata = NULL; | ||||
| 		chan->writeinterrupt = 0; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params) | ||||
| { | ||||
| 	if (chan->generatordata) { | ||||
| 		chan->generator->release(chan, chan->generatordata); | ||||
| 		chan->generatordata = NULL; | ||||
| 	} | ||||
| 	if ((chan->generatordata = gen->alloc(chan, params))) { | ||||
| 		chan->generator = gen; | ||||
| 	} else { | ||||
| 		return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception) | ||||
| { | ||||
| 	/* Wait for x amount of time on a file descriptor to have input.  */ | ||||
| @@ -511,9 +684,10 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, | ||||
| 	tv.tv_usec = (*ms % 1000) * 1000; | ||||
| 	FD_ZERO(&rfds); | ||||
| 	FD_ZERO(&efds); | ||||
|  | ||||
| 	for (x=0;x<n;x++) { | ||||
| 		for (y=0;y<AST_MAX_FDS;y++) { | ||||
| 			if (c[x]->fds[y] > 0) { | ||||
| 			if (c[x]->fds[y] > -1) { | ||||
| 				FD_SET(c[x]->fds[y], &rfds); | ||||
| 				FD_SET(c[x]->fds[y], &efds); | ||||
| 				if (c[x]->fds[y] > max) | ||||
| @@ -623,12 +797,13 @@ char ast_waitfordigit(struct ast_channel *c, int ms) | ||||
| struct ast_frame *ast_read(struct ast_channel *chan) | ||||
| { | ||||
| 	struct ast_frame *f = NULL; | ||||
| 	int blah; | ||||
| 	static struct ast_frame null_frame =  | ||||
| 	{ | ||||
| 		AST_FRAME_NULL, | ||||
| 	}; | ||||
| 	 | ||||
| 	pthread_mutex_lock(&chan->lock); | ||||
| 	ast_pthread_mutex_lock(&chan->lock); | ||||
| 	if (chan->masq) { | ||||
| 		if (ast_do_masquerade(chan)) { | ||||
| 			ast_log(LOG_WARNING, "Failed to perform masquerade\n"); | ||||
| @@ -644,7 +819,7 @@ struct ast_frame *ast_read(struct ast_channel *chan) | ||||
| 		pthread_mutex_unlock(&chan->lock); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	if (!chan->deferdtmf && strlen(chan->dtmfq)) { | ||||
| 		/* We have DTMF that has been deferred.  Return it now */ | ||||
| 		chan->dtmff.frametype = AST_FRAME_DTMF; | ||||
| @@ -655,19 +830,35 @@ struct ast_frame *ast_read(struct ast_channel *chan) | ||||
| 		return &chan->dtmff; | ||||
| 	} | ||||
| 	 | ||||
| 	chan->blocker = pthread_self(); | ||||
| 	if (chan->exception) { | ||||
| 		if (chan->pvt->exception)  | ||||
| 			f = chan->pvt->exception(chan); | ||||
| 	/* Read and ignore anything on the alertpipe, but read only | ||||
| 	   one sizeof(blah) per frame that we send from it */ | ||||
| 	if (chan->pvt->alertpipe[0] > -1) { | ||||
| 		read(chan->pvt->alertpipe[0], &blah, sizeof(blah)); | ||||
| 	} | ||||
|  | ||||
| 	/* Check for pending read queue */ | ||||
| 	if (chan->pvt->readq) { | ||||
| 		f = chan->pvt->readq; | ||||
| 		chan->pvt->readq = f->next; | ||||
| 		/* Interpret hangup and return NULL */ | ||||
| 		if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) | ||||
| 			f = NULL; | ||||
| 	} else { | ||||
| 		chan->blocker = pthread_self(); | ||||
| 		if (chan->exception) { | ||||
| 			if (chan->pvt->exception)  | ||||
| 				f = chan->pvt->exception(chan); | ||||
| 			else | ||||
| 				ast_log(LOG_WARNING, "Exception flag set, but no exception handler\n"); | ||||
| 			/* Clear the exception flag */ | ||||
| 			chan->exception = 0; | ||||
| 		} else | ||||
| 		if (chan->pvt->read) | ||||
| 			f = chan->pvt->read(chan); | ||||
| 		else | ||||
| 			ast_log(LOG_WARNING, "Exception flag set, but no exception handler\n"); | ||||
| 		/* Clear the exception flag */ | ||||
| 		chan->exception = 0; | ||||
| 	} else | ||||
| 	if (chan->pvt->read) | ||||
| 		f = chan->pvt->read(chan); | ||||
| 	else | ||||
| 		ast_log(LOG_WARNING, "No read routine on channel %s\n", chan); | ||||
| 			ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name); | ||||
| 	} | ||||
|  | ||||
| 	if (f && (f->frametype == AST_FRAME_VOICE)) { | ||||
| 		if (chan->pvt->readtrans) { | ||||
| 			f = ast_translate(chan->pvt->readtrans, f, 1); | ||||
| @@ -675,6 +866,7 @@ struct ast_frame *ast_read(struct ast_channel *chan) | ||||
| 				f = &null_frame; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Make sure we always return NULL in the future */ | ||||
| 	if (!f) { | ||||
| 		chan->softhangup = 1; | ||||
| @@ -689,10 +881,26 @@ struct ast_frame *ast_read(struct ast_channel *chan) | ||||
| 		f = &null_frame; | ||||
| 	} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) { | ||||
| 		/* Answer the CDR */ | ||||
| 		chan->state = AST_STATE_UP; | ||||
| 		ast_cdr_answer(chan->cdr); | ||||
| 	} | ||||
| 	pthread_mutex_unlock(&chan->lock); | ||||
|  | ||||
| 	/* Run any generator sitting on the line */ | ||||
| 	if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) { | ||||
| 		/* Mask generator data temporarily */ | ||||
| 		void *tmp; | ||||
| 		int res; | ||||
| 		tmp = chan->generatordata; | ||||
| 		chan->generatordata = NULL; | ||||
| 		res = chan->generator->generate(chan, tmp, f->datalen); | ||||
| 		chan->generatordata = tmp; | ||||
| 		if (res) { | ||||
| 			ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); | ||||
| 			ast_deactivate_generator(chan); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return f; | ||||
| } | ||||
|  | ||||
| @@ -769,6 +977,12 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) | ||||
| 	} | ||||
| 	if (chan->masqr) | ||||
| 		return 0; | ||||
| 	if (chan->generatordata) { | ||||
| 		if (chan->writeinterrupt) | ||||
| 			ast_deactivate_generator(chan); | ||||
| 		else | ||||
| 			return 0; | ||||
| 	} | ||||
| 	CHECK_BLOCKING(chan); | ||||
| 	switch(fr->frametype) { | ||||
| 	case AST_FRAME_CONTROL: | ||||
| @@ -796,6 +1010,9 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) | ||||
| 		} | ||||
| 	} | ||||
| 	chan->blocking = 0; | ||||
| 	/* Consider a write failure to force a soft hangup */ | ||||
| 	if (res < 0) | ||||
| 		chan->softhangup = 1; | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| @@ -899,7 +1116,7 @@ int ast_call(struct ast_channel *chan, char *addr, int timeout) | ||||
| 	   return anyway.  */ | ||||
| 	int res = -1; | ||||
| 	/* Stop if we're a zombie or need a soft hangup */ | ||||
| 	pthread_mutex_lock(&chan->lock); | ||||
| 	ast_pthread_mutex_lock(&chan->lock); | ||||
| 	if (!chan->zombie && !ast_check_hangup(chan))  | ||||
| 		if (chan->pvt->call) | ||||
| 			res = chan->pvt->call(chan, addr, timeout); | ||||
| @@ -975,19 +1192,19 @@ int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *pe | ||||
| 	chanf = chan->nativeformats; | ||||
| 	res = ast_translator_best_choice(&peerf, &chanf); | ||||
| 	if (res < 0) { | ||||
| 		ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan, chan->nativeformats, peer, peer->nativeformats); | ||||
| 		ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* Set read format on channel */ | ||||
| 	res = ast_set_read_format(chan, peerf); | ||||
| 	if (res < 0) { | ||||
| 		ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan, chanf); | ||||
| 		ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* Set write format on peer channel */ | ||||
| 	res = ast_set_write_format(peer, peerf); | ||||
| 	if (res < 0) { | ||||
| 		ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer, peerf); | ||||
| 		ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* Now we go the other way */ | ||||
| @@ -995,19 +1212,19 @@ int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *pe | ||||
| 	chanf = chan->nativeformats; | ||||
| 	res = ast_translator_best_choice(&chanf, &peerf); | ||||
| 	if (res < 0) { | ||||
| 		ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer, peer->nativeformats, chan, chan->nativeformats); | ||||
| 		ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* Set writeformat on channel */ | ||||
| 	res = ast_set_write_format(chan, chanf); | ||||
| 	if (res < 0) { | ||||
| 		ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan, chanf); | ||||
| 		ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* Set read format on peer channel */ | ||||
| 	res = ast_set_read_format(peer, chanf); | ||||
| 	if (res < 0) { | ||||
| 		ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer, peerf); | ||||
| 		ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| @@ -1057,7 +1274,7 @@ static int ast_do_masquerade(struct ast_channel *original) | ||||
| 	free_translation(original); | ||||
|  | ||||
| 	/* We need the clone's lock, too */ | ||||
| 	pthread_mutex_lock(&clone->lock); | ||||
| 	ast_pthread_mutex_lock(&clone->lock); | ||||
|  | ||||
| 	/* Unlink the masquerade */ | ||||
| 	original->masq = NULL; | ||||
| @@ -1224,7 +1441,8 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags | ||||
| 		} | ||||
| 	 | ||||
| 			 | ||||
| 		if ((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat)) { | ||||
| 		if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat)) && | ||||
| 			!(c0->generator || c1->generator))  { | ||||
| 			if (ast_channel_make_compatible(c0, c1)) { | ||||
| 				ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); | ||||
| 				return -1; | ||||
| @@ -1282,10 +1500,14 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags | ||||
| 				last = who; | ||||
| #endif | ||||
| tackygoto: | ||||
| 				if (who == c0)  | ||||
| 					ast_write(c1, f); | ||||
| 				else  | ||||
| 					ast_write(c0, f); | ||||
| 				/* Don't copy packets if there is a generator on either one, since they're | ||||
| 				   not supposed to be listening anyway */ | ||||
| 				if (!c0->generator && !c1->generator) { | ||||
| 					if (who == c0)  | ||||
| 						ast_write(c1, f); | ||||
| 					else  | ||||
| 						ast_write(c0, f); | ||||
| 				} | ||||
| 			} | ||||
| 			ast_frfree(f); | ||||
| 		} else | ||||
| @@ -1320,3 +1542,136 @@ int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct tonepair_def { | ||||
| 	int freq1; | ||||
| 	int freq2; | ||||
| 	int duration; | ||||
| 	int vol; | ||||
| }; | ||||
|  | ||||
| struct tonepair_state { | ||||
| 	float freq1; | ||||
| 	float freq2; | ||||
| 	float vol; | ||||
| 	int duration; | ||||
| 	int pos; | ||||
| 	int origrfmt; | ||||
| 	int origwfmt; | ||||
| 	struct ast_frame f; | ||||
| 	unsigned char offset[AST_FRIENDLY_OFFSET]; | ||||
| 	short data[4000]; | ||||
| }; | ||||
|  | ||||
| static void tonepair_release(struct ast_channel *chan, void *params) | ||||
| { | ||||
| 	struct tonepair_state *ts = params; | ||||
| 	if (chan) { | ||||
| 		ast_set_write_format(chan, ts->origwfmt); | ||||
| 		ast_set_read_format(chan, ts->origrfmt); | ||||
| 	} | ||||
| 	free(ts); | ||||
| } | ||||
|  | ||||
| static void * tonepair_alloc(struct ast_channel *chan, void *params) | ||||
| { | ||||
| 	struct tonepair_state *ts; | ||||
| 	struct tonepair_def *td = params; | ||||
| 	ts = malloc(sizeof(struct tonepair_state)); | ||||
| 	if (!ts) | ||||
| 		return NULL; | ||||
| 	memset(ts, 0, sizeof(struct tonepair_state)); | ||||
| 	ts->origrfmt = chan->readformat; | ||||
| 	ts->origwfmt = chan->writeformat; | ||||
| 	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { | ||||
| 		ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name); | ||||
| 		tonepair_release(NULL, ts); | ||||
| 		ts = NULL; | ||||
| 	} else if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { | ||||
| 		ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (read)\n", chan->name); | ||||
| 		ast_set_write_format(chan, ts->origwfmt); | ||||
| 		tonepair_release(NULL, ts); | ||||
| 		ts = NULL; | ||||
| 	} else { | ||||
| 		ts->freq1 = td->freq1; | ||||
| 		ts->freq2 = td->freq2; | ||||
| 		ts->duration = td->duration; | ||||
| 		ts->vol = td->vol; | ||||
| 	} | ||||
| 	/* Let interrupts interrupt :) */ | ||||
| 	chan->writeinterrupt = 1; | ||||
| 	return ts; | ||||
| } | ||||
|  | ||||
| static int tonepair_generator(struct ast_channel *chan, void *data, int len) | ||||
| { | ||||
| 	struct tonepair_state *ts = data; | ||||
| 	int x; | ||||
| 	if (len > sizeof(ts->data) / 2 - 1) { | ||||
| 		ast_log(LOG_WARNING, "Can't generate that much data!\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	memset(&ts->f, 0, sizeof(ts->f)); | ||||
| 	for (x=0;x<len/2;x++) { | ||||
| 		ts->data[x] = ts->vol * ( | ||||
| 				sin((ts->freq1 * 2.0 * M_PI / 8000.0) * (ts->pos + x)) + | ||||
| 				sin((ts->freq2 * 2.0 * M_PI / 8000.0) * (ts->pos + x)) | ||||
| 			); | ||||
| 	} | ||||
| 	ts->f.frametype = AST_FRAME_VOICE; | ||||
| 	ts->f.subclass = AST_FORMAT_SLINEAR; | ||||
| 	ts->f.datalen = len; | ||||
| 	ts->f.timelen = len/8; | ||||
| 	ts->f.offset = AST_FRIENDLY_OFFSET; | ||||
| 	ts->f.data = ts->data; | ||||
| 	ast_write(chan, &ts->f); | ||||
| 	ts->pos += x; | ||||
| 	if (ts->duration > 0) { | ||||
| 		if (ts->pos >= ts->duration * 8) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static struct ast_generator tonepair = { | ||||
| 	alloc: tonepair_alloc, | ||||
| 	release: tonepair_release, | ||||
| 	generate: tonepair_generator, | ||||
| }; | ||||
|  | ||||
| int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol) | ||||
| { | ||||
| 	struct tonepair_def d = { 0, }; | ||||
| 	d.freq1 = freq1; | ||||
| 	d.freq2 = freq2; | ||||
| 	d.duration = duration; | ||||
| 	if (vol < 1) | ||||
| 		d.vol = 8192; | ||||
| 	else | ||||
| 		d.vol = vol; | ||||
| 	if (ast_activate_generator(chan, &tonepair, &d)) | ||||
| 		return -1; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void ast_tonepair_stop(struct ast_channel *chan) | ||||
| { | ||||
| 	ast_deactivate_generator(chan); | ||||
| } | ||||
|  | ||||
| int ast_tonepair(struct ast_channel *chan, int freq1, int freq2, int duration, int vol) | ||||
| { | ||||
| 	struct ast_frame *f; | ||||
| 	int res; | ||||
| 	if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol))) | ||||
| 		return res; | ||||
|  | ||||
| 	/* Give us some wiggle room */ | ||||
| 	while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) { | ||||
| 		f = ast_read(chan); | ||||
| 		if (f) | ||||
| 			ast_frfree(f); | ||||
| 		else | ||||
| 			return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|   | ||||
| @@ -80,7 +80,7 @@ struct vofr_hdr { | ||||
| 	u_int8_t cid;			/* Channel ID */ | ||||
| 	u_int8_t mod:4;			/* Modulation */ | ||||
| 	u_int8_t remid:4;		/* Remote ID */ | ||||
| #elif __BYTE__ORDER == __BIG_ENDIAN | ||||
| #elif __BYTE_ORDER == __BIG_ENDIAN | ||||
| 	u_int8_t ctag:4;		/* Connect tag */ | ||||
| 	u_int8_t dtype:4;		/* Data type */ | ||||
| 	u_int8_t vflags:4;		/* Voice Routing Flags */ | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include <stdio.h> | ||||
| #include <pthread.h> | ||||
| #include <string.h> | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/channel.h> | ||||
| #include <asterisk/channel_pvt.h> | ||||
| #include <asterisk/config.h> | ||||
| @@ -55,14 +56,14 @@ static int silencesupression = 0; | ||||
|  | ||||
| static int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW; | ||||
|  | ||||
| static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER; | ||||
|  | ||||
| /* Protect the interface list (of phone_pvt's) */ | ||||
| static pthread_mutex_t iflock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t iflock = AST_MUTEX_INITIALIZER; | ||||
|  | ||||
| /* Protect the monitoring thread, so only one process can kill or start it, and not | ||||
|    when it's doing something critical. */ | ||||
| static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t monlock = AST_MUTEX_INITIALIZER; | ||||
|  | ||||
| /* This is the thread for the monitor which checks for input on the channels | ||||
|    which are not currently in use.  */ | ||||
| @@ -140,7 +141,31 @@ static int phone_digit(struct ast_channel *ast, char digit) | ||||
| static int phone_call(struct ast_channel *ast, char *dest, int timeout) | ||||
| { | ||||
| 	struct phone_pvt *p; | ||||
| 	struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_RINGING }; | ||||
|  | ||||
| 	// CID stuff for the phonejack... | ||||
|  | ||||
| 	PHONE_CID cid; | ||||
| 	time_t UtcTime; | ||||
| 	struct tm *t; | ||||
|  | ||||
|  | ||||
| 	if (ast->callerid) { | ||||
| 		time(&UtcTime); | ||||
| 		t = localtime(&UtcTime); | ||||
|  | ||||
| 		if(t != NULL) { | ||||
| 			sprintf(cid.month, "%02d",(t->tm_mon + 1)); | ||||
| 			sprintf(cid.day, "%02d", t->tm_mday); | ||||
| 			sprintf(cid.hour, "%02d", t->tm_hour); | ||||
| 			sprintf(cid.min, "%02d", t->tm_min); | ||||
| 		} | ||||
| 		strcpy(cid.name, "Unknown"); | ||||
| 		sprintf(cid.number,"%s",ast->callerid); | ||||
| 	} | ||||
|  | ||||
| 	p = ast->pvt->pvt; | ||||
|  | ||||
| 	if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) { | ||||
| 		ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name); | ||||
| 		return -1; | ||||
| @@ -149,7 +174,9 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout) | ||||
| 	   ring the phone and wait for someone to answer */ | ||||
| 	if (option_debug) | ||||
| 		ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]); | ||||
| 	ioctl(p->fd, PHONE_RING_START); | ||||
|  | ||||
| 	ioctl(p->fd, PHONE_RING_START,&cid); | ||||
| 	ast_queue_frame(ast, &f, 0); | ||||
| 	ast->state = AST_STATE_RINGING; | ||||
| 	return 0; | ||||
| } | ||||
| @@ -336,7 +363,7 @@ static struct ast_frame  *phone_exception(struct ast_channel *ast) | ||||
| 	if (phonee.bits.pstn_ring) | ||||
| 		ast_verbose("Unit is ringing\n"); | ||||
| 	if (phonee.bits.caller_id) { | ||||
| 		ast_verbose("We have caller ID: %s\n"); | ||||
| 		ast_verbose("We have caller ID\n"); | ||||
| 	} | ||||
| 	if (phonee.bits.pstn_wink) | ||||
| 		ast_verbose("Detected Wink\n"); | ||||
| @@ -351,6 +378,7 @@ static struct ast_frame  *phone_read(struct ast_channel *ast) | ||||
| { | ||||
| 	int res; | ||||
| 	struct phone_pvt *p = ast->pvt->pvt; | ||||
| 	 | ||||
|  | ||||
| 	/* Some nice norms */ | ||||
| 	p->fr.datalen = 0; | ||||
| @@ -448,14 +476,13 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) | ||||
| 	char tmpbuf[4]; | ||||
| 	/* Write a frame of (presumably voice) data */ | ||||
| 	if (frame->frametype != AST_FRAME_VOICE) { | ||||
| 		ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype); | ||||
| 		ast_frfree(frame); | ||||
| 		return -1; | ||||
| 		if (frame->frametype != AST_FRAME_IMAGE) | ||||
| 			ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (!(frame->subclass & | ||||
| 		(AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW))) { | ||||
| 		ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); | ||||
| 		ast_frfree(frame); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* If we're not in up mode, go into up mode now */ | ||||
| @@ -560,17 +587,20 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) | ||||
| 			res = phone_write_buf(p, pos, expected, maxfr); | ||||
| 		} | ||||
| 		if (res != expected) { | ||||
| 			if (res < 0)  | ||||
| 				ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno)); | ||||
| /* | ||||
|  * Card is in non-blocking mode now and it works well now, but there are | ||||
|  * lot of messages like this. So, this message is temporarily disabled. | ||||
|  */ | ||||
| 			if (errno != EAGAIN) { | ||||
| 				if (res < 0)  | ||||
| 					ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno)); | ||||
| 	/* | ||||
| 	 * Card is in non-blocking mode now and it works well now, but there are | ||||
| 	 * lot of messages like this. So, this message is temporarily disabled. | ||||
| 	 */ | ||||
| #if 0 | ||||
| 			else | ||||
| 				ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen); | ||||
| 				else | ||||
| 					ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen); | ||||
| #endif | ||||
| 			return -1; | ||||
| 				return -1; | ||||
| 			} else /* Pretend it worked */ | ||||
| 				res = expected; | ||||
| 		} | ||||
| 		sofar += res; | ||||
| 		pos += res; | ||||
| @@ -581,7 +611,7 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame) | ||||
| static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *context) | ||||
| { | ||||
| 	struct ast_channel *tmp; | ||||
| 	tmp = ast_channel_alloc(); | ||||
| 	tmp = ast_channel_alloc(1); | ||||
| 	if (tmp) { | ||||
| 		snprintf(tmp->name, sizeof(tmp->name), "Phone/%s", i->dev + 5); | ||||
| 		tmp->type = type; | ||||
|   | ||||
| @@ -25,6 +25,8 @@ CFLAGS+= | ||||
| LIBG723=g723.1/libg723.a | ||||
| LIBG723B=g723.1b/libg723b.a | ||||
| LIBGSM=gsm/lib/libgsm.a | ||||
| LIBGSM=$(shell if uname -m | grep -q 86; then echo gsm/lib/libgsm.a; else echo "-lgsm" ; fi) | ||||
| LIBGSMT=$(shell if uname -m | grep -q 86; then echo gsm/lib/libgsm.a; fi) | ||||
| LIBMP3=mp3/libmp3.a | ||||
| LIBLPC10=lpc10/liblpc10.a | ||||
|  | ||||
| @@ -44,7 +46,7 @@ clean: | ||||
| $(LIBG723): | ||||
| 	make -C g723.1 all | ||||
|  | ||||
| $(LIBGSM): | ||||
| gsm/lib/libgsm.a: | ||||
| 	make -C gsm lib/libgsm.a | ||||
|  | ||||
| $(LIBG723B): | ||||
| @@ -65,7 +67,7 @@ codec_g723_1b.o : codec_g723_1.c | ||||
| codec_g723_1b.so : codec_g723_1b.o $(LIBG723B) | ||||
| 	$(CC) -shared -Xlinker -x -o $@ $< $(LIBG723B) -lm | ||||
|  | ||||
| codec_gsm.so: codec_gsm.o $(LIBGSM) | ||||
| codec_gsm.so: codec_gsm.o $(LIBGSMT)  | ||||
| 	$(CC) -shared -Xlinker -x -o $@ $< $(LIBGSM) | ||||
|  | ||||
| codec_lpc10.so: codec_lpc10.o $(LIBLPC10) | ||||
|   | ||||
| @@ -22,7 +22,8 @@ LIB_TARGET_DIR = . | ||||
| #  | ||||
|  | ||||
| WARNINGS = -Wall -Wno-comment -Wno-error | ||||
| CFLAGS = -O6 -mpentium -I$(LIB_TARGET_DIR) $(WARNINGS) | ||||
| CFLAGS = -O6 -I$(LIB_TARGET_DIR) $(WARNINGS) | ||||
| CFLAGS+= $(shell if uname -m | grep -q 86; then echo "-mpentium" ; fi) | ||||
|  | ||||
| LIB = $(LIB_TARGET_DIR)/liblpc10.a | ||||
|  | ||||
|   | ||||
| @@ -80,7 +80,7 @@ static int jpeg_write_image(int fd, struct ast_frame *fr) | ||||
| 	if (fr->datalen) { | ||||
| 		res = write(fd, fr->data, fr->datalen); | ||||
| 		if (res != fr->datalen) { | ||||
| 			ast_log(LOG_WARNING, "Only wrote %d of %d bytes: %s\n", res, fr->datalen); | ||||
| 			ast_log(LOG_WARNING, "Only wrote %d of %d bytes: %s\n", res, fr->datalen, strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|   | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/channel.h> | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/logger.h> | ||||
| @@ -51,7 +52,7 @@ struct ast_filestream { | ||||
|  | ||||
|  | ||||
| static struct ast_filestream *glist = NULL; | ||||
| static pthread_mutex_t wav_lock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t wav_lock = AST_MUTEX_INITIALIZER; | ||||
| static int glistcnt = 0; | ||||
|  | ||||
| static char *name = "wav"; | ||||
| @@ -167,7 +168,7 @@ static int check_header(int fd) | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (read(fd, &bisam, 2) != 2) { | ||||
| 		ast_log(LOG_WARNING, "Read failed (Bits Per Sample): &d\n", ltohs(bisam)); | ||||
| 		ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam)); | ||||
| 		return -1; | ||||
| 	} | ||||
|         /* Begin data chunk */ | ||||
|   | ||||
| @@ -37,7 +37,8 @@ extern "C" { | ||||
|  * ast_log(LOG_WHATEVER, "Problem with the %s Captain.  We should get some more.  Will %d be enough?", "flux capacitor", 10); | ||||
|  * where WHATEVER is one of ERROR, DEBUG, EVENT, NOTICE, or WARNING depending on which log you wish to output to. | ||||
|  */ | ||||
| extern void ast_log(int level, char *file, int line, char *function, char *fmt, ...); | ||||
| extern void ast_log(int level, char *file, int line, char *function, char *fmt, ...) | ||||
| 	__attribute__ ((format (printf, 5, 6))); | ||||
|  | ||||
| //! Send a verbose message (based on verbose level) | ||||
| /*! | ||||
| @@ -47,7 +48,8 @@ extern void ast_log(int level, char *file, int line, char *function, char *fmt, | ||||
|  * Note the abscence of a comma after the VERBOSE_PREFIX_3.  This is important. | ||||
|  * VERBOSE_PREFIX_1 through VERBOSE_PREFIX_3 are defined. | ||||
|  */ | ||||
| extern void ast_verbose(char *fmt, ...); | ||||
| extern void ast_verbose(char *fmt, ...) | ||||
| 	__attribute__ ((format (printf, 1, 2))); | ||||
|  | ||||
| extern int ast_register_verbose(void (*verboser)(char *string, int opos, int replacelast, int complete)); | ||||
| extern int ast_unregister_verbose(void (*verboser)(char *string, int opos, int replacelast, int complete)); | ||||
|   | ||||
							
								
								
									
										39
									
								
								logger.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								logger.c
									
									
									
									
									
								
							| @@ -15,10 +15,12 @@ | ||||
| #include <stdio.h> | ||||
| #include <unistd.h> | ||||
| #include <time.h> | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/logger.h> | ||||
| #include <asterisk/options.h> | ||||
| #include <asterisk/channel.h> | ||||
| #include <asterisk/config.h> | ||||
| #include <asterisk/term.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <errno.h> | ||||
| @@ -30,8 +32,8 @@ | ||||
|  | ||||
| #define MAX_MSG_QUEUE 200 | ||||
|  | ||||
| static pthread_mutex_t msglist_lock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t loglock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t msglist_lock = AST_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t loglock = AST_MUTEX_INITIALIZER; | ||||
|  | ||||
| static struct msglist { | ||||
| 	char *msg; | ||||
| @@ -59,6 +61,14 @@ static char *levels[] = { | ||||
| 	"ERROR" | ||||
| }; | ||||
|  | ||||
| static int colors[] = { | ||||
| 	COLOR_BRGREEN, | ||||
| 	COLOR_BRBLUE, | ||||
| 	COLOR_YELLOW, | ||||
| 	COLOR_BRRED, | ||||
| 	COLOR_RED | ||||
| }; | ||||
|  | ||||
| static int make_components(char *s, int lineno) | ||||
| { | ||||
| 	char *w; | ||||
| @@ -207,14 +217,21 @@ int reload_logger(void) | ||||
| extern void ast_log(int level, char *file, int line, char *function, char *fmt, ...) | ||||
| { | ||||
| 	char date[256]; | ||||
| 	char tmp[80]; | ||||
| 	char tmp2[80]; | ||||
| 	char tmp3[80]; | ||||
| 	char tmp4[80]; | ||||
| 	char linestr[80]; | ||||
| 	time_t t; | ||||
| 	struct tm *tm; | ||||
| 	struct logfile *f; | ||||
|  | ||||
| 	va_list ap; | ||||
| 	va_start(ap, fmt); | ||||
| 	if (!option_verbose && !option_debug && (!level)) | ||||
| 	if (!option_verbose && !option_debug && (!level)) { | ||||
| 		va_end(ap); | ||||
| 		return; | ||||
| 	} | ||||
| 	ast_pthread_mutex_lock(&loglock); | ||||
| 	if (level == 1 /* Event */) { | ||||
| 		time(&t); | ||||
| @@ -226,7 +243,9 @@ extern void ast_log(int level, char *file, int line, char *function, char *fmt, | ||||
| 			vfprintf(eventlog, fmt, ap); | ||||
| 			fflush(eventlog); | ||||
| 		} else | ||||
| 			ast_log(LOG_WARNING, "Unable to retrieve local time?\n"); | ||||
| 			/** Cannot use ast_log() from locked section of ast_log()! | ||||
| 			    ast_log(LOG_WARNING, "Unable to retrieve local time?\n"); **/ | ||||
| 			fprintf(stderr, "ast_log: Unable to retrieve local time for %d?\n", t); | ||||
| 	} else { | ||||
| 		if (logfiles) { | ||||
| 			f = logfiles; | ||||
| @@ -238,16 +257,26 @@ extern void ast_log(int level, char *file, int line, char *function, char *fmt, | ||||
| 						strftime(date, sizeof(date), "%b %e %T", tm); | ||||
| 						fprintf(f->f, "%s %s[%ld]: File %s, Line %d (%s): ", date, levels[level], pthread_self(), file, line, function); | ||||
| 					} else { | ||||
| 						fprintf(f->f, "%s[%ld]: File %s, Line %d (%s): ", levels[level], pthread_self(), file, line, function); | ||||
| 						sprintf(linestr, "%d", line); | ||||
| 						fprintf(f->f, "%s[%ld]: File %s, Line %s (%s): ", | ||||
| 																term_color(tmp, levels[level], colors[level], 0, sizeof(tmp)), | ||||
| 																pthread_self(), | ||||
| 																term_color(tmp2, file, COLOR_BRWHITE, 0, sizeof(tmp2)), | ||||
| 																term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)), | ||||
| 																term_color(tmp4, function, COLOR_BRWHITE, 0, sizeof(tmp4))); | ||||
| 					} | ||||
| 					vfprintf(f->f, fmt, ap); | ||||
| 					va_start(ap, fmt); | ||||
| 					fflush(f->f); | ||||
| 					va_end(ap); | ||||
| 				} | ||||
| 				f = f->next; | ||||
| 			} | ||||
| 		} else { | ||||
| 			fprintf(stdout, "%s[%ld]: File %s, Line %d (%s): ", levels[level], pthread_self(), file, line, function); | ||||
| 			va_start(ap, fmt); | ||||
| 			vfprintf(stdout, fmt, ap); | ||||
| 			va_end(ap); | ||||
| 			fflush(stdout); | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										417
									
								
								pbx.c
									
									
									
									
									
								
							
							
						
						
									
										417
									
								
								pbx.c
									
									
									
									
									
								
							| @@ -11,7 +11,7 @@ | ||||
|  * the GNU General Public License | ||||
|  */ | ||||
|  | ||||
| #include <pthread.h> | ||||
| #include <asterisk/lock.h> | ||||
| #include <asterisk/cli.h> | ||||
| #include <asterisk/pbx.h> | ||||
| #include <asterisk/channel.h> | ||||
| @@ -20,6 +20,7 @@ | ||||
| #include <asterisk/file.h> | ||||
| #include <asterisk/callerid.h> | ||||
| #include <asterisk/cdr.h> | ||||
| #include <asterisk/term.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <stdlib.h> | ||||
| @@ -71,7 +72,13 @@ struct ast_exten { | ||||
|  | ||||
| struct ast_include { | ||||
| 	char name[AST_MAX_EXTENSION]; | ||||
| 	char rname[AST_MAX_EXTENSION]; | ||||
| 	char *registrar; | ||||
| 	int hastime; | ||||
| 	unsigned int monthmask; | ||||
| 	unsigned int daymask; | ||||
| 	unsigned int dowmask; | ||||
| 	unsigned int minmask[24]; | ||||
| 	struct ast_include *next; | ||||
| }; | ||||
|  | ||||
| @@ -244,14 +251,14 @@ static struct pbx_builtin { | ||||
| }; | ||||
|  | ||||
| /* Lock for the application list */ | ||||
| static pthread_mutex_t applock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t applock = AST_MUTEX_INITIALIZER; | ||||
| static struct ast_context *contexts = NULL; | ||||
| /* Lock for the ast_context list */ | ||||
| static pthread_mutex_t conlock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t conlock = AST_MUTEX_INITIALIZER; | ||||
| static struct ast_app *apps = NULL; | ||||
|  | ||||
| /* Lock for switches */ | ||||
| static pthread_mutex_t switchlock = PTHREAD_MUTEX_INITIALIZER; | ||||
| static pthread_mutex_t switchlock = AST_MUTEX_INITIALIZER; | ||||
| struct ast_switch *switches = NULL; | ||||
|  | ||||
| int pbx_exec(struct ast_channel *c, /* Channel */ | ||||
| @@ -342,6 +349,47 @@ static struct ast_switch *pbx_findswitch(char *sw) | ||||
| 	return asw; | ||||
| } | ||||
|  | ||||
| static inline int include_valid(struct ast_include *i) | ||||
| { | ||||
| 	struct tm *tm; | ||||
| 	time_t t; | ||||
| 	if (!i->hastime) | ||||
| 		return 1; | ||||
| 	time(&t); | ||||
| 	tm = localtime(&t); | ||||
| 	if (!tm) { | ||||
| 		ast_log(LOG_WARNING, "Failed to get local time\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* If it's not the right month, return */ | ||||
| 	if (!(i->monthmask & (1 << tm->tm_mon))) { | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* If it's not that time of the month.... */ | ||||
| 	if (!(i->daymask & (1 << tm->tm_mday))) | ||||
| 		return 0; | ||||
|  | ||||
| 	/* If it's not the right day of the week */ | ||||
| 	if (!(i->dowmask & (1 << tm->tm_wday))) | ||||
| 		return 0; | ||||
|  | ||||
| 	/* Sanity check the hour just to be safe */ | ||||
| 	if ((tm->tm_hour < 0) || (tm->tm_hour > 23)) { | ||||
| 		ast_log(LOG_WARNING, "Insane time...\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Now the tough part, we calculate if it fits | ||||
| 	   in the right time based on min/hour */ | ||||
| 	if (!(i->minmask[tm->tm_hour] & (1 << (tm->tm_min / 2)))) | ||||
| 		return 0; | ||||
|  | ||||
| 	/* If we got this far, then we're good */ | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static void pbx_destroy(struct ast_pbx *p) | ||||
| { | ||||
| 	free(p); | ||||
| @@ -561,10 +609,12 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, char *cont | ||||
| 			/* Now try any includes we have in this context */ | ||||
| 			i = tmp->includes; | ||||
| 			while(i) { | ||||
| 				if ((e = pbx_find_extension(chan, i->name, exten, priority, callerid, action, incstack, stacklen, status, swo, data)))  | ||||
| 					return e; | ||||
| 				if (*swo)  | ||||
| 					return NULL; | ||||
| 				if (include_valid(i)) { | ||||
| 					if ((e = pbx_find_extension(chan, i->rname, exten, priority, callerid, action, incstack, stacklen, status, swo, data)))  | ||||
| 						return e; | ||||
| 					if (*swo)  | ||||
| 						return NULL; | ||||
| 				} | ||||
| 				i = i->next; | ||||
| 			} | ||||
| 		} | ||||
| @@ -584,6 +634,9 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte | ||||
| 	int status = 0; | ||||
| 	char *incstack[AST_PBX_MAX_STACK]; | ||||
| 	int stacklen = 0; | ||||
| 	char tmp[80]; | ||||
| 	char tmp2[80]; | ||||
| 	char tmp3[256]; | ||||
| 	if (ast_pthread_mutex_lock(&conlock)) { | ||||
| 		ast_log(LOG_WARNING, "Unable to obtain lock\n"); | ||||
| 		if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH)) | ||||
| @@ -614,7 +667,10 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte | ||||
| 						ast_log(LOG_DEBUG, "Launching '%s'\n", app->name); | ||||
| 				else if (option_verbose > 2) | ||||
| 						ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n",  | ||||
| 								app->name, c->name, (e->data ? (char *)e->data : NULL), (newstack ? "in new stack" : "in same stack")); | ||||
| 								term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), | ||||
| 								term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), | ||||
| 								term_color(tmp3, (e->data ? (char *)e->data : NULL), COLOR_BRMAGENTA, 0, sizeof(tmp3)), | ||||
| 								(newstack ? "in new stack" : "in same stack")); | ||||
| 				res = pbx_exec(c, app, e->data, newstack); | ||||
| 				return res; | ||||
| 			} else { | ||||
| @@ -675,41 +731,6 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte | ||||
|  | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| int ast_pbx_longest_extension(char *context)  | ||||
| { | ||||
| 	/* XXX Not include-aware XXX */ | ||||
| 	struct ast_context *tmp; | ||||
| 	struct ast_exten *e; | ||||
| 	int len = 0; | ||||
| 	if (ast_pthread_mutex_lock(&conlock)) { | ||||
| 		ast_log(LOG_WARNING, "Unable to obtain lock\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	tmp = contexts; | ||||
| 	while(tmp) { | ||||
| 		if (!strcasecmp(tmp->name, context)) { | ||||
| 			/* By locking tmp, not only can the state of its entries not | ||||
| 			   change, but it cannot be destroyed either. */ | ||||
| 			ast_pthread_mutex_lock(&tmp->lock); | ||||
| 			/* But we can relieve the conlock, as tmp will not change */ | ||||
| 			ast_pthread_mutex_unlock(&conlock); | ||||
| 			e = tmp->root; | ||||
| 			while(e) { | ||||
| 				if (strlen(e->exten) > len) | ||||
| 					len = strlen(e->exten); | ||||
| 				e = e->next; | ||||
| 			} | ||||
| 			ast_pthread_mutex_unlock(&tmp->lock); | ||||
| 			return len; | ||||
| 		} | ||||
| 		tmp = tmp->next; | ||||
| 	} | ||||
| 	ast_log(LOG_WARNING, "No such context '%s'\n", context); | ||||
| 	return -1; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)  | ||||
| { | ||||
| 	return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS); | ||||
| @@ -736,7 +757,7 @@ int ast_pbx_run(struct ast_channel *c) | ||||
|  | ||||
| 	/* A little initial setup here */ | ||||
| 	if (c->pbx) | ||||
| 		ast_log(LOG_WARNING, "%s already has PBX structure??\n"); | ||||
| 		ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); | ||||
| 	c->pbx = malloc(sizeof(struct ast_pbx)); | ||||
| 	if (!c->pbx) { | ||||
| 		ast_log(LOG_WARNING, "Out of memory\n"); | ||||
| @@ -744,7 +765,7 @@ int ast_pbx_run(struct ast_channel *c) | ||||
| 	} | ||||
| 	if (c->amaflags) { | ||||
| 		if (c->cdr) { | ||||
| 			ast_log(LOG_WARNING, "%s already has a call record??\n"); | ||||
| 			ast_log(LOG_WARNING, "%s already has a call record??\n", c->name); | ||||
| 		} else { | ||||
| 			c->cdr = ast_cdr_alloc(); | ||||
| 			if (!c->cdr) { | ||||
| @@ -890,6 +911,22 @@ int ast_pbx_run(struct ast_channel *c) | ||||
| 	if (firstpass)  | ||||
| 		ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); | ||||
| out: | ||||
| 	if (ast_exists_extension(c, c->context, "h", 1, c->callerid)) { | ||||
| 		strcpy(c->exten, "h"); | ||||
| 		c->priority = 1; | ||||
| 		while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) { | ||||
| 			if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) { | ||||
| 				/* Something bad happened, or a hangup has been requested. */ | ||||
| 				if (option_debug) | ||||
| 					ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); | ||||
| 				else if (option_verbose > 1) | ||||
| 					ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); | ||||
| 				break; | ||||
| 			} | ||||
| 			c->priority++; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	pbx_destroy(c->pbx); | ||||
| 	c->pbx = NULL; | ||||
| 	if (res != AST_PBX_KEEPALIVE) | ||||
| @@ -973,7 +1010,7 @@ int ast_context_remove_include2(struct ast_context *con, char *include, char *re | ||||
| { | ||||
| 	struct ast_include *i, *pi = NULL; | ||||
|  | ||||
| 	if (pthread_mutex_lock(&con->lock)) return -1; | ||||
| 	if (ast_pthread_mutex_lock(&con->lock)) return -1; | ||||
|  | ||||
| 	/* walk includes */ | ||||
| 	i = con->includes; | ||||
| @@ -1045,7 +1082,7 @@ int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, ch | ||||
| { | ||||
| 	struct ast_sw *i, *pi = NULL; | ||||
|  | ||||
| 	if (pthread_mutex_lock(&con->lock)) return -1; | ||||
| 	if (ast_pthread_mutex_lock(&con->lock)) return -1; | ||||
|  | ||||
| 	/* walk switchs */ | ||||
| 	i = con->alts; | ||||
| @@ -1215,6 +1252,7 @@ int ast_context_remove_extension2(struct ast_context *con, char *extension, int | ||||
| int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description) | ||||
| { | ||||
| 	struct ast_app *tmp; | ||||
| 	char tmps[80]; | ||||
| 	if (ast_pthread_mutex_lock(&applock)) { | ||||
| 		ast_log(LOG_ERROR, "Unable to lock application list\n"); | ||||
| 		return -1; | ||||
| @@ -1230,6 +1268,7 @@ int ast_register_application(char *app, int (*execute)(struct ast_channel *, voi | ||||
| 	} | ||||
| 	tmp = malloc(sizeof(struct ast_app)); | ||||
| 	if (tmp) { | ||||
| 		memset(tmp, 0, sizeof(struct ast_app)); | ||||
| 		strncpy(tmp->name, app, sizeof(tmp->name)-1); | ||||
| 		tmp->execute = execute; | ||||
| 		tmp->synopsis = synopsis; | ||||
| @@ -1242,7 +1281,7 @@ int ast_register_application(char *app, int (*execute)(struct ast_channel *, voi | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (option_verbose > 1) | ||||
| 		ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", tmp->name); | ||||
| 		ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); | ||||
| 	ast_pthread_mutex_unlock(&applock); | ||||
| 	return 0; | ||||
| } | ||||
| @@ -1769,7 +1808,7 @@ struct ast_context *ast_context_create(char *name, char *registrar) | ||||
| 	tmp = malloc(sizeof(struct ast_context)); | ||||
| 	if (tmp) { | ||||
| 		memset(tmp, 0, sizeof(struct ast_context)); | ||||
| 		pthread_mutex_init(&tmp->lock, NULL); | ||||
| 		ast_pthread_mutex_init(&tmp->lock); | ||||
| 		strncpy(tmp->name, name, sizeof(tmp->name)-1); | ||||
| 		tmp->root = NULL; | ||||
| 		tmp->registrar = registrar; | ||||
| @@ -1821,6 +1860,255 @@ int ast_context_add_include(char *context, char *include, char *registrar) | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| #define FIND_NEXT \ | ||||
| do { \ | ||||
| 	c = info; \ | ||||
| 	while(*c && (*c != '|')) c++; \ | ||||
| 	if (*c) *c = '\0'; else c = NULL; \ | ||||
| } while(0) | ||||
|  | ||||
| static void get_timerange(struct ast_include *i, char *times) | ||||
| { | ||||
| 	char *e; | ||||
| 	int x; | ||||
| 	int s1, s2; | ||||
| 	int e1, e2; | ||||
| 	/* Star is all times */ | ||||
| 	if (!strlen(times) || !strcmp(times, "*")) { | ||||
| 		for (x=0;x<24;x++) | ||||
| 			i->minmask[x] = (1 << 30) - 1; | ||||
| 		return; | ||||
| 	} | ||||
| 	/* Otherwise expect a range */ | ||||
| 	e = strchr(times, '-'); | ||||
| 	if (!e) { | ||||
| 		ast_log(LOG_WARNING, "Time range is not valid. Assuming no time.\n"); | ||||
| 		return; | ||||
| 	} | ||||
| 	*e = '\0'; | ||||
| 	e++; | ||||
| 	while(*e && !isdigit(*e)) e++; | ||||
| 	if (!*e) { | ||||
| 		ast_log(LOG_WARNING, "Invalid time range.  Assuming no time.\n"); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (sscanf(times, "%d:%d", &s1, &s2) != 2) { | ||||
| 		ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", times); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (sscanf(e, "%d:%d", &e1, &e2) != 2) { | ||||
| 		ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", e); | ||||
| 		return; | ||||
| 	} | ||||
| 	s1 = s1 * 30 + s2/2; | ||||
| 	if ((s1 < 0) || (s1 >= 24*30)) { | ||||
| 		ast_log(LOG_WARNING, "%s isn't a valid star time. Assuming no time.\n", times); | ||||
| 		return; | ||||
| 	} | ||||
| 	e1 = e1 * 30 + e2/2; | ||||
| 	if ((e1 < 0) || (e2 >= 24*30)) { | ||||
| 		ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); | ||||
| 		return; | ||||
| 	} | ||||
| 	/* Go through the time and enable each appropriate bit */ | ||||
| 	for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { | ||||
| 		i->minmask[x/30] |= (1 << (x % 30)); | ||||
| 	} | ||||
| 	/* Do the last one */ | ||||
| 	i->minmask[x/30] |= (1 << (x % 30)); | ||||
| 	/* All done */ | ||||
| } | ||||
|  | ||||
| static char *days[] = | ||||
| { | ||||
| 	"sun", | ||||
| 	"mon", | ||||
| 	"tue", | ||||
| 	"wed", | ||||
| 	"thu", | ||||
| 	"fri", | ||||
| 	"sat", | ||||
| }; | ||||
|  | ||||
| static unsigned int get_dow(char *dow) | ||||
| { | ||||
| 	char *c; | ||||
| 	/* The following line is coincidence, really! */ | ||||
| 	int s, e, x; | ||||
| 	unsigned mask; | ||||
| 	/* Check for all days */ | ||||
| 	if (!strlen(dow) || !strcmp(dow, "*")) | ||||
| 		return (1 << 7) - 1; | ||||
| 	/* Get start and ending days */ | ||||
| 	c = strchr(dow, '-'); | ||||
| 	if (c) { | ||||
| 		*c = '\0'; | ||||
| 		c++; | ||||
| 	} | ||||
| 	/* Find the start */ | ||||
| 	s = 0; | ||||
| 	while((s < 7) && strcasecmp(dow, days[s])) s++; | ||||
| 	if (s >= 7) { | ||||
| 		ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (c) { | ||||
| 		e = 0; | ||||
| 		while((e < 7) && strcasecmp(dow, days[e])) e++; | ||||
| 		if (e >= 7) { | ||||
| 			ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c); | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} else | ||||
| 		e = s; | ||||
| 	mask = 0; | ||||
| 	for (x=s;x!=e;x = (x + 1) % 7) { | ||||
| 		mask |= (1 << x); | ||||
| 	} | ||||
| 	/* One last one */ | ||||
| 	mask |= (1 << x); | ||||
| 	return mask; | ||||
| } | ||||
|  | ||||
| static unsigned int get_day(char *day) | ||||
| { | ||||
| 	char *c; | ||||
| 	/* The following line is coincidence, really! */ | ||||
| 	int s, e, x; | ||||
| 	unsigned int mask; | ||||
| 	/* Check for all days */ | ||||
| 	if (!strlen(day) || !strcmp(day, "*")) { | ||||
| 		mask = (1 << 30)  + ((1 << 30) - 1); | ||||
| 	} | ||||
| 	/* Get start and ending days */ | ||||
| 	c = strchr(day, '-'); | ||||
| 	if (c) { | ||||
| 		*c = '\0'; | ||||
| 		c++; | ||||
| 	} | ||||
| 	/* Find the start */ | ||||
| 	if (sscanf(day, "%d", &s) != 1) { | ||||
| 		ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if ((s < 1) || (s > 31)) { | ||||
| 		ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	s--; | ||||
| 	if (c) { | ||||
| 		if (sscanf(c, "%d", &e) != 1) { | ||||
| 			ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		if ((e < 1) || (e > 31)) { | ||||
| 			ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		e--; | ||||
| 	} else | ||||
| 		e = s; | ||||
| 	mask = 0; | ||||
| 	for (x=s;x!=e;x = (x + 1) % 31) { | ||||
| 		mask |= (1 << x); | ||||
| 	} | ||||
| 	mask |= (1 << x); | ||||
| 	return mask; | ||||
| } | ||||
|  | ||||
| static char *months[] = | ||||
| { | ||||
| 	"jan", | ||||
| 	"feb", | ||||
| 	"mar", | ||||
| 	"apr", | ||||
| 	"may", | ||||
| 	"jun", | ||||
| 	"jul", | ||||
| 	"aug", | ||||
| 	"sep", | ||||
| 	"oct", | ||||
| 	"nov", | ||||
| 	"dec", | ||||
| }; | ||||
|  | ||||
| static unsigned int get_month(char *mon) | ||||
| { | ||||
| 	char *c; | ||||
| 	/* The following line is coincidence, really! */ | ||||
| 	int s, e, x; | ||||
| 	unsigned int mask; | ||||
| 	/* Check for all days */ | ||||
| 	if (!strlen(mon) || !strcmp(mon, "*"))  | ||||
| 		return (1 << 12) - 1; | ||||
| 	/* Get start and ending days */ | ||||
| 	c = strchr(mon, '-'); | ||||
| 	if (c) { | ||||
| 		*c = '\0'; | ||||
| 		c++; | ||||
| 	} | ||||
| 	/* Find the start */ | ||||
| 	s = 0; | ||||
| 	while((s < 12) && strcasecmp(mon, months[s])) s++; | ||||
| 	if (s >= 12) { | ||||
| 		ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (c) { | ||||
| 		e = 0; | ||||
| 		while((e < 12) && strcasecmp(mon, months[e])) e++; | ||||
| 		if (e >= 12) { | ||||
| 			ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c); | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} else | ||||
| 		e = s; | ||||
| 	mask = 0; | ||||
| 	for (x=s;x!=e;x = (x + 1) % 12) { | ||||
| 		mask |= (1 << x); | ||||
| 	} | ||||
| 	/* One last one */ | ||||
| 	mask |= (1 << x); | ||||
| 	return mask; | ||||
| } | ||||
|  | ||||
| static void build_timing(struct ast_include *i, char *info) | ||||
| { | ||||
| 	char *c; | ||||
| 	/* Check for empty just in case */ | ||||
| 	if (!strlen(info)) | ||||
| 		return; | ||||
| 	i->hastime = 1; | ||||
| 	/* Assume everything except time */ | ||||
| 	i->monthmask = (1 << 12) - 1; | ||||
| 	i->daymask = (1 << 30) - 1 + (1 << 30); | ||||
| 	i->dowmask = (1 << 7) - 1; | ||||
| 	/* Avoid using strtok */ | ||||
| 	FIND_NEXT; | ||||
|  | ||||
| 	/* Info has the time range, start with that */ | ||||
| 	get_timerange(i, info); | ||||
| 	info = c; | ||||
| 	if (!info) | ||||
| 		return; | ||||
| 	FIND_NEXT; | ||||
| 	/* Now check for day of week */ | ||||
| 	i->dowmask = get_dow(info); | ||||
|  | ||||
| 	info = c; | ||||
| 	if (!info) | ||||
| 		return; | ||||
| 	FIND_NEXT; | ||||
| 	/* Now check for the day of the month */ | ||||
| 	i->daymask = get_day(info); | ||||
| 	info = c; | ||||
| 	if (!info) | ||||
| 		return; | ||||
| 	FIND_NEXT; | ||||
| 	/* And finally go for the month */ | ||||
| 	i->monthmask = get_month(info); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * errno values | ||||
|  *  ENOMEM - out of memory | ||||
| @@ -1832,6 +2120,7 @@ int ast_context_add_include2(struct ast_context *con, char *value, | ||||
| 	char *registrar) | ||||
| { | ||||
| 	struct ast_include *new_include; | ||||
| 	char *c; | ||||
| 	struct ast_include *i, *il = NULL; /* include, include_last */ | ||||
|  | ||||
| 	/* allocate new include structure ... */ | ||||
| @@ -1842,7 +2131,17 @@ int ast_context_add_include2(struct ast_context *con, char *value, | ||||
| 	} | ||||
| 	 | ||||
| 	/* ... fill in this structure ... */ | ||||
| 	memset(new_include, 0, sizeof(struct ast_include)); | ||||
| 	strncpy(new_include->name, value, sizeof(new_include->name)-1); | ||||
| 	strncpy(new_include->rname, value, sizeof(new_include->rname)-1); | ||||
| 	c = new_include->rname; | ||||
| 	/* Strip off timing info */ | ||||
| 	while(*c && (*c != '|')) c++;  | ||||
| 	/* Process if it's there */ | ||||
| 	if (*c) { | ||||
| 		build_timing(new_include, c+1); | ||||
| 		*c = '\0'; | ||||
| 	} | ||||
| 	new_include->next      = NULL; | ||||
| 	new_include->registrar = registrar; | ||||
|  | ||||
| @@ -1932,6 +2231,7 @@ int ast_context_add_switch2(struct ast_context *con, char *value, | ||||
| 	} | ||||
| 	 | ||||
| 	/* ... fill in this structure ... */ | ||||
| 	memset(new_sw, 0, sizeof(struct ast_sw)); | ||||
| 	strncpy(new_sw->name, value, sizeof(new_sw->name)-1); | ||||
| 	if (data) | ||||
| 		strncpy(new_sw->data, data, sizeof(new_sw->data)-1); | ||||
| @@ -2068,10 +2368,11 @@ int ast_context_add_ignorepat2(struct ast_context *con, char *value, char *regis | ||||
| 		errno = ENOMEM; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	memset(ignorepat, 0, sizeof(struct ast_ignorepat)); | ||||
| 	strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1); | ||||
| 	ignorepat->next = NULL; | ||||
| 	ignorepat->registrar = registrar; | ||||
| 	pthread_mutex_lock(&con->lock); | ||||
| 	ast_pthread_mutex_lock(&con->lock); | ||||
| 	ignorepatc = con->ignorepats; | ||||
| 	while(ignorepatc) { | ||||
| 		ignorepatl = ignorepatc; | ||||
| @@ -2194,6 +2495,7 @@ int ast_add_extension2(struct ast_context *con, | ||||
| 	/* Be optimistic:  Build the extension structure first */ | ||||
| 	tmp = malloc(sizeof(struct ast_exten)); | ||||
| 	if (tmp) { | ||||
| 		memset(tmp, 0, sizeof(struct ast_exten)); | ||||
| 		ext_strncpy(tmp->exten, extension, sizeof(tmp->exten)); | ||||
| 		tmp->priority = priority; | ||||
| 		if (callerid) { | ||||
| @@ -2474,21 +2776,10 @@ static int pbx_builtin_prefix(struct ast_channel *chan, void *data) | ||||
| static int pbx_builtin_wait(struct ast_channel *chan, void *data) | ||||
| { | ||||
| 	int ms; | ||||
| 	struct ast_frame *f; | ||||
| 	/* Wait for "n" seconds */ | ||||
| 	if (data && atoi((char *)data)) { | ||||
| 		ms = atoi((char *)data) * 1000; | ||||
| 		while(ms > 0) { | ||||
| 			ms = ast_waitfor(chan, ms); | ||||
| 			if (ms <0) | ||||
| 				return -1; | ||||
| 			if (ms > 0) { | ||||
| 				f = ast_read(chan); | ||||
| 				if (!f) | ||||
| 					return -1; | ||||
| 				ast_frfree(f); | ||||
| 			} | ||||
| 		} | ||||
| 		return ast_safe_sleep(chan, ms); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|   | ||||
							
								
								
									
										344
									
								
								res/res_adsi.c
									
									
									
									
									
								
							
							
						
						
									
										344
									
								
								res/res_adsi.c
									
									
									
									
									
								
							| @@ -99,27 +99,6 @@ static int adsi_generate(unsigned char *buf, int msgtype, char *msg, int msglen, | ||||
|  | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int len, int *remainder) | ||||
| { | ||||
| 	int res; | ||||
| 	fd_set fds; | ||||
| 	while(len) { | ||||
| 		FD_ZERO(&fds); | ||||
| 		FD_SET(chan->fds[0], &fds); | ||||
| 		select(chan->fds[0] + 1, NULL, &fds, NULL, NULL); | ||||
| 		res = write(chan->fds[0], buf, len); | ||||
| 		if (res < 1) { | ||||
| 			ast_log(LOG_WARNING, "Failed to write: %s\n", strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		buf += res; | ||||
| 		len -= res; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| #else | ||||
| static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int len, int *remainder) | ||||
| { | ||||
| 	/* Sends carefully on a full duplex channel by using reading for | ||||
| @@ -190,7 +169,6 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **msg, int *msglen, int *msgtype) | ||||
| { | ||||
| @@ -305,7 +283,7 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms | ||||
| 				break; | ||||
| 			else { | ||||
| 				retries++; | ||||
| 				ast_log(LOG_DEBUG, "Retransmitting (%d), from %d\n", start + 1); | ||||
| 				ast_log(LOG_DEBUG, "Retransmitting (%d), from %d\n", retries, start + 1); | ||||
| 			} | ||||
| 		} else { | ||||
| 			retries++; | ||||
| @@ -502,14 +480,15 @@ int adsi_download_connect(unsigned char *buf, unsigned char *service,  unsigned | ||||
| 	/* Delimiter */ | ||||
| 	buf[bytes++] = 0xff; | ||||
| 	 | ||||
| 	for (x=0;x<4;x++) | ||||
| 	for (x=0;x<4;x++) { | ||||
| 		buf[bytes++] = fdn[x]; | ||||
| 	} | ||||
| 	for (x=0;x<4;x++) | ||||
| 		buf[bytes++] = sec[x]; | ||||
| 	if (ver > -1) | ||||
| 		buf[bytes++] = ver & 0xff; | ||||
| 	buf[bytes++] = ver & 0xff; | ||||
|  | ||||
| 	buf[1] = bytes - 2; | ||||
|  | ||||
| 	return bytes; | ||||
|  | ||||
| } | ||||
| @@ -529,6 +508,158 @@ int adsi_disconnect_session(unsigned char *buf) | ||||
|  | ||||
| } | ||||
|  | ||||
| int adsi_query_cpeid(unsigned char *buf) | ||||
| { | ||||
| 	int bytes = 0; | ||||
| 	buf[bytes++] = ADSI_QUERY_CPEID; | ||||
| 	/* Reserve space for length */ | ||||
| 	bytes++; | ||||
| 	buf[1] = bytes - 2; | ||||
| 	return bytes; | ||||
| } | ||||
|  | ||||
| int adsi_query_cpeinfo(unsigned char *buf) | ||||
| { | ||||
| 	int bytes = 0; | ||||
| 	buf[bytes++] = ADSI_QUERY_CONFIG; | ||||
| 	/* Reserve space for length */ | ||||
| 	bytes++; | ||||
| 	buf[1] = bytes - 2; | ||||
| 	return bytes; | ||||
| } | ||||
|  | ||||
| int adsi_read_encoded_dtmf(struct ast_channel *chan, unsigned char *buf, int maxlen) | ||||
| { | ||||
| 	int bytes = 0; | ||||
| 	int res; | ||||
| 	unsigned char current = 0; | ||||
| 	int gotstar = 0; | ||||
| 	int pos = 0; | ||||
| 	memset(buf, 0, sizeof(buf)); | ||||
| 	while(bytes <= maxlen) { | ||||
| 		/* Wait up to a second for a digit */ | ||||
| 		res = ast_waitfordigit(chan, 1000); | ||||
| 		if (!res) | ||||
| 			break; | ||||
| 		if (res == '*') { | ||||
| 			gotstar = 1;	 | ||||
| 			continue; | ||||
| 		} | ||||
| 		/* Ignore anything other than a digit */ | ||||
| 		if ((res < '0') || (res > '9')) | ||||
| 			continue; | ||||
| 		res -= '0'; | ||||
| 		if (gotstar) | ||||
| 			res += 9; | ||||
| 		if (pos)  { | ||||
| 			pos = 0; | ||||
| 			buf[bytes++] = (res << 4) | current; | ||||
| 		} else { | ||||
| 			pos = 1; | ||||
| 			current = res; | ||||
| 		} | ||||
| 		gotstar = 0; | ||||
| 	} | ||||
| 	return bytes; | ||||
| } | ||||
|  | ||||
| int adsi_get_cpeid(struct ast_channel *chan, unsigned char *cpeid, int voice) | ||||
| { | ||||
| 	char buf[256]; | ||||
| 	int bytes = 0; | ||||
| 	int res; | ||||
| 	bytes += adsi_data_mode(buf); | ||||
| 	adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); | ||||
|  | ||||
| 	bytes = 0; | ||||
| 	bytes += adsi_query_cpeid(buf); | ||||
| 	adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); | ||||
|  | ||||
| 	/* Get response */ | ||||
| 	memset(buf, 0, sizeof(buf)); | ||||
| 	res = adsi_read_encoded_dtmf(chan, cpeid, 4); | ||||
| 	if (res != 4) { | ||||
| 		ast_log(LOG_WARNING, "Got %d bytes back of encoded DTMF, expecting 4\n", res); | ||||
| 		res = 0; | ||||
| 	} else { | ||||
| 		res = 1; | ||||
| 	} | ||||
|  | ||||
| 	if (voice) { | ||||
| 		bytes = 0; | ||||
| 		bytes += adsi_voice_mode(buf, 0); | ||||
| 		adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); | ||||
| 		/* Ignore the resulting DTMF B announcing it's in voice mode */ | ||||
| 		ast_waitfordigit(chan, 1000); | ||||
| 	} | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| int adsi_get_cpeinfo(struct ast_channel *chan, int *width, int *height, int *buttons, int voice) | ||||
| { | ||||
| 	char buf[256]; | ||||
| 	int bytes = 0; | ||||
| 	int res; | ||||
| 	bytes += adsi_data_mode(buf); | ||||
| 	adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); | ||||
|  | ||||
| 	bytes = 0; | ||||
| 	bytes += adsi_query_cpeinfo(buf); | ||||
| 	adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); | ||||
|  | ||||
| 	/* Get width */ | ||||
| 	memset(buf, 0, sizeof(buf)); | ||||
| 	res = ast_readstring(chan, buf, 2, 1000, 500, ""); | ||||
| 	if (res < 0) | ||||
| 		return res; | ||||
| 	if (strlen(buf) != 2) { | ||||
| 		ast_log(LOG_WARNING, "Got %d bytes of width, expecting 2\n", res); | ||||
| 		res = 0; | ||||
| 	} else { | ||||
| 		res = 1; | ||||
| 	} | ||||
| 	if (width) | ||||
| 		*width = atoi(buf); | ||||
| 	/* Get height */ | ||||
| 	memset(buf, 0, sizeof(buf)); | ||||
| 	if (res) { | ||||
| 		res = ast_readstring(chan, buf, 2, 1000, 500, ""); | ||||
| 		if (res < 0) | ||||
| 			return res; | ||||
| 		if (strlen(buf) != 2) { | ||||
| 			ast_log(LOG_WARNING, "Got %d bytes of height, expecting 2\n", res); | ||||
| 			res = 0; | ||||
| 		} else { | ||||
| 			res = 1; | ||||
| 		}	 | ||||
| 		if (height) | ||||
| 			*height= atoi(buf); | ||||
| 	} | ||||
| 	/* Get buttons */ | ||||
| 	memset(buf, 0, sizeof(buf)); | ||||
| 	if (res) { | ||||
| 		res = ast_readstring(chan, buf, 1, 1000, 500, ""); | ||||
| 		if (res < 0) | ||||
| 			return res; | ||||
| 		if (strlen(buf) != 1) { | ||||
| 			ast_log(LOG_WARNING, "Got %d bytes of buttons, expecting 1\n", res); | ||||
| 			res = 0; | ||||
| 		} else { | ||||
| 			res = 1; | ||||
| 		}	 | ||||
| 		if (buttons) | ||||
| 			*buttons = atoi(buf); | ||||
| 	} | ||||
| 	if (voice) { | ||||
| 		bytes = 0; | ||||
| 		bytes += adsi_voice_mode(buf, 0); | ||||
| 		adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); | ||||
| 		/* Ignore the resulting DTMF B announcing it's in voice mode */ | ||||
| 		ast_waitfordigit(chan, 1000); | ||||
| 	} | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| int adsi_data_mode(unsigned char *buf) | ||||
| { | ||||
| 	int bytes=0; | ||||
| @@ -544,6 +675,36 @@ int adsi_data_mode(unsigned char *buf) | ||||
|  | ||||
| } | ||||
|  | ||||
| int adsi_clear_soft_keys(unsigned char *buf) | ||||
| { | ||||
| 	int bytes=0; | ||||
|  | ||||
| 	/* Message type */ | ||||
| 	buf[bytes++] = ADSI_CLEAR_SOFTKEY; | ||||
|  | ||||
| 	/* Reserve space for length */ | ||||
| 	bytes++; | ||||
|  | ||||
| 	buf[1] = bytes - 2; | ||||
| 	return bytes; | ||||
|  | ||||
| } | ||||
|  | ||||
| int adsi_clear_screen(unsigned char *buf) | ||||
| { | ||||
| 	int bytes=0; | ||||
|  | ||||
| 	/* Message type */ | ||||
| 	buf[bytes++] = ADSI_CLEAR_SCREEN; | ||||
|  | ||||
| 	/* Reserve space for length */ | ||||
| 	bytes++; | ||||
|  | ||||
| 	buf[1] = bytes - 2; | ||||
| 	return bytes; | ||||
|  | ||||
| } | ||||
|  | ||||
| int adsi_voice_mode(unsigned char *buf, int when) | ||||
| { | ||||
| 	int bytes=0; | ||||
| @@ -719,86 +880,6 @@ int adsi_set_line(unsigned char *buf, int page, int line) | ||||
| static int total = 0; | ||||
| static int speeds = 0; | ||||
|  | ||||
| #if 0 | ||||
| int adsi_channel_init(struct ast_channel *chan) | ||||
| { | ||||
| 	char dsp[256]; | ||||
| 	char keys[256]; | ||||
| 	int bytes; | ||||
| 	int x; | ||||
| 	unsigned char *msgs[3]; | ||||
| 	unsigned char keyd[6]; | ||||
| 	int lens[3]; | ||||
| 	int types[3]; | ||||
| 	memset(dsp, 0, sizeof(dsp)); | ||||
| 	memset(keys, 0, sizeof(keys)); | ||||
| 	memset(msgs, 0, sizeof(msgs)); | ||||
|  | ||||
| 	/* Start with initial display setup */ | ||||
| 	bytes = 0; | ||||
| 	bytes += adsi_connect_session(dsp, NULL, -1); | ||||
| 	for (x=0;x<total;x++) { | ||||
| 		bytes += adsi_display(dsp + bytes, ADSI_INFO_PAGE, x + 1, aligns[x], 0, | ||||
| 			strlen(intro[x]) ? intro[x] : " ", ""); | ||||
| 	} | ||||
| 	bytes += adsi_set_line(dsp + bytes, ADSI_INFO_PAGE, 1); | ||||
|  	msgs[0] = dsp; | ||||
| 	lens[0] = bytes; | ||||
| 	types[0] = ADSI_MSG_DISPLAY; | ||||
|  | ||||
| 	/* Prepare key setup messages */ | ||||
|  | ||||
| 	if (speeds) { | ||||
| 		bytes = 0; | ||||
| 		memset(keyd, 0, sizeof(keyd)); | ||||
| 		for (x=0;x<speeds;x++) { | ||||
| 			bytes += adsi_load_soft_key(keys + bytes, ADSI_SPEED_DIAL + x, | ||||
| 					speeddial[x][1], speeddial[x][2], speeddial[x][0]); | ||||
| 			keyd[x] = ADSI_SPEED_DIAL + x; | ||||
| 		} | ||||
| 		bytes += adsi_set_keys(keys + bytes, keyd); | ||||
| 		msgs[1] = keys; | ||||
| 		lens[1] = bytes; | ||||
| 		types[1] = ADSI_MSG_DISPLAY; | ||||
| 	} | ||||
| 	adsi_transmit_messages(chan, msgs, lens, types); | ||||
| 	return 0; | ||||
| } | ||||
| #else | ||||
| int adsi_channel_init(struct ast_channel *chan) | ||||
| { | ||||
| 	char dsp[256]; | ||||
| 	int bytes; | ||||
| 	int x; | ||||
| 	unsigned char keyd[6]; | ||||
|  | ||||
| 	memset(dsp, 0, sizeof(dsp)); | ||||
|  | ||||
| 	/* Start with initial display setup */ | ||||
| 	bytes = 0; | ||||
| 	bytes += adsi_connect_session(dsp, NULL, -1); | ||||
| 	for (x=0;x<total;x++) { | ||||
| 		bytes += adsi_display(dsp + bytes, ADSI_INFO_PAGE, x + 1, aligns[x], 0, | ||||
| 			strlen(intro[x]) ? intro[x] : " ", ""); | ||||
| 	} | ||||
| 	bytes += adsi_set_line(dsp + bytes, ADSI_INFO_PAGE, 1); | ||||
|  | ||||
| 	/* Prepare key setup messages */ | ||||
|  | ||||
| 	if (speeds) { | ||||
| 		memset(keyd, 0, sizeof(keyd)); | ||||
| 		for (x=0;x<speeds;x++) { | ||||
| 			bytes += adsi_load_soft_key(dsp + bytes, ADSI_SPEED_DIAL + x, | ||||
| 					speeddial[x][1], speeddial[x][2], speeddial[x][0], 0); | ||||
| 			keyd[x] = ADSI_SPEED_DIAL + x; | ||||
| 		} | ||||
| 		bytes += adsi_set_keys(dsp + bytes, keyd); | ||||
| 	} | ||||
| 	adsi_transmit_message(chan, dsp, bytes, ADSI_MSG_DISPLAY); | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| int adsi_channel_restore(struct ast_channel *chan) | ||||
| { | ||||
| 	char dsp[256]; | ||||
| @@ -826,6 +907,26 @@ int adsi_channel_restore(struct ast_channel *chan) | ||||
|  | ||||
| } | ||||
|  | ||||
| int adsi_print(struct ast_channel *chan, char **lines, int *aligns, int voice) | ||||
| { | ||||
| 	char buf[4096]; | ||||
| 	int bytes=0; | ||||
| 	int res; | ||||
| 	int x; | ||||
| 	for(x=0;lines[x];x++)  | ||||
| 		bytes += adsi_display(buf + bytes, ADSI_INFO_PAGE, x+1, aligns[x],0, lines[x], ""); | ||||
| 	bytes += adsi_set_line(buf + bytes, ADSI_INFO_PAGE, 1); | ||||
| 	if (voice) { | ||||
| 		bytes += adsi_voice_mode(buf + bytes, 0); | ||||
| 	} | ||||
| 	res = adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); | ||||
| 	if (voice) { | ||||
| 		/* Ignore the resulting DTMF B announcing it's in voice mode */ | ||||
| 		ast_waitfordigit(chan, 1000); | ||||
| 	} | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| int adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data) | ||||
| { | ||||
| 	char dsp[256]; | ||||
| @@ -845,21 +946,24 @@ int adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int | ||||
| 	/* Prepare key setup messages */ | ||||
| 	if (adsi_transmit_message(chan, dsp, bytes, ADSI_MSG_DISPLAY)) | ||||
| 		return -1; | ||||
| 	res = ast_readstring(chan, resp, 1, 1200, 1200, ""); | ||||
| 	if (res < 0) | ||||
| 		return -1; | ||||
| 	if (res) { | ||||
| 		ast_log(LOG_DEBUG, "No response from CPE about version.  Assuming not there.\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (!strcmp(resp, "B")) { | ||||
| 		ast_log(LOG_DEBUG, "CPE has script '%s' version %d already loaded\n", app, ver); | ||||
| 	if (app) { | ||||
| 		res = ast_readstring(chan, resp, 1, 1200, 1200, ""); | ||||
| 		if (res < 0) | ||||
| 			return -1; | ||||
| 		if (res) { | ||||
| 			ast_log(LOG_DEBUG, "No response from CPE about version.  Assuming not there.\n"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		if (!strcmp(resp, "B")) { | ||||
| 			ast_log(LOG_DEBUG, "CPE has script '%s' version %d already loaded\n", app, ver); | ||||
| 			return 1; | ||||
| 		} else if (!strcmp(resp, "A")) { | ||||
| 			ast_log(LOG_DEBUG, "CPE hasn't script '%s' version %d already loaded\n", app, ver); | ||||
| 		} else { | ||||
| 			ast_log(LOG_WARNING, "Unexpected CPE response to script query: %s\n", resp); | ||||
| 		} | ||||
| 	} else | ||||
| 		return 1; | ||||
| 	} else if (!strcmp(resp, "A")) { | ||||
| 		ast_log(LOG_DEBUG, "CPE hasn't script '%s' version %d already loaded\n", app, ver); | ||||
| 	} else { | ||||
| 		ast_log(LOG_WARNING, "Unexpected CPE response to script query: %s\n", resp); | ||||
| 	} | ||||
| 	return 0; | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user