![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
autoservice.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2006, Digium, Inc. 00005 * 00006 * Mark Spencer <markster@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! \file 00020 * 00021 * \brief Automatic channel service routines 00022 * 00023 * \author Mark Spencer <markster@digium.com> 00024 */ 00025 00026 #include "asterisk.h" 00027 00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 51499 $") 00029 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #include <sys/time.h> 00034 #include <signal.h> 00035 #include <errno.h> 00036 #include <unistd.h> 00037 00038 #include "asterisk/pbx.h" 00039 #include "asterisk/frame.h" 00040 #include "asterisk/sched.h" 00041 #include "asterisk/options.h" 00042 #include "asterisk/channel.h" 00043 #include "asterisk/logger.h" 00044 #include "asterisk/file.h" 00045 #include "asterisk/translate.h" 00046 #include "asterisk/manager.h" 00047 #include "asterisk/chanvars.h" 00048 #include "asterisk/linkedlists.h" 00049 #include "asterisk/indications.h" 00050 #include "asterisk/lock.h" 00051 #include "asterisk/utils.h" 00052 00053 #define MAX_AUTOMONS 256 00054 00055 struct asent { 00056 struct ast_channel *chan; 00057 AST_LIST_ENTRY(asent) list; 00058 }; 00059 00060 static AST_RWLIST_HEAD_STATIC(aslist, asent); 00061 00062 static pthread_t asthread = AST_PTHREADT_NULL; 00063 00064 static void *autoservice_run(void *ign) 00065 { 00066 00067 for (;;) { 00068 struct ast_channel *mons[MAX_AUTOMONS]; 00069 struct ast_channel *chan; 00070 struct asent *as; 00071 int x = 0, ms = 500; 00072 00073 AST_RWLIST_RDLOCK(&aslist); 00074 AST_RWLIST_TRAVERSE(&aslist, as, list) { 00075 if (!as->chan->_softhangup) { 00076 if (x < MAX_AUTOMONS) 00077 mons[x++] = as->chan; 00078 else 00079 ast_log(LOG_WARNING, "Exceeded maximum number of automatic monitoring events. Fix autoservice.c\n"); 00080 } 00081 } 00082 AST_RWLIST_UNLOCK(&aslist); 00083 00084 chan = ast_waitfor_n(mons, x, &ms); 00085 if (chan) { 00086 /* Read and ignore anything that occurs */ 00087 struct ast_frame *f = ast_read(chan); 00088 if (f) 00089 ast_frfree(f); 00090 } 00091 } 00092 asthread = AST_PTHREADT_NULL; 00093 return NULL; 00094 } 00095 00096 int ast_autoservice_start(struct ast_channel *chan) 00097 { 00098 int res = -1; 00099 struct asent *as; 00100 00101 AST_RWLIST_WRLOCK(&aslist); 00102 00103 /* Check if the channel already has autoservice */ 00104 AST_RWLIST_TRAVERSE(&aslist, as, list) { 00105 if (as->chan == chan) 00106 break; 00107 } 00108 00109 /* If not, start autoservice on channel */ 00110 if (!as && (as = ast_calloc(1, sizeof(*as)))) { 00111 as->chan = chan; 00112 AST_RWLIST_INSERT_HEAD(&aslist, as, list); 00113 res = 0; 00114 if (asthread == AST_PTHREADT_NULL) { /* need start the thread */ 00115 if (ast_pthread_create_background(&asthread, NULL, autoservice_run, NULL)) { 00116 ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n"); 00117 /* There will only be a single member in the list at this point, 00118 the one we just added. */ 00119 AST_RWLIST_REMOVE(&aslist, as, list); 00120 free(as); 00121 res = -1; 00122 } else 00123 pthread_kill(asthread, SIGURG); 00124 } 00125 } 00126 AST_RWLIST_UNLOCK(&aslist); 00127 return res; 00128 } 00129 00130 int ast_autoservice_stop(struct ast_channel *chan) 00131 { 00132 int res = -1; 00133 struct asent *as; 00134 00135 AST_RWLIST_WRLOCK(&aslist); 00136 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&aslist, as, list) { 00137 if (as->chan == chan) { 00138 AST_RWLIST_REMOVE_CURRENT(&aslist, list); 00139 free(as); 00140 if (!chan->_softhangup) 00141 res = 0; 00142 break; 00143 } 00144 } 00145 AST_RWLIST_TRAVERSE_SAFE_END 00146 00147 if (asthread != AST_PTHREADT_NULL) 00148 pthread_kill(asthread, SIGURG); 00149 AST_RWLIST_UNLOCK(&aslist); 00150 00151 /* Wait for it to un-block */ 00152 while (ast_test_flag(chan, AST_FLAG_BLOCKING)) 00153 usleep(1000); 00154 return res; 00155 }