00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
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_LIST_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_LIST_LOCK(&aslist);
00074 AST_LIST_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_LIST_UNLOCK(&aslist);
00083
00084 chan = ast_waitfor_n(mons, x, &ms);
00085 if (chan) {
00086
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 AST_LIST_LOCK(&aslist);
00101
00102
00103 AST_LIST_TRAVERSE(&aslist, as, list) {
00104 if (as->chan == chan)
00105 break;
00106 }
00107
00108
00109 if (!as && (as = ast_calloc(1, sizeof(*as)))) {
00110 as->chan = chan;
00111 AST_LIST_INSERT_HEAD(&aslist, as, list);
00112 res = 0;
00113 if (asthread == AST_PTHREADT_NULL) {
00114 if (ast_pthread_create_background(&asthread, NULL, autoservice_run, NULL)) {
00115 ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
00116
00117
00118 AST_LIST_REMOVE(&aslist, as, list);
00119 free(as);
00120 res = -1;
00121 } else
00122 pthread_kill(asthread, SIGURG);
00123 }
00124 }
00125 AST_LIST_UNLOCK(&aslist);
00126 return res;
00127 }
00128
00129 int ast_autoservice_stop(struct ast_channel *chan)
00130 {
00131 int res = -1;
00132 struct asent *as;
00133
00134 AST_LIST_LOCK(&aslist);
00135 AST_LIST_TRAVERSE_SAFE_BEGIN(&aslist, as, list) {
00136 if (as->chan == chan) {
00137 AST_LIST_REMOVE_CURRENT(&aslist, list);
00138 free(as);
00139 if (!chan->_softhangup)
00140 res = 0;
00141 break;
00142 }
00143 }
00144 AST_LIST_TRAVERSE_SAFE_END
00145
00146 if (asthread != AST_PTHREADT_NULL)
00147 pthread_kill(asthread, SIGURG);
00148 AST_LIST_UNLOCK(&aslist);
00149
00150
00151 while(ast_test_flag(chan, AST_FLAG_BLOCKING))
00152 usleep(1000);
00153 return res;
00154 }