Fri Aug 24 02:22:12 2007

Asterisk developer's documentation


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$")
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          /* 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    AST_LIST_LOCK(&aslist);
00101 
00102    /* Check if the channel already has autoservice */
00103    AST_LIST_TRAVERSE(&aslist, as, list) {
00104       if (as->chan == chan)
00105          break;
00106    }
00107 
00108    /* If not, start autoservice on channel */
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) { /* need start the thread */
00114          if (ast_pthread_create_background(&asthread, NULL, autoservice_run, NULL)) {
00115             ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
00116             /* There will only be a single member in the list at this point,
00117                the one we just added. */
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    /* Wait for it to un-block */
00151    while(ast_test_flag(chan, AST_FLAG_BLOCKING))
00152       usleep(1000);
00153    return res;
00154 }

Generated on Fri Aug 24 02:22:12 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1