| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-01-05 09:30:21 +00:00
										 |  |  |  * Copyright (C) 1999 - 2006, Digium, Inc. | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \brief Automatic channel service routines | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \author Mark Spencer <markster@digium.com>  | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <sys/time.h>
 | 
					
						
							|  |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-22 13:11:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/pbx.h"
 | 
					
						
							|  |  |  | #include "asterisk/frame.h"
 | 
					
						
							|  |  |  | #include "asterisk/sched.h"
 | 
					
						
							|  |  |  | #include "asterisk/options.h"
 | 
					
						
							|  |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/logger.h"
 | 
					
						
							|  |  |  | #include "asterisk/file.h"
 | 
					
						
							|  |  |  | #include "asterisk/translate.h"
 | 
					
						
							|  |  |  | #include "asterisk/manager.h"
 | 
					
						
							|  |  |  | #include "asterisk/chanvars.h"
 | 
					
						
							|  |  |  | #include "asterisk/linkedlists.h"
 | 
					
						
							|  |  |  | #include "asterisk/indications.h"
 | 
					
						
							|  |  |  | #include "asterisk/lock.h"
 | 
					
						
							|  |  |  | #include "asterisk/utils.h"
 | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define MAX_AUTOMONS 256
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct asent { | 
					
						
							|  |  |  | 	struct ast_channel *chan; | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 	AST_LIST_ENTRY(asent) list; | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | static AST_RWLIST_HEAD_STATIC(aslist, asent); | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-03-15 07:51:22 +00:00
										 |  |  | static pthread_t asthread = AST_PTHREADT_NULL; | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void *autoservice_run(void *ign) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-23 00:11:32 +00:00
										 |  |  | 	for (;;) { | 
					
						
							| 
									
										
										
										
											2007-06-12 14:16:37 +00:00
										 |  |  | 		struct ast_channel *mons[MAX_AUTOMONS], *chan; | 
					
						
							| 
									
										
										
										
											2006-02-15 01:38:20 +00:00
										 |  |  | 		struct asent *as; | 
					
						
							|  |  |  | 		int x = 0, ms = 500; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 		AST_RWLIST_RDLOCK(&aslist); | 
					
						
							|  |  |  | 		AST_RWLIST_TRAVERSE(&aslist, as, list) { | 
					
						
							| 
									
										
										
										
											2007-08-01 15:39:54 +00:00
										 |  |  | 			if (!ast_check_hangup(as->chan)) { | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 				if (x < MAX_AUTOMONS) | 
					
						
							|  |  |  | 					mons[x++] = as->chan; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					ast_log(LOG_WARNING, "Exceeded maximum number of automatic monitoring events.  Fix autoservice.c\n"); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 		AST_RWLIST_UNLOCK(&aslist); | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-12 14:16:37 +00:00
										 |  |  | 		if ((chan = ast_waitfor_n(mons, x, &ms))) { | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 			/* Read and ignore anything that occurs */ | 
					
						
							| 
									
										
										
										
											2006-02-15 01:38:20 +00:00
										 |  |  | 			struct ast_frame *f = ast_read(chan); | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 			if (f) | 
					
						
							|  |  |  | 				ast_frfree(f); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-06-12 14:16:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-03-15 07:51:22 +00:00
										 |  |  | 	asthread = AST_PTHREADT_NULL; | 
					
						
							| 
									
										
										
										
											2007-06-12 14:16:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ast_autoservice_start(struct ast_channel *chan) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = -1; | 
					
						
							|  |  |  | 	struct asent *as; | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	AST_RWLIST_WRLOCK(&aslist); | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Check if the channel already has autoservice */ | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 	AST_RWLIST_TRAVERSE(&aslist, as, list) { | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 		if (as->chan == chan) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* If not, start autoservice on channel */ | 
					
						
							| 
									
										
										
										
											2006-02-15 01:48:54 +00:00
										 |  |  | 	if (!as && (as = ast_calloc(1, sizeof(*as)))) { | 
					
						
							|  |  |  | 		as->chan = chan; | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 		AST_RWLIST_INSERT_HEAD(&aslist, as, list); | 
					
						
							| 
									
										
										
										
											2006-02-15 01:48:54 +00:00
										 |  |  | 		res = 0; | 
					
						
							|  |  |  | 		if (asthread == AST_PTHREADT_NULL) { /* need start the thread */ | 
					
						
							| 
									
										
										
										
											2006-10-04 19:51:38 +00:00
										 |  |  | 			if (ast_pthread_create_background(&asthread, NULL, autoservice_run, NULL)) { | 
					
						
							| 
									
										
										
										
											2006-02-15 01:48:54 +00:00
										 |  |  | 				ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n"); | 
					
						
							|  |  |  | 				/* There will only be a single member in the list at this point,
 | 
					
						
							|  |  |  | 				   the one we just added. */ | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 				AST_RWLIST_REMOVE(&aslist, as, list); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 				ast_free(as); | 
					
						
							| 
									
										
										
										
											2006-02-15 01:48:54 +00:00
										 |  |  | 				res = -1; | 
					
						
							|  |  |  | 			} else | 
					
						
							|  |  |  | 				pthread_kill(asthread, SIGURG); | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 	AST_RWLIST_UNLOCK(&aslist); | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ast_autoservice_stop(struct ast_channel *chan) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = -1; | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 	struct asent *as; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 	AST_RWLIST_WRLOCK(&aslist); | 
					
						
							|  |  |  | 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&aslist, as, list) {	 | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 		if (as->chan == chan) { | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 			AST_RWLIST_REMOVE_CURRENT(&aslist, list); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 			ast_free(as); | 
					
						
							| 
									
										
										
										
											2007-08-01 15:39:54 +00:00
										 |  |  | 			if (!ast_check_hangup(chan)) | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 				res = 0; | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 	AST_RWLIST_TRAVERSE_SAFE_END | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-03-15 07:51:22 +00:00
										 |  |  | 	if (asthread != AST_PTHREADT_NULL)  | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 		pthread_kill(asthread, SIGURG); | 
					
						
							| 
									
										
										
										
											2007-01-23 00:16:55 +00:00
										 |  |  | 	AST_RWLIST_UNLOCK(&aslist); | 
					
						
							| 
									
										
										
										
											2006-01-03 08:54:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 	/* Wait for it to un-block */ | 
					
						
							| 
									
										
										
										
											2007-01-23 00:11:32 +00:00
										 |  |  | 	while (ast_test_flag(chan, AST_FLAG_BLOCKING)) | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 		usleep(1000); | 
					
						
							| 
									
										
										
										
											2007-06-12 14:16:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-30 13:09:27 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } |