Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

channel.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- A telephony toolkit for Linux.
00003  *
00004  * Channel Management
00005  * 
00006  * Copyright (C) 1999-2004, Digium, Inc.
00007  *
00008  * Mark Spencer <markster@digium.com>
00009  *
00010  * This program is free software, distributed under the terms of
00011  * the GNU General Public License
00012  */
00013 
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <sys/time.h>
00018 #include <signal.h>
00019 #include <errno.h>
00020 #include <unistd.h>
00021 #include <math.h>       /* For PI */
00022 #include <sys/poll.h>
00023 #include <asterisk/pbx.h>
00024 #include <asterisk/frame.h>
00025 #include <asterisk/sched.h>
00026 #include <asterisk/options.h>
00027 #include <asterisk/channel.h>
00028 #include <asterisk/channel_pvt.h>
00029 #include <asterisk/logger.h>
00030 #include <asterisk/say.h>
00031 #include <asterisk/file.h>
00032 #include <asterisk/translate.h>
00033 #include <asterisk/manager.h>
00034 #include <asterisk/chanvars.h>
00035 #include <asterisk/linkedlists.h>
00036 #include <asterisk/indications.h>
00037 #include <asterisk/monitor.h>
00038 #include <asterisk/causes.h>
00039 #include <asterisk/utils.h>
00040 #include <asterisk/lock.h>
00041 #include "astconf.h"
00042 #ifdef ZAPTEL_OPTIMIZATIONS
00043 #include <sys/ioctl.h>
00044 #ifdef __linux__
00045 #include "/usr/src/modules/zaptel/zaptel.h"
00046 #else
00047 #include <zaptel.h>
00048 #endif /* __linux__ */
00049 #ifndef ZT_TIMERPING
00050 #error "You need newer zaptel!  Please cvs update zaptel"
00051 #endif
00052 #endif
00053 
00054 /* uncomment if you have problems with 'monitoring' synchronized files */
00055 #if 0
00056 #define MONITOR_CONSTANT_DELAY
00057 #define MONITOR_DELAY   150 * 8     /* 150 ms of MONITORING DELAY */
00058 #endif
00059 
00060 extern int ast_mainpid; /* provided by asterisk.c */
00061 static int shutting_down = 0;
00062 static int uniqueint = 0;
00063 AST_MUTEX_DEFINE_STATIC(uniquelock);
00064 
00065 /* XXX Lock appropriately in more functions XXX */
00066 
00067 struct chanlist {
00068    char type[80];
00069    char description[80];
00070    int capabilities;
00071    struct ast_channel * (*requester)(char *type, int format, void *data);
00072    int (*devicestate)(void *data);
00073    struct chanlist *next;
00074 } *backends = NULL;
00075 struct ast_channel *channels = NULL;
00076 
00077 /* Protect the channel list (highly unlikely that two things would change
00078    it at the same time, but still! */
00079    
00080 AST_MUTEX_DEFINE_STATIC(chlock);
00081 
00082 int ast_check_hangup(struct ast_channel *chan)
00083 {
00084 time_t   myt;
00085 
00086      /* if soft hangup flag, return true */
00087    if (chan->_softhangup) return 1;
00088      /* if no private structure, return true */
00089    if (!chan->pvt->pvt) return 1;
00090      /* if no hangup scheduled, just return here */
00091    if (!chan->whentohangup) return 0;
00092    time(&myt); /* get current time */
00093      /* return, if not yet */
00094    if (chan->whentohangup > myt) return 0;
00095    chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
00096    return 1;
00097 }
00098 
00099 static int ast_check_hangup_locked(struct ast_channel *chan)
00100 {
00101    int res;
00102    ast_mutex_lock(&chan->lock);
00103    res = ast_check_hangup(chan);
00104    ast_mutex_unlock(&chan->lock);
00105    return res;
00106 }
00107 
00108 void ast_begin_shutdown(int hangup)
00109 {
00110    struct ast_channel *c;
00111    shutting_down = 1;
00112    if (hangup) {
00113       ast_mutex_lock(&chlock);
00114       c = channels;
00115       while(c) {
00116          ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
00117          c = c->next;
00118       }
00119       ast_mutex_unlock(&chlock);
00120    }
00121 }
00122 
00123 int ast_active_channels(void)
00124 {
00125    struct ast_channel *c;
00126    int cnt = 0;
00127    ast_mutex_lock(&chlock);
00128    c = channels;
00129    while(c) {
00130       cnt++;
00131       c = c->next;
00132    }
00133    ast_mutex_unlock(&chlock);
00134    return cnt;
00135 }
00136 
00137 void ast_cancel_shutdown(void)
00138 {
00139    shutting_down = 0;
00140 }
00141 
00142 int ast_shutting_down(void)
00143 {
00144    return shutting_down;
00145 }
00146 
00147 void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
00148 {
00149    time_t   myt;
00150 
00151    time(&myt);
00152    if (offset)
00153       chan->whentohangup = myt + offset;
00154    else
00155       chan->whentohangup = 0;
00156    return;
00157 }
00158 
00159 int ast_channel_register(char *type, char *description, int capabilities,
00160       struct ast_channel *(*requester)(char *type, int format, void *data))
00161 {
00162    return ast_channel_register_ex(type, description, capabilities, requester, NULL);
00163 }
00164 
00165 int ast_channel_register_ex(char *type, char *description, int capabilities,
00166       struct ast_channel *(*requester)(char *type, int format, void *data),
00167       int (*devicestate)(void *data))
00168 {
00169    struct chanlist *chan, *last=NULL;
00170    if (ast_mutex_lock(&chlock)) {
00171       ast_log(LOG_WARNING, "Unable to lock channel list\n");
00172       return -1;
00173    }
00174    chan = backends;
00175    while (chan) {
00176       if (!strcasecmp(type, chan->type)) {
00177          ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
00178          ast_mutex_unlock(&chlock);
00179          return -1;
00180       }
00181       last = chan;
00182       chan = chan->next;
00183    }
00184    chan = malloc(sizeof(struct chanlist));
00185    if (!chan) {
00186       ast_log(LOG_WARNING, "Out of memory\n");
00187       ast_mutex_unlock(&chlock);
00188       return -1;
00189    }
00190    strncpy(chan->type, type, sizeof(chan->type)-1);
00191    strncpy(chan->description, description, sizeof(chan->description)-1);
00192    chan->capabilities = capabilities;
00193    chan->requester = requester;
00194    chan->devicestate = devicestate;
00195    chan->next = NULL;
00196    if (last)
00197       last->next = chan;
00198    else
00199       backends = chan;
00200    if (option_debug)
00201       ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
00202    else if (option_verbose > 1)
00203       ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
00204    ast_mutex_unlock(&chlock);
00205    return 0;
00206 }
00207 
00208 char *ast_state2str(int state)
00209 {
00210    /* XXX Not reentrant XXX */
00211    static char localtmp[256];
00212    switch(state) {
00213    case AST_STATE_DOWN:
00214       return "Down";
00215    case AST_STATE_RESERVED:
00216       return "Rsrvd";
00217    case AST_STATE_OFFHOOK:
00218       return "OffHook";
00219    case AST_STATE_DIALING:
00220       return "Dialing";
00221    case AST_STATE_RING:
00222       return "Ring";
00223    case AST_STATE_RINGING:
00224       return "Ringing";
00225    case AST_STATE_UP:
00226       return "Up";
00227    case AST_STATE_BUSY:
00228       return "Busy";
00229    default:
00230       snprintf(localtmp, sizeof(localtmp), "Unknown (%d)\n", state);
00231       return localtmp;
00232    }
00233 }
00234 
00235 
00236 int ast_best_codec(int fmts)
00237 {
00238    /* This just our opinion, expressed in code.  We are asked to choose
00239       the best codec to use, given no information */
00240    int x;
00241    static int prefs[] = 
00242    {
00243       /* Okay, ulaw is used by all telephony equipment, so start with it */
00244       AST_FORMAT_ULAW,
00245       /* Unless of course, you're a silly European, so then prefer ALAW */
00246       AST_FORMAT_ALAW,
00247       /* Okay, well, signed linear is easy to translate into other stuff */
00248       AST_FORMAT_SLINEAR,
00249       /* G.726 is standard ADPCM */
00250       AST_FORMAT_G726,
00251       /* ADPCM has great sound quality and is still pretty easy to translate */
00252       AST_FORMAT_ADPCM,
00253       /* Okay, we're down to vocoders now, so pick GSM because it's small and easier to
00254          translate and sounds pretty good */
00255       AST_FORMAT_GSM,
00256       /* iLBC is not too bad */
00257       AST_FORMAT_ILBC,
00258       /* Speex is free, but computationally more expensive than GSM */
00259       AST_FORMAT_SPEEX,
00260       /* Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough
00261          to use it */
00262       AST_FORMAT_LPC10,
00263       /* G.729a is faster than 723 and slightly less expensive */
00264       AST_FORMAT_G729A,
00265       /* Down to G.723.1 which is proprietary but at least designed for voice */
00266       AST_FORMAT_G723_1,
00267    };
00268    
00269    
00270    for (x=0;x<sizeof(prefs) / sizeof(prefs[0]); x++)
00271       if (fmts & prefs[x])
00272          return prefs[x];
00273    ast_log(LOG_WARNING, "Don't know any of 0x%x formats\n", fmts);
00274    return 0;
00275 }
00276 
00277 char *ast_alloc_uniqueid(void) {
00278     char *uniqueid;
00279     uniqueid = malloc(64);
00280     if (!uniqueid) return NULL;
00281     ast_mutex_lock(&uniquelock);
00282     snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYMBOLIC_NAME, ast_mainpid, (long)time(NULL), uniqueint++);
00283     ast_mutex_unlock(&uniquelock);
00284 //    ast_log(LOG_NOTICE,"uid = %s\n",uniqueid);
00285     return uniqueid;
00286 }
00287 
00288 struct ast_channel *ast_channel_alloc(int needqueue)
00289 {
00290    struct ast_channel *tmp;
00291    struct ast_channel_pvt *pvt;
00292    int x;
00293    int flags;
00294    struct varshead *headp;
00295    char *tmpuniqueid;
00296            
00297    
00298    /* If shutting down, don't allocate any new channels */
00299    if (shutting_down)
00300       return NULL;
00301    ast_mutex_lock(&chlock);
00302    tmp = malloc(sizeof(struct ast_channel));
00303    if (tmp) {
00304       memset(tmp, 0, sizeof(struct ast_channel));
00305       pvt = malloc(sizeof(struct ast_channel_pvt));
00306       if (pvt) {
00307          memset(pvt, 0, sizeof(struct ast_channel_pvt));
00308          tmp->sched = sched_context_create();
00309          if (tmp->sched) {
00310             for (x=0;x<AST_MAX_FDS - 1;x++)
00311                tmp->fds[x] = -1;
00312 #ifdef ZAPTEL_OPTIMIZATIONS
00313             tmp->timingfd = open("/dev/zap/timer", O_RDWR);
00314             if (tmp->timingfd > -1) {
00315                /* Check if timing interface supports new
00316                   ping/pong scheme */
00317                flags = 1;
00318                if (!ioctl(tmp->timingfd, ZT_TIMERPONG, &flags))
00319                   needqueue = 0;
00320             }
00321 #else
00322             tmp->timingfd = -1;              
00323 #endif               
00324             if (needqueue &&  
00325                pipe(pvt->alertpipe)) {
00326                ast_log(LOG_WARNING, "Alert pipe creation failed!\n");
00327                free(pvt);
00328                free(tmp);
00329                tmp = NULL;
00330                pvt = NULL;
00331             } else {
00332                if (needqueue) {
00333                   flags = fcntl(pvt->alertpipe[0], F_GETFL);
00334                   fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK);
00335                   flags = fcntl(pvt->alertpipe[1], F_GETFL);
00336                   fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK);
00337                } else 
00338                /* Make sure we've got it done right if they don't */
00339                   pvt->alertpipe[0] = pvt->alertpipe[1] = -1;
00340                /* Always watch the alertpipe */
00341                tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0];
00342                /* And timing pipe */
00343                tmp->fds[AST_MAX_FDS-2] = tmp->timingfd;
00344                strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1);
00345                tmp->pvt = pvt;
00346                /* Initial state */
00347                tmp->_state = AST_STATE_DOWN;
00348                tmp->stack = -1;
00349                tmp->streamid = -1;
00350                tmp->appl = NULL;
00351                tmp->data = NULL;
00352                tmp->fin = 0;
00353                tmp->fout = 0;
00354                tmpuniqueid = ast_alloc_uniqueid();
00355                snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), tmpuniqueid);
00356                if (tmpuniqueid) { 
00357                    free(tmpuniqueid);
00358                    tmpuniqueid = NULL;
00359                }
00360                headp=&tmp->varshead;
00361                ast_mutex_init(&tmp->lock);
00362                     AST_LIST_HEAD_INIT(headp);
00363                tmp->vars=ast_var_assign("tempvar","tempval");
00364                AST_LIST_INSERT_HEAD(headp,tmp->vars,entries);
00365                strncpy(tmp->context, "default", sizeof(tmp->context)-1);
00366                strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1);
00367                strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
00368                tmp->priority=1;
00369                tmp->amaflags = ast_default_amaflags;
00370                strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1);
00371                tmp->next = channels;
00372                channels= tmp;
00373             }
00374          } else {
00375             ast_log(LOG_WARNING, "Unable to create schedule context\n");
00376             free(tmp);
00377             tmp = NULL;
00378          }
00379       } else {
00380          ast_log(LOG_WARNING, "Out of memory\n");
00381          free(tmp);
00382          tmp = NULL;
00383       }
00384    } else 
00385       ast_log(LOG_WARNING, "Out of memory\n");
00386    ast_mutex_unlock(&chlock);
00387    return tmp;
00388 }
00389 
00390 int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin)
00391 {
00392    struct ast_frame *f;
00393    struct ast_frame *prev, *cur;
00394    int blah = 1;
00395    int qlen = 0;
00396    /* Build us a copy and free the original one */
00397    f = ast_frdup(fin);
00398    if (!f) {
00399       ast_log(LOG_WARNING, "Unable to duplicate frame\n");
00400       return -1;
00401    }
00402    ast_mutex_lock(&chan->lock);
00403    prev = NULL;
00404    cur = chan->pvt->readq;
00405    while(cur) {
00406       if ((cur->frametype == AST_FRAME_CONTROL) && (cur->subclass == AST_CONTROL_HANGUP)) {
00407          /* Don't bother actually queueing anything after a hangup */
00408          ast_frfree(f);
00409          ast_mutex_unlock(&chan->lock);
00410          return 0;
00411       }
00412       prev = cur;
00413       cur = cur->next;
00414       qlen++;
00415    }
00416    /* Allow up to 96 voice frames outstanding, and up to 128 total frames */
00417    if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen  > 128)) {
00418       if (fin->frametype != AST_FRAME_VOICE) {
00419          ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
00420          CRASH;
00421       } else {
00422          ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name);
00423          ast_frfree(f);
00424          ast_mutex_unlock(&chan->lock);
00425          return 0;
00426       }
00427    }
00428    if (prev)
00429       prev->next = f;
00430    else
00431       chan->pvt->readq = f;
00432    if (chan->pvt->alertpipe[1] > -1) {
00433       if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah))
00434          ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
00435             chan->name, f->frametype, f->subclass, qlen, strerror(errno));
00436 #ifdef ZAPTEL_OPTIMIZATIONS
00437    } else if (chan->timingfd > -1) {
00438       ioctl(chan->timingfd, ZT_TIMERPING, &blah);
00439 #endif            
00440    } else if (chan->blocking) {
00441       pthread_kill(chan->blocker, SIGURG);
00442    }
00443    ast_mutex_unlock(&chan->lock);
00444    return 0;
00445 }
00446 
00447 int ast_queue_hangup(struct ast_channel *chan)
00448 {
00449    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
00450    chan->_softhangup |= AST_SOFTHANGUP_DEV;
00451    return ast_queue_frame(chan, &f);
00452 }
00453 
00454 int ast_queue_control(struct ast_channel *chan, int control)
00455 {
00456    struct ast_frame f = { AST_FRAME_CONTROL, };
00457    f.subclass = control;
00458    return ast_queue_frame(chan, &f);
00459 }
00460 
00461 int ast_channel_defer_dtmf(struct ast_channel *chan)
00462 {
00463    int pre = 0;
00464    if (chan) {
00465       pre = chan->deferdtmf;
00466       chan->deferdtmf = 1;
00467    }
00468    return pre;
00469 }
00470 
00471 void ast_channel_undefer_dtmf(struct ast_channel *chan)
00472 {
00473    if (chan)
00474       chan->deferdtmf = 0;
00475 }
00476 
00477 struct ast_channel *ast_channel_walk_locked(struct ast_channel *prev)
00478 {
00479    /* Returns next channel (locked) */
00480    struct ast_channel *l, *ret;
00481    int retries = 0;  
00482 retry:
00483    ret=NULL;
00484    ast_mutex_lock(&chlock);
00485    l = channels;
00486    if (!prev) {
00487       if (l) {
00488          if (ast_mutex_trylock(&l->lock)) {
00489             if (retries < 10)
00490                ast_log(LOG_DEBUG, "Avoiding initial deadlock for '%s'\n", l->name);
00491             else
00492                ast_log(LOG_WARNING, "Avoided initial deadlock for '%s', %d retries!\n", l->name, retries);
00493             ast_mutex_unlock(&chlock);
00494             if (retries < 10) {
00495                usleep(1);
00496                retries++;
00497                goto retry;
00498             } else
00499                return NULL;
00500          }
00501       }
00502       ast_mutex_unlock(&chlock);
00503       return l;
00504    }
00505    while(l) {
00506       if (l == prev)
00507          ret = l->next;
00508       l = l->next;
00509    }
00510    if (ret) {
00511       if (ast_mutex_trylock(&ret->lock)) {
00512          if (retries < 10)
00513             ast_log(LOG_DEBUG, "Avoiding deadlock for '%s'\n", ret->name);
00514          else
00515             ast_log(LOG_WARNING, "Avoided deadlock for '%s', %d retries!\n", ret->name, retries);
00516          ast_mutex_unlock(&chlock);
00517          if (retries < 10) {
00518             usleep(1);
00519             retries++;
00520             goto retry;
00521          } else
00522             return NULL;
00523       }
00524    }
00525    ast_mutex_unlock(&chlock);
00526    return ret;
00527    
00528 }
00529 
00530 struct ast_channel *ast_get_channel_by_name_locked(char *channame)
00531 {
00532    struct ast_channel *chan;
00533    chan = ast_channel_walk_locked(NULL);
00534    while(chan) {
00535       if (!strcasecmp(chan->name, channame))
00536          return chan;
00537       ast_mutex_unlock(&chan->lock);
00538       chan = ast_channel_walk_locked(chan);
00539    }
00540    return NULL;
00541 }
00542 
00543 struct ast_channel *ast_get_channel_by_uniqueid_locked(char *uniqueid)
00544 {
00545    struct ast_channel *chan;
00546    chan = ast_channel_walk_locked(NULL);
00547    while(chan) {
00548       if (!strcasecmp(chan->uniqueid, uniqueid))
00549          return chan;
00550       ast_mutex_unlock(&chan->lock);
00551       chan = ast_channel_walk_locked(chan);
00552    }
00553    return NULL;
00554 }
00555 
00556 int ast_safe_sleep_conditional(  struct ast_channel *chan, int ms,
00557                         int (*cond)(void*), void *data )
00558 {
00559    struct ast_frame *f;
00560 
00561    while(ms > 0) {
00562       if( cond && ((*cond)(data) == 0 ) )
00563          return 0;
00564       ms = ast_waitfor(chan, ms);
00565       if (ms <0)
00566          return -1;
00567       if (ms > 0) {
00568          f = ast_read(chan);
00569          if (!f)
00570             return -1;
00571          ast_frfree(f);
00572       }
00573    }
00574    return 0;
00575 }
00576 
00577 int ast_safe_sleep(struct ast_channel *chan, int ms)
00578 {
00579    struct ast_frame *f;
00580    while(ms > 0) {
00581       ms = ast_waitfor(chan, ms);
00582       if (ms <0)
00583          return -1;
00584       if (ms > 0) {
00585          f = ast_read(chan);
00586          if (!f)
00587             return -1;
00588          ast_frfree(f);
00589       }
00590    }
00591    return 0;
00592 }
00593 
00594 void ast_channel_free(struct ast_channel *chan)
00595 {
00596    struct ast_channel *last=NULL, *cur;
00597    int fd;
00598    struct ast_var_t *vardata;
00599    struct ast_frame *f, *fp;
00600    struct varshead *headp;
00601    char name[AST_CHANNEL_NAME];
00602    
00603    headp=&chan->varshead;
00604    
00605    ast_mutex_lock(&chlock);
00606    cur = channels;
00607    while(cur) {
00608       if (cur == chan) {
00609          if (last)
00610             last->next = cur->next;
00611          else
00612             channels = cur->next;
00613          break;
00614       }
00615       last = cur;
00616       cur = cur->next;
00617    }
00618    if (!cur)
00619       ast_log(LOG_WARNING, "Unable to find channel in list\n");
00620    else {
00621       /* Lock and unlock the channel just to be sure nobody
00622          has it locked still */
00623       ast_mutex_lock(&cur->lock);
00624       ast_mutex_unlock(&cur->lock);
00625    }
00626    if (chan->pvt->pvt)
00627       ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
00628 
00629    strncpy(name, chan->name, sizeof(name)-1);
00630    
00631    /* Stop monitoring */
00632    if (chan->monitor) {
00633       chan->monitor->stop( chan, 0 );
00634    }
00635 
00636    /* Free translatosr */
00637    if (chan->pvt->readtrans)
00638       ast_translator_free_path(chan->pvt->readtrans);
00639    if (chan->pvt->writetrans)
00640       ast_translator_free_path(chan->pvt->writetrans);
00641    if (chan->pbx) 
00642       ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
00643    if (chan->dnid)
00644       free(chan->dnid);
00645    if (chan->callerid)
00646       free(chan->callerid);   
00647    if (chan->ani)
00648       free(chan->ani);
00649    if (chan->rdnis)
00650       free(chan->rdnis);
00651    ast_mutex_destroy(&chan->lock);
00652    /* Close pipes if appropriate */
00653    if ((fd = chan->pvt->alertpipe[0]) > -1)
00654       close(fd);
00655    if ((fd = chan->pvt->alertpipe[1]) > -1)
00656       close(fd);
00657    if ((fd = chan->timingfd) > -1)
00658       close(fd);
00659    f = chan->pvt->readq;
00660    chan->pvt->readq = NULL;
00661    while(f) {
00662       fp = f;
00663       f = f->next;
00664       ast_frfree(fp);
00665    }
00666    
00667    /* loop over the variables list, freeing all data and deleting list items */
00668    /* no need to lock the list, as the channel is already locked */
00669    
00670    while (!AST_LIST_EMPTY(headp)) {           /* List Deletion. */
00671                vardata = AST_LIST_FIRST(headp);
00672                AST_LIST_REMOVE_HEAD(headp, entries);
00673 //             printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata));
00674                ast_var_delete(vardata);
00675    }
00676                                                     
00677 
00678    free(chan->pvt);
00679    chan->pvt = NULL;
00680    free(chan);
00681    ast_mutex_unlock(&chlock);
00682 
00683    ast_device_state_changed(name);
00684 }
00685 
00686 int ast_softhangup_nolock(struct ast_channel *chan, int cause)
00687 {
00688    int res = 0;
00689    struct ast_frame f = { AST_FRAME_NULL };
00690    if (option_debug)
00691       ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name);
00692    /* Inform channel driver that we need to be hung up, if it cares */
00693    chan->_softhangup |= cause;
00694    ast_queue_frame(chan, &f);
00695    /* Interrupt any poll call or such */
00696    if (chan->blocking)
00697       pthread_kill(chan->blocker, SIGURG);
00698    return res;
00699 }
00700 
00701 int ast_softhangup(struct ast_channel *chan, int cause)
00702 {
00703    int res;
00704    ast_mutex_lock(&chan->lock);
00705    res = ast_softhangup_nolock(chan, cause);
00706    ast_mutex_unlock(&chan->lock);
00707    return res;
00708 }
00709 
00710 static void free_translation(struct ast_channel *clone)
00711 {
00712    if (clone->pvt->writetrans)
00713       ast_translator_free_path(clone->pvt->writetrans);
00714    if (clone->pvt->readtrans)
00715       ast_translator_free_path(clone->pvt->readtrans);
00716    clone->pvt->writetrans = NULL;
00717    clone->pvt->readtrans = NULL;
00718    clone->pvt->rawwriteformat = clone->nativeformats;
00719    clone->pvt->rawreadformat = clone->nativeformats;
00720 }
00721 
00722 int ast_hangup(struct ast_channel *chan)
00723 {
00724    int res = 0;
00725    /* Don't actually hang up a channel that will masquerade as someone else, or
00726       if someone is going to masquerade as us */
00727    ast_mutex_lock(&chan->lock);
00728    if (chan->masq) {
00729       if (ast_do_masquerade(chan)) 
00730          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
00731    }
00732 
00733    if (chan->masq) {
00734       ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
00735       ast_mutex_unlock(&chan->lock);
00736       return 0;
00737    }
00738    /* If this channel is one which will be masqueraded into something, 
00739       mark it as a zombie already, so we know to free it later */
00740    if (chan->masqr) {
00741       chan->zombie=1;
00742       ast_mutex_unlock(&chan->lock);
00743       return 0;
00744    }
00745    free_translation(chan);
00746    if (chan->stream) 
00747       ast_closestream(chan->stream);
00748    if (chan->vstream)
00749       ast_closestream(chan->vstream);
00750    if (chan->sched)
00751       sched_context_destroy(chan->sched);
00752    /* Clear any tone stuff remaining */
00753    if (chan->generatordata)
00754       chan->generator->release(chan, chan->generatordata);
00755    chan->generatordata = NULL;
00756    chan->generator = NULL;
00757    if (chan->cdr) {
00758       /* End the CDR if it hasn't already */
00759       ast_cdr_end(chan->cdr);
00760       /* Post and Free the CDR */
00761       ast_cdr_post(chan->cdr);
00762       ast_cdr_free(chan->cdr);
00763    }
00764    if (chan->blocking) {
00765       ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
00766                "is blocked by thread %ld in procedure %s!  Expect a failure\n",
00767                (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc);
00768       CRASH;
00769    }
00770    if (!chan->zombie) {
00771       if (option_debug)
00772          ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
00773       if (chan->pvt->hangup)
00774          res = chan->pvt->hangup(chan);
00775    } else
00776       if (option_debug)
00777          ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
00778          
00779    ast_mutex_unlock(&chan->lock);
00780    manager_event(EVENT_FLAG_CALL, "Hangup", 
00781          "Channel: %s\r\n"
00782          "Uniqueid: %s\r\n"
00783          "Cause: %i\r\n",
00784          chan->name, chan->uniqueid, chan->hangupcause);
00785    ast_channel_free(chan);
00786    return res;
00787 }
00788 
00789 void ast_channel_unregister(char *type)
00790 {
00791    struct chanlist *chan, *last=NULL;
00792    if (option_debug)
00793       ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type);
00794    if (ast_mutex_lock(&chlock)) {
00795       ast_log(LOG_WARNING, "Unable to lock channel list\n");
00796       return;
00797    }
00798    if (option_verbose > 1)
00799       ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type);
00800 
00801    chan = backends;
00802    while(chan) {
00803       if (!strcasecmp(chan->type, type)) {
00804          if (last)
00805             last->next = chan->next;
00806          else
00807             backends = backends->next;
00808          free(chan);
00809          ast_mutex_unlock(&chlock);
00810          return;
00811       }
00812       last = chan;
00813       chan = chan->next;
00814    }
00815    ast_mutex_unlock(&chlock);
00816 }
00817 
00818 int ast_answer(struct ast_channel *chan)
00819 {
00820    int res = 0;
00821    ast_mutex_lock(&chan->lock);
00822    /* Stop if we're a zombie or need a soft hangup */
00823    if (chan->zombie || ast_check_hangup(chan)) {
00824       ast_mutex_unlock(&chan->lock);
00825       return -1;
00826    }
00827    switch(chan->_state) {
00828    case AST_STATE_RINGING:
00829    case AST_STATE_RING:
00830       if (chan->pvt->answer)
00831          res = chan->pvt->answer(chan);
00832       ast_setstate(chan, AST_STATE_UP);
00833       if (chan->cdr)
00834          ast_cdr_answer(chan->cdr);
00835       ast_mutex_unlock(&chan->lock);
00836       return res;
00837       break;
00838    case AST_STATE_UP:
00839       if (chan->cdr)
00840          ast_cdr_answer(chan->cdr);
00841       break;
00842    }
00843    ast_mutex_unlock(&chan->lock);
00844    return 0;
00845 }
00846 
00847 
00848 
00849 void ast_deactivate_generator(struct ast_channel *chan)
00850 {
00851    ast_mutex_lock(&chan->lock);
00852    if (chan->generatordata) {
00853       if (chan->generator && chan->generator->release) 
00854          chan->generator->release(chan, chan->generatordata);
00855       chan->generatordata = NULL;
00856       chan->generator = NULL;
00857       chan->writeinterrupt = 0;
00858       ast_settimeout(chan, 0, NULL, NULL);
00859    }
00860    ast_mutex_unlock(&chan->lock);
00861 }
00862 
00863 static int generator_force(void *data)
00864 {
00865    /* Called if generator doesn't have data */
00866    void *tmp;
00867    int res;
00868    int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
00869    struct ast_channel *chan = data;
00870    tmp = chan->generatordata;
00871    chan->generatordata = NULL;
00872    generate = chan->generator->generate;
00873    res = generate(chan, tmp, 0, 160);
00874    chan->generatordata = tmp;
00875    if (res) {
00876       ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
00877       ast_deactivate_generator(chan);
00878    }
00879    return 0;
00880 }
00881 
00882 int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
00883 {
00884    int res = 0;
00885    ast_mutex_lock(&chan->lock);
00886    if (chan->generatordata) {
00887       if (chan->generator && chan->generator->release)
00888          chan->generator->release(chan, chan->generatordata);
00889       chan->generatordata = NULL;
00890    }
00891    ast_prod(chan);
00892    if ((chan->generatordata = gen->alloc(chan, params))) {
00893       ast_settimeout(chan, 160, generator_force, chan);
00894       chan->generator = gen;
00895    } else {
00896       res = -1;
00897    }
00898    ast_mutex_unlock(&chan->lock);
00899    return res;
00900 }
00901 
00902 int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
00903 {
00904    /* Wait for x amount of time on a file descriptor to have input.  */
00905    struct timeval start, now;
00906    int res;
00907    int x, y;
00908    int winner = -1;
00909    int spoint;
00910    struct pollfd *pfds;
00911    
00912    pfds = alloca(sizeof(struct pollfd) * n);
00913    if (!pfds) {
00914       ast_log(LOG_WARNING, "alloca failed!  bad things will happen.\n");
00915       return -1;
00916    }
00917    if (*ms > 0)
00918       gettimeofday(&start, NULL);
00919    y = 0;
00920    for (x=0;x<n;x++) {
00921       if (fds[x] > -1) {
00922          pfds[y].fd = fds[x];
00923          pfds[y].events = POLLIN | POLLPRI;
00924          y++;
00925       }
00926    }
00927    res = poll(pfds, y, *ms);
00928    if (res < 0) {
00929       /* Simulate a timeout if we were interrupted */
00930       if (errno != EINTR)
00931          *ms = -1;
00932       else
00933          *ms = 0;
00934       return -1;
00935    }
00936    spoint = 0;
00937    for (x=0;x<n;x++) {
00938       if (fds[x] > -1) {
00939          if ((res = ast_fdisset(pfds, fds[x], y, &spoint))) {
00940             winner = fds[x];
00941             if (exception) {
00942                if (res & POLLPRI)
00943                   *exception = -1;
00944                else
00945                   *exception = 0;
00946             }
00947          }
00948       }
00949    }
00950    if (*ms > 0) {
00951       long passed;
00952       gettimeofday(&now, NULL);
00953       passed = (now.tv_sec - start.tv_sec) * 1000;
00954       passed += (now.tv_usec - start.tv_usec) / 1000;
00955       if (passed <= *ms)
00956          *ms -= passed;
00957       else
00958          *ms = 0;
00959    }
00960    return winner;
00961 }
00962 
00963 struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds, 
00964    int *exception, int *outfd, int *ms)
00965 {
00966    /* Wait for x amount of time on a file descriptor to have input.  */
00967    struct timeval start, end;
00968    struct pollfd *pfds;
00969    int res;
00970    long rms;
00971    int x, y, max;
00972    int spoint;
00973    time_t now = 0;
00974    long whentohangup = 0, havewhen = 0, diff;
00975    struct ast_channel *winner = NULL;
00976 
00977    pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds));
00978    if (!pfds) {
00979       ast_log(LOG_WARNING, "alloca failed!  bad things will happen.\n");
00980       *outfd = -1;
00981       return NULL;
00982    }
00983 
00984    if (outfd)
00985       *outfd = -99999;
00986    if (exception)
00987       *exception = 0;
00988    
00989    /* Perform any pending masquerades */
00990    for (x=0;x<n;x++) {
00991       ast_mutex_lock(&c[x]->lock);
00992       if (c[x]->whentohangup) {
00993          if (!havewhen)
00994             time(&now);
00995          diff = c[x]->whentohangup - now;
00996          if (!havewhen || (diff < whentohangup)) {
00997             havewhen++;
00998             whentohangup = diff;
00999          }
01000       }
01001       if (c[x]->masq) {
01002          if (ast_do_masquerade(c[x])) {
01003             ast_log(LOG_WARNING, "Masquerade failed\n");
01004             *ms = -1;
01005             ast_mutex_unlock(&c[x]->lock);
01006             return NULL;
01007          }
01008       }
01009       ast_mutex_unlock(&c[x]->lock);
01010    }
01011 
01012    rms = *ms;
01013    
01014    if (havewhen) {
01015       if ((*ms < 0) || (whentohangup * 1000 < *ms)) {
01016          rms =  whentohangup * 1000;
01017       }
01018    }
01019    max = 0;
01020    for (x=0;x<n;x++) {
01021       for (y=0;y<AST_MAX_FDS;y++) {
01022          if (c[x]->fds[y] > -1) {
01023             pfds[max].fd = c[x]->fds[y];
01024             pfds[max].events = POLLIN | POLLPRI;
01025             max++;
01026          }
01027       }
01028       CHECK_BLOCKING(c[x]);
01029    }
01030    for (x=0;x<nfds; x++) {
01031       if (fds[x] > -1) {
01032          pfds[max].fd = fds[x];
01033          pfds[max].events = POLLIN | POLLPRI;
01034          max++;
01035       }
01036    }
01037    if (*ms > 0) 
01038       gettimeofday(&start, NULL);
01039    res = poll(pfds, max, rms);
01040    if (res < 0) {
01041       for (x=0;x<n;x++) 
01042          c[x]->blocking = 0;
01043       /* Simulate a timeout if we were interrupted */
01044       if (errno != EINTR)
01045          *ms = -1;
01046       else {
01047          /* Just an interrupt */
01048 #if 0
01049          *ms = 0;
01050 #endif         
01051       }
01052       return NULL;
01053    }
01054 
01055    if (havewhen)
01056       time(&now);
01057    spoint = 0;
01058    for (x=0;x<n;x++) {
01059       c[x]->blocking = 0;
01060       if (havewhen && c[x]->whentohangup && (now > c[x]->whentohangup)) {
01061          c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
01062          if (!winner)
01063             winner = c[x];
01064       }
01065       for (y=0;y<AST_MAX_FDS;y++) {
01066          if (c[x]->fds[y] > -1) {
01067             if ((res = ast_fdisset(pfds, c[x]->fds[y], max, &spoint))) {
01068                if (res & POLLPRI)
01069                   c[x]->exception = -1;
01070                else
01071                   c[x]->exception = 0;
01072                c[x]->fdno = y;
01073                winner = c[x];
01074             }
01075          }
01076       }
01077    }
01078    for (x=0;x<nfds;x++) {
01079       if (fds[x] > -1) {
01080          if ((res = ast_fdisset(pfds, fds[x], max, &spoint))) {
01081             if (outfd)
01082                *outfd = fds[x];
01083             if (exception) {  
01084                if (res & POLLPRI) 
01085                   *exception = -1;
01086                else
01087                   *exception = 0;
01088             }
01089             winner = NULL;
01090          }
01091       }  
01092    }
01093    if (*ms > 0) {
01094       long diff;
01095       gettimeofday(&end, NULL);
01096       diff = (end.tv_sec - start.tv_sec) * 1000;
01097       diff += (end.tv_usec - start.tv_usec) / 1000;
01098       if (diff < *ms)
01099          *ms -= diff;
01100       else
01101          *ms = 0;
01102    }
01103    return winner;
01104 }
01105 
01106 struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
01107 {
01108    return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
01109 }
01110 
01111 int ast_waitfor(struct ast_channel *c, int ms)
01112 {
01113    struct ast_channel *chan;
01114    int oldms = ms;
01115    chan = ast_waitfor_n(&c, 1, &ms);
01116    if (ms < 0) {
01117       if (oldms < 0)
01118          return 0;
01119       else
01120          return -1;
01121    }
01122    return ms;
01123 }
01124 
01125 char ast_waitfordigit(struct ast_channel *c, int ms)
01126 {
01127    /* XXX Should I be merged with waitfordigit_full XXX */
01128    struct ast_frame *f;
01129    char result = 0;
01130    /* Stop if we're a zombie or need a soft hangup */
01131    if (c->zombie || ast_check_hangup(c)) 
01132       return -1;
01133    /* Wait for a digit, no more than ms milliseconds total. */
01134    while(ms && !result) {
01135       ms = ast_waitfor(c, ms);
01136       if (ms < 0) /* Error */
01137          result = -1; 
01138       else if (ms > 0) {
01139          /* Read something */
01140          f = ast_read(c);
01141          if (f) {
01142             if (f->frametype == AST_FRAME_DTMF) 
01143                result = f->subclass;
01144             ast_frfree(f);
01145          } else
01146             result = -1;
01147       }
01148    }
01149    return result;
01150 }
01151 
01152 int ast_settimeout(struct ast_channel *c, int samples, int (*func)(void *data), void *data)
01153 {
01154    int res = -1;
01155 #ifdef ZAPTEL_OPTIMIZATIONS
01156    if (c->timingfd > -1) {
01157       if (!func) {
01158          samples = 0;
01159          data = 0;
01160       }
01161       ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples);
01162       res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples);
01163       c->timingfunc = func;
01164       c->timingdata = data;
01165    }
01166 #endif   
01167    return res;
01168 }
01169 char ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int cmdfd)
01170 {
01171    struct ast_frame *f;
01172    struct ast_channel *rchan;
01173    int outfd;
01174    int res;
01175    /* Stop if we're a zombie or need a soft hangup */
01176    if (c->zombie || ast_check_hangup(c)) 
01177       return -1;
01178    /* Wait for a digit, no more than ms milliseconds total. */
01179    while(ms) {
01180       rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01181       if ((!rchan) && (outfd < 0) && (ms)) { 
01182          ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01183          return -1;
01184       } else if (outfd > -1) {
01185          /* The FD we were watching has something waiting */
01186          return 1;
01187       } else if (rchan) {
01188          f = ast_read(c);
01189          if(!f) {
01190             return -1;
01191          }
01192 
01193          switch(f->frametype) {
01194          case AST_FRAME_DTMF:
01195             res = f->subclass;
01196             ast_frfree(f);
01197             return res;
01198          case AST_FRAME_CONTROL:
01199             switch(f->subclass) {
01200             case AST_CONTROL_HANGUP:
01201                ast_frfree(f);
01202                return -1;
01203             case AST_CONTROL_RINGING:
01204             case AST_CONTROL_ANSWER:
01205                /* Unimportant */
01206                break;
01207             default:
01208                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass);
01209             }
01210          case AST_FRAME_VOICE:
01211             /* Write audio if appropriate */
01212             if (audiofd > -1)
01213                write(audiofd, f->data, f->datalen);
01214          }
01215          /* Ignore */
01216          ast_frfree(f);
01217       }
01218    }
01219    return 0; // Time is up
01220 }
01221 
01222 struct ast_frame *ast_read(struct ast_channel *chan)
01223 {
01224    struct ast_frame *f = NULL;
01225    int blah;
01226 #ifdef ZAPTEL_OPTIMIZATIONS
01227    int (*func)(void *);
01228    void *data;
01229    int res;
01230 #endif
01231    static struct ast_frame null_frame = 
01232    {
01233       AST_FRAME_NULL,
01234    };
01235    
01236    ast_mutex_lock(&chan->lock);
01237    if (chan->masq) {
01238       if (ast_do_masquerade(chan)) {
01239          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01240          f = NULL;
01241       } else
01242          f =  &null_frame;
01243       ast_mutex_unlock(&chan->lock);
01244       return f;
01245    }
01246 
01247    /* Stop if we're a zombie or need a soft hangup */
01248    if (chan->zombie || ast_check_hangup(chan)) {
01249       if (chan->generator)
01250          ast_deactivate_generator(chan);
01251       ast_mutex_unlock(&chan->lock);
01252       return NULL;
01253    }
01254 
01255    if (!chan->deferdtmf && !ast_strlen_zero(chan->dtmfq)) {
01256       /* We have DTMF that has been deferred.  Return it now */
01257       chan->dtmff.frametype = AST_FRAME_DTMF;
01258       chan->dtmff.subclass = chan->dtmfq[0];
01259       /* Drop first digit */
01260       memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
01261       ast_mutex_unlock(&chan->lock);
01262       return &chan->dtmff;
01263    }
01264    
01265    /* Read and ignore anything on the alertpipe, but read only
01266       one sizeof(blah) per frame that we send from it */
01267    if (chan->pvt->alertpipe[0] > -1) {
01268       read(chan->pvt->alertpipe[0], &blah, sizeof(blah));
01269    }
01270 #ifdef ZAPTEL_OPTIMIZATIONS
01271    if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) {
01272       chan->exception = 0;
01273       blah = -1;
01274       /* IF we can't get event, assume it's an expired as-per the old interface */
01275       res = ioctl(chan->timingfd, ZT_GETEVENT, &blah);
01276       if (res) 
01277          blah = ZT_EVENT_TIMER_EXPIRED;
01278 
01279       if (blah == ZT_EVENT_TIMER_PING) {
01280 #if 0
01281          ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
01282 #endif         
01283          if (!chan->pvt->readq || !chan->pvt->readq->next) {
01284             /* Acknowledge PONG unless we need it again */
01285 #if 0
01286             ast_log(LOG_NOTICE, "Sending a PONG!\n");
01287 #endif            
01288             if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) {
01289                ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno));
01290             }
01291          }
01292       } else if (blah == ZT_EVENT_TIMER_EXPIRED) {
01293          ioctl(chan->timingfd, ZT_TIMERACK, &blah);
01294          func = chan->timingfunc;
01295          data = chan->timingdata;
01296          ast_mutex_unlock(&chan->lock);
01297          if (func) {
01298 #if 0
01299             ast_log(LOG_DEBUG, "Calling private function\n");
01300 #endif         
01301             func(data);
01302          } else {
01303             blah = 0;
01304             ast_mutex_lock(&chan->lock);
01305             ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
01306             chan->timingdata = NULL;
01307             ast_mutex_unlock(&chan->lock);
01308          }
01309          f =  &null_frame;
01310          return f;
01311       } else
01312          ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
01313    }
01314 #endif
01315    /* Check for pending read queue */
01316    if (chan->pvt->readq) {
01317       f = chan->pvt->readq;
01318       chan->pvt->readq = f->next;
01319       /* Interpret hangup and return NULL */
01320       if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
01321          ast_frfree(f);
01322          f = NULL;
01323       }
01324    } else {
01325       chan->blocker = pthread_self();
01326       if (chan->exception) {
01327          if (chan->pvt->exception) 
01328             f = chan->pvt->exception(chan);
01329          else {
01330             ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
01331             f = &null_frame;
01332          }
01333          /* Clear the exception flag */
01334          chan->exception = 0;
01335       } else
01336       if (chan->pvt->read)
01337          f = chan->pvt->read(chan);
01338       else
01339          ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
01340    }
01341 
01342 
01343    if (f && (f->frametype == AST_FRAME_VOICE)) {
01344       if (!(f->subclass & chan->nativeformats)) {
01345          /* This frame can't be from the current native formats -- drop it on the
01346             floor */
01347          ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", chan->name, ast_getformatname(f->subclass), ast_getformatname(chan->nativeformats));
01348          ast_frfree(f);
01349          f = &null_frame;
01350       } else {
01351          if (chan->monitor && chan->monitor->read_stream ) {
01352 #ifndef MONITOR_CONSTANT_DELAY
01353             int jump = chan->outsmpl - chan->insmpl - 2 * f->samples;
01354             if (jump >= 0) {
01355                if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01356                   ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01357                chan->insmpl += jump + 2 * f->samples;
01358             } else
01359                chan->insmpl+= f->samples;
01360 #else
01361             int jump = chan->outsmpl - chan->insmpl;
01362             if (jump - MONITOR_DELAY >= 0) {
01363                if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01364                   ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01365                chan->insmpl += jump;
01366             } else
01367                chan->insmpl += f->samples;
01368 #endif
01369             if (ast_writestream(chan->monitor->read_stream, f) < 0)
01370                ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
01371          }
01372          if (chan->pvt->readtrans) {
01373             f = ast_translate(chan->pvt->readtrans, f, 1);
01374             if (!f)
01375                f = &null_frame;
01376          }
01377       }
01378    }
01379 
01380    /* Make sure we always return NULL in the future */
01381    if (!f) {
01382       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01383       if (chan->generator)
01384          ast_deactivate_generator(chan);
01385       /* End the CDR if appropriate */
01386       if (chan->cdr)
01387          ast_cdr_end(chan->cdr);
01388    } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
01389       if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
01390          chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
01391       else
01392          ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
01393       f = &null_frame;
01394    } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
01395       if (chan->_state == AST_STATE_UP) {
01396          ast_log(LOG_DEBUG, "Dropping duplicate answer!\n");
01397          f = &null_frame;
01398       }
01399       /* Answer the CDR */
01400       ast_setstate(chan, AST_STATE_UP);
01401       ast_cdr_answer(chan->cdr);
01402    } 
01403 
01404    /* Run any generator sitting on the line */
01405    if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
01406       /* Mask generator data temporarily and apply.  If there is a timing function, it
01407          will be calling the generator instead */
01408       void *tmp;
01409       int res;
01410       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
01411       if (chan->timingfunc) {
01412          ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
01413          ast_settimeout(chan, 0, NULL, NULL);
01414       }
01415       tmp = chan->generatordata;
01416       chan->generatordata = NULL;
01417       generate = chan->generator->generate;
01418       res = generate(chan, tmp, f->datalen, f->samples);
01419       chan->generatordata = tmp;
01420       if (res) {
01421          ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
01422          ast_deactivate_generator(chan);
01423       }
01424    } else if (f && (f->frametype == AST_FRAME_CNG)) {
01425       if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) {
01426          ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n");
01427          ast_settimeout(chan, 160, generator_force, chan);
01428       }
01429    }
01430    if (chan->fin & 0x80000000)
01431       ast_frame_dump(chan->name, f, "<<");
01432    if ((chan->fin & 0x7fffffff) == 0x7fffffff)
01433       chan->fin &= 0x80000000;
01434    else
01435       chan->fin++;
01436    ast_mutex_unlock(&chan->lock);
01437    return f;
01438 }
01439 
01440 int ast_indicate(struct ast_channel *chan, int condition)
01441 {
01442    int res = -1;
01443    /* Stop if we're a zombie or need a soft hangup */
01444    if (chan->zombie || ast_check_hangup(chan)) 
01445       return -1;
01446    ast_mutex_lock(&chan->lock);
01447    if (chan->pvt->indicate)
01448       res = chan->pvt->indicate(chan, condition);
01449    ast_mutex_unlock(&chan->lock);
01450    if (!chan->pvt->indicate || res) {
01451       /*
01452        * Device does not support (that) indication, lets fake
01453        * it by doing our own tone generation. (PM2002)
01454        */
01455       if (condition >= 0) {
01456          const struct tone_zone_sound *ts = NULL;
01457          switch (condition) {
01458           case AST_CONTROL_RINGING:
01459             ts = ast_get_indication_tone(chan->zone, "ring");
01460             break;
01461           case AST_CONTROL_BUSY:
01462             ts = ast_get_indication_tone(chan->zone, "busy");
01463             break;
01464           case AST_CONTROL_CONGESTION:
01465             ts = ast_get_indication_tone(chan->zone, "congestion");
01466             break;
01467          }
01468          if (ts && ts->data[0]) {
01469             ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
01470             ast_playtones_start(chan,0,ts->data, 1);
01471             res = 0;
01472          } else if (condition == AST_CONTROL_PROGRESS) {
01473             /* ast_playtones_stop(chan); */
01474          } else if (condition == AST_CONTROL_PROCEEDING) {
01475             /* Do nothing, really */
01476          } else {
01477             /* not handled */
01478             ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
01479             res = -1;
01480          }
01481       }
01482       else ast_playtones_stop(chan);
01483    }
01484    return res;
01485 }
01486 
01487 int ast_recvchar(struct ast_channel *chan, int timeout)
01488 {
01489    int res,ourto,c;
01490    struct ast_frame *f;
01491    
01492    ourto = timeout;
01493    for(;;)
01494       {
01495       if (ast_check_hangup(chan)) return -1;
01496       res = ast_waitfor(chan,ourto);
01497       if (res <= 0) /* if timeout */
01498          {
01499          return 0;
01500          }
01501       ourto = res;
01502       f = ast_read(chan);
01503       if (f == NULL) return -1; /* if hangup */
01504       if ((f->frametype == AST_FRAME_CONTROL) &&
01505           (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
01506       if (f->frametype == AST_FRAME_TEXT)  /* if a text frame */
01507          {
01508          c = *((char *)f->data);  /* get the data */
01509          ast_frfree(f);
01510          return(c);
01511          }
01512       ast_frfree(f);
01513    }
01514 }
01515 
01516 int ast_sendtext(struct ast_channel *chan, char *text)
01517 {
01518    int res = 0;
01519    /* Stop if we're a zombie or need a soft hangup */
01520    if (chan->zombie || ast_check_hangup(chan)) 
01521       return -1;
01522    CHECK_BLOCKING(chan);
01523    if (chan->pvt->send_text)
01524       res = chan->pvt->send_text(chan, text);
01525    chan->blocking = 0;
01526    return res;
01527 }
01528 
01529 static int do_senddigit(struct ast_channel *chan, char digit)
01530 {
01531    int res = -1;
01532 
01533    if (chan->pvt->send_digit)
01534       res = chan->pvt->send_digit(chan, digit);
01535    if (!chan->pvt->send_digit || res) {
01536       /*
01537        * Device does not support DTMF tones, lets fake
01538        * it by doing our own generation. (PM2002)
01539        */
01540       static const char* dtmf_tones[] = {
01541          "!941+1336/100,!0/100", /* 0 */
01542          "!697+1209/100,!0/100", /* 1 */
01543          "!697+1336/100,!0/100", /* 2 */
01544          "!697+1477/100,!0/100", /* 3 */
01545          "!770+1209/100,!0/100", /* 4 */
01546          "!770+1336/100,!0/100", /* 5 */
01547          "!770+1477/100,!0/100", /* 6 */
01548          "!852+1209/100,!0/100", /* 7 */
01549          "!852+1336/100,!0/100", /* 8 */
01550          "!852+1477/100,!0/100", /* 9 */
01551          "!697+1633/100,!0/100", /* A */
01552          "!770+1633/100,!0/100", /* B */
01553          "!852+1633/100,!0/100", /* C */
01554          "!941+1633/100,!0/100", /* D */
01555          "!941+1209/100,!0/100", /* * */
01556          "!941+1477/100,!0/100" };  /* # */
01557       if (digit >= '0' && digit <='9')
01558          ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
01559       else if (digit >= 'A' && digit <= 'D')
01560          ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
01561       else if (digit == '*')
01562          ast_playtones_start(chan,0,dtmf_tones[14], 0);
01563       else if (digit == '#')
01564          ast_playtones_start(chan,0,dtmf_tones[15], 0);
01565       else {
01566          /* not handled */
01567          ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
01568       }
01569    }
01570    return 0;
01571 }
01572 
01573 int ast_senddigit(struct ast_channel *chan, char digit)
01574 {
01575    return do_senddigit(chan, digit);
01576 }
01577 
01578 int ast_prod(struct ast_channel *chan)
01579 {
01580    struct ast_frame a = { AST_FRAME_VOICE };
01581    char nothing[128];
01582    /* Send an empty audio frame to get things moving */
01583    if (chan->_state != AST_STATE_UP) {
01584       ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
01585       a.subclass = chan->pvt->rawwriteformat;
01586       a.data = nothing + AST_FRIENDLY_OFFSET;
01587       if (ast_write(chan, &a))
01588          ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name);
01589    }
01590    return 0;
01591 }
01592 
01593 int ast_write_video(struct ast_channel *chan, struct ast_frame *fr)
01594 {
01595    int res;
01596    if (!chan->pvt->write_video)
01597       return 0;
01598    res = ast_write(chan, fr);
01599    if (!res)
01600       res = 1;
01601    return res;
01602 }
01603 
01604 int ast_write(struct ast_channel *chan, struct ast_frame *fr)
01605 {
01606    int res = -1;
01607    struct ast_frame *f = NULL;
01608    /* Stop if we're a zombie or need a soft hangup */
01609    ast_mutex_lock(&chan->lock);
01610    if (chan->zombie || ast_check_hangup(chan))  {
01611       ast_mutex_unlock(&chan->lock);
01612       return -1;
01613    }
01614    /* Handle any pending masquerades */
01615    if (chan->masq) {
01616       if (ast_do_masquerade(chan)) {
01617          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01618          ast_mutex_unlock(&chan->lock);
01619          return -1;
01620       }
01621    }
01622    if (chan->masqr) {
01623       ast_mutex_unlock(&chan->lock);
01624       return 0;
01625    }
01626    if (chan->generatordata) {
01627       if (chan->writeinterrupt)
01628          ast_deactivate_generator(chan);
01629       else {
01630          ast_mutex_unlock(&chan->lock);
01631          return 0;
01632       }
01633    }
01634    if (chan->fout & 0x80000000)
01635       ast_frame_dump(chan->name, fr, ">>");
01636    CHECK_BLOCKING(chan);
01637    switch(fr->frametype) {
01638    case AST_FRAME_CONTROL:
01639       /* XXX Interpret control frames XXX */
01640       ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
01641       break;
01642    case AST_FRAME_DTMF:
01643       chan->blocking = 0;
01644       ast_mutex_unlock(&chan->lock);
01645       res = do_senddigit(chan,fr->subclass);
01646       ast_mutex_lock(&chan->lock);
01647       CHECK_BLOCKING(chan);
01648       break;
01649    case AST_FRAME_TEXT:
01650       if (chan->pvt->send_text)
01651          res = chan->pvt->send_text(chan, (char *) fr->data);
01652       break;
01653    case AST_FRAME_VIDEO:
01654       /* XXX Handle translation of video codecs one day XXX */
01655       if (chan->pvt->write_video)
01656          res = chan->pvt->write_video(chan, fr);
01657       else
01658          res = 0;
01659       break;
01660    default:
01661       if (chan->pvt->write) {
01662          if (chan->pvt->writetrans) {
01663             f = ast_translate(chan->pvt->writetrans, fr, 0);
01664          } else
01665             f = fr;
01666          if (f) {
01667             res = chan->pvt->write(chan, f);
01668             if( chan->monitor &&
01669                   chan->monitor->write_stream &&
01670                   f && ( f->frametype == AST_FRAME_VOICE ) ) {
01671 #ifndef MONITOR_CONSTANT_DELAY
01672                int jump = chan->insmpl - chan->outsmpl - 2 * f->samples;
01673                if (jump >= 0) {
01674                   if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01675                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01676                   chan->outsmpl += jump + 2 * f->samples;
01677                } else
01678                   chan->outsmpl += f->samples;
01679 #else
01680                int jump = chan->insmpl - chan->outsmpl;
01681                if (jump - MONITOR_DELAY >= 0) {
01682                   if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01683                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01684                   chan->outsmpl += jump;
01685                } else
01686                   chan->outsmpl += f->samples;
01687 #endif
01688             if (ast_writestream(chan->monitor->write_stream, f) < 0)
01689                   ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
01690             }
01691          } else
01692             res = 0;
01693       }
01694    }
01695    if (f && (f != fr))
01696       ast_frfree(f);
01697    chan->blocking = 0;
01698    /* Consider a write failure to force a soft hangup */
01699    if (res < 0)
01700       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01701    else {
01702       if ((chan->fout & 0x7fffffff) == 0x7fffffff)
01703          chan->fout &= 0x80000000;
01704       else
01705          chan->fout++;
01706       chan->fout++;
01707    }
01708    ast_mutex_unlock(&chan->lock);
01709    return res;
01710 }
01711 
01712 int ast_set_write_format(struct ast_channel *chan, int fmts)
01713 {
01714    int fmt;
01715    int native;
01716    int res;
01717    
01718    ast_mutex_lock(&chan->lock);
01719    native = chan->nativeformats;
01720    fmt = fmts;
01721    
01722    res = ast_translator_best_choice(&native, &fmt);
01723    if (res < 0) {
01724       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01725          ast_getformatname(fmts), ast_getformatname(chan->nativeformats));
01726       ast_mutex_unlock(&chan->lock);
01727       return -1;
01728    }
01729    
01730    /* Now we have a good choice for both.  We'll write using our native format. */
01731    chan->pvt->rawwriteformat = native;
01732    /* User perspective is fmt */
01733    chan->writeformat = fmt;
01734    /* Free any write translation we have right now */
01735    if (chan->pvt->writetrans)
01736       ast_translator_free_path(chan->pvt->writetrans);
01737    /* Build a translation path from the user write format to the raw writing format */
01738    chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
01739    if (option_debug)
01740       ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat));
01741    ast_mutex_unlock(&chan->lock);
01742    return 0;
01743 }
01744 
01745 int ast_set_read_format(struct ast_channel *chan, int fmts)
01746 {
01747    int fmt;
01748    int native;
01749    int res;
01750    
01751    ast_mutex_lock(&chan->lock);
01752    native = chan->nativeformats;
01753    fmt = fmts;
01754    /* Find a translation path from the native read format to one of the user's read formats */
01755    res = ast_translator_best_choice(&fmt, &native);
01756    if (res < 0) {
01757       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01758          ast_getformatname(chan->nativeformats), ast_getformatname(fmts));
01759       ast_mutex_unlock(&chan->lock);
01760       return -1;
01761    }
01762    
01763    /* Now we have a good choice for both.  We'll write using our native format. */
01764    chan->pvt->rawreadformat = native;
01765    /* User perspective is fmt */
01766    chan->readformat = fmt;
01767    /* Free any read translation we have right now */
01768    if (chan->pvt->readtrans)
01769       ast_translator_free_path(chan->pvt->readtrans);
01770    /* Build a translation path from the raw read format to the user reading format */
01771    chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
01772    if (option_debug)
01773       ast_log(LOG_DEBUG, "Set channel %s to read format %s\n", 
01774          chan->name, ast_getformatname(chan->readformat));
01775    ast_mutex_unlock(&chan->lock);
01776    return 0;
01777 }
01778 
01779 struct ast_channel *__ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate, int callingpres, char *callerid, struct outgoing_helper *oh, char* uniqueid)
01780 {
01781    int state = 0;
01782    struct ast_channel *chan;
01783    struct ast_frame *f;
01784    int res = 0;
01785    char *variable;
01786    chan = ast_request(type, format, data, uniqueid);
01787    if (chan) {
01788       if (oh) {
01789          char *tmp, *var;
01790          /* JDG chanvar */
01791          if (oh->variable)
01792             variable = ast_strdupa(oh->variable);
01793          else
01794             variable = NULL;
01795          tmp = variable;
01796          /* FIXME replace this call with strsep  NOT*/
01797          while( (var = strtok_r(NULL, "|", &tmp)) ) {
01798             pbx_builtin_setvar( chan, var );
01799          } /* /JDG */
01800          if (oh->callerid && *oh->callerid)
01801             ast_set_callerid(chan, oh->callerid, 1);
01802          if (oh->account && *oh->account)
01803             ast_cdr_setaccount(chan, oh->account);
01804       }
01805       if (callerid && !ast_strlen_zero(callerid))
01806          ast_set_callerid(chan, callerid, 1);
01807 
01808       chan->callingpres = callingpres;
01809       if (!ast_call(chan, data, 0)) {
01810          while(timeout && (chan->_state != AST_STATE_UP)) {
01811             res = ast_waitfor(chan, timeout);
01812             if (res < 0) {
01813                /* Something not cool, or timed out */
01814                break;
01815             }
01816             /* If done, break out */
01817             if (!res)
01818                break;
01819             if (timeout > -1)
01820                timeout = res;
01821             f = ast_read(chan);
01822             if (!f) {
01823                state = AST_CONTROL_HANGUP;
01824                res = 0;
01825                break;
01826             }
01827             if (f->frametype == AST_FRAME_CONTROL) {
01828                if (f->subclass == AST_CONTROL_RINGING)
01829                   state = AST_CONTROL_RINGING;
01830                else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01831                   res = 0;
01832                   state = f->subclass;
01833                   ast_frfree(f);
01834                   break;
01835                } else if (f->subclass == AST_CONTROL_ANSWER) {
01836                   state = f->subclass;
01837                   ast_frfree(f);
01838                   break;
01839                } else if (f->subclass == AST_CONTROL_PROGRESS) {
01840                   /* Ignore */
01841                } else if (f->subclass == -1) {
01842                   /* Ignore -- just stopping indications */
01843                } else {
01844                   ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
01845                }
01846             }
01847             ast_frfree(f);
01848          }
01849       } else
01850          ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01851    } else
01852       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01853    if (chan) {
01854       /* Final fixups */
01855       if (oh) {
01856          if (oh->context && *oh->context)
01857             strncpy(chan->context, oh->context, sizeof(chan->context) - 1);
01858          if (oh->exten && *oh->exten)
01859             strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1);
01860          chan->priority = oh->priority;
01861       }
01862       if (chan->_state == AST_STATE_UP) 
01863          state = AST_CONTROL_ANSWER;
01864    }
01865    if (outstate)
01866       *outstate = state;
01867    if (chan && res <= 0) {
01868       if (!chan->cdr) {
01869          chan->cdr = ast_cdr_alloc();
01870          if (chan->cdr)
01871             ast_cdr_init(chan->cdr, chan);
01872       }
01873       if (chan->cdr) {
01874          char tmp[256];
01875          snprintf(tmp, 256, "%s/%s", type, (char *)data);
01876          ast_cdr_setapp(chan->cdr,"Dial",tmp);
01877          ast_cdr_update(chan);
01878          ast_cdr_start(chan->cdr);
01879          ast_cdr_end(chan->cdr);
01880          /* If the cause wasn't handled properly */
01881          if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
01882             ast_cdr_failed(chan->cdr);
01883       } else 
01884          ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01885       ast_hangup(chan);
01886       chan = NULL;
01887    }
01888    return chan;
01889 }
01890 
01891 struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate, int callingpres, char *callerid, char *uniqueid)
01892 {
01893    return __ast_request_and_dial(type, format, data, timeout, outstate, 0, callerid, NULL, uniqueid);
01894 }
01895 
01896 struct ast_channel *ast_request(char *type, int format, void *data, char *uniqueid)
01897 {
01898    struct chanlist *chan;
01899    struct ast_channel *c = NULL;
01900    int capabilities;
01901    int fmt;
01902    int res;
01903    if (ast_mutex_lock(&chlock)) {
01904       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01905       return NULL;
01906    }
01907    chan = backends;
01908    while(chan) {
01909       if (!strcasecmp(type, chan->type)) {
01910          capabilities = chan->capabilities;
01911          fmt = format;
01912          res = ast_translator_best_choice(&fmt, &capabilities);
01913          if (res < 0) {
01914             ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
01915             ast_mutex_unlock(&chlock);
01916             return NULL;
01917          }
01918          ast_mutex_unlock(&chlock);
01919          if (chan->requester)
01920             c = chan->requester(type, capabilities, data);
01921          if (c) {
01922             if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
01923             if (c->_state == AST_STATE_DOWN) {
01924                manager_event(EVENT_FLAG_CALL, "Newchannel",
01925                "Channel: %s\r\n"
01926                "State: %s\r\n"
01927                "CallerID: %s\r\n"
01928                "Uniqueid: %s\r\n",
01929                c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid);
01930             }
01931          }
01932          return c;
01933       }
01934       chan = chan->next;
01935    }
01936    if (!chan)
01937       ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
01938    ast_mutex_unlock(&chlock);
01939    return c;
01940 }
01941 
01942 int ast_parse_device_state(char *device)
01943 {
01944    char name[AST_CHANNEL_NAME] = "";
01945    char *cut;
01946    struct ast_channel *chan;
01947 
01948    chan = ast_channel_walk_locked(NULL);
01949    while (chan) {
01950       strncpy(name, chan->name, sizeof(name)-1);
01951       ast_mutex_unlock(&chan->lock);
01952       cut = strchr(name,'-');
01953       if (cut)
01954               *cut = 0;
01955       if (!strcmp(name, device)) {
01956           if (chan->_state == AST_STATE_RINGING)
01957          return AST_DEVICE_RINGING;
01958           else          
01959               return AST_DEVICE_INUSE;
01960       }
01961       chan = ast_channel_walk_locked(chan);
01962    }
01963    return AST_DEVICE_UNKNOWN;
01964 }
01965 
01966 int ast_device_state(char *device)
01967 {
01968    char tech[AST_MAX_EXTENSION] = "";
01969    char *number;
01970    struct chanlist *chanls;
01971    int res = 0;
01972    
01973    strncpy(tech, device, sizeof(tech)-1);
01974    number = strchr(tech, '/');
01975    if (!number) {
01976        return AST_DEVICE_INVALID;
01977    }
01978    *number = 0;
01979    number++;
01980       
01981    if (ast_mutex_lock(&chlock)) {
01982       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01983       return -1;
01984    }
01985    chanls = backends;
01986    while(chanls) {
01987       if (!strcasecmp(tech, chanls->type)) {
01988          ast_mutex_unlock(&chlock);
01989          if (!chanls->devicestate) 
01990             return ast_parse_device_state(device);
01991          else {
01992             res = chanls->devicestate(number);
01993             if (res == AST_DEVICE_UNKNOWN)
01994                return ast_parse_device_state(device);
01995             else
01996                return res;
01997          }
01998       }
01999       chanls = chanls->next;
02000    }
02001    ast_mutex_unlock(&chlock);
02002    return AST_DEVICE_INVALID;
02003 }
02004 
02005 int ast_call(struct ast_channel *chan, char *addr, int timeout) 
02006 {
02007    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
02008       If the remote end does not answer within the timeout, then do NOT hang up, but 
02009       return anyway.  */
02010    int res = -1;
02011    /* Stop if we're a zombie or need a soft hangup */
02012    ast_mutex_lock(&chan->lock);
02013    if (!chan->zombie && !ast_check_hangup(chan)) 
02014       if (chan->pvt->call)
02015          res = chan->pvt->call(chan, addr, timeout);
02016    ast_mutex_unlock(&chan->lock);
02017    return res;
02018 }
02019 
02020 int ast_transfer(struct ast_channel *chan, char *dest) 
02021 {
02022    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
02023       If the remote end does not answer within the timeout, then do NOT hang up, but 
02024       return anyway.  */
02025    int res = -1;
02026    /* Stop if we're a zombie or need a soft hangup */
02027    ast_mutex_lock(&chan->lock);
02028    if (!chan->zombie && !ast_check_hangup(chan)) {
02029       if (chan->pvt->transfer) {
02030          res = chan->pvt->transfer(chan, dest);
02031          if (!res)
02032             res = 1;
02033       } else
02034          res = 0;
02035    }
02036    ast_mutex_unlock(&chan->lock);
02037    return res;
02038 }
02039 
02040 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
02041 {
02042    int pos=0;
02043    int to = ftimeout;
02044    char d;
02045    /* XXX Merge with full version? XXX */
02046    /* Stop if we're a zombie or need a soft hangup */
02047    if (c->zombie || ast_check_hangup(c)) 
02048       return -1;
02049    if (!len)
02050       return -1;
02051    do {
02052       if (c->stream) {
02053          d = ast_waitstream(c, AST_DIGIT_ANY);
02054          ast_stopstream(c);
02055          usleep(1000);
02056          if (!d)
02057             d = ast_waitfordigit(c, to);
02058       } else {
02059          d = ast_waitfordigit(c, to);
02060       }
02061       if (d < 0)
02062          return -1;
02063       if (d == 0) {
02064          s[pos]='\0';
02065          return 1;
02066       }
02067       if (!strchr(enders, d))
02068          s[pos++] = d;
02069       if (strchr(enders, d) || (pos >= len)) {
02070          s[pos]='\0';
02071          return 0;
02072       }
02073       to = timeout;
02074    } while(1);
02075    /* Never reached */
02076    return 0;
02077 }
02078 
02079 int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
02080 {
02081    int pos=0;
02082    int to = ftimeout;
02083    char d;
02084    /* Stop if we're a zombie or need a soft hangup */
02085    if (c->zombie || ast_check_hangup(c)) 
02086       return -1;
02087    if (!len)
02088       return -1;
02089    do {
02090       if (c->stream) {
02091          d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
02092          ast_stopstream(c);
02093          usleep(1000);
02094          if (!d)
02095             d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02096       } else {
02097          d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02098       }
02099       if (d < 0)
02100          return -1;
02101       if (d == 0) {
02102          s[pos]='\0';
02103          return 1;
02104       }
02105       if (d == 1) {
02106          s[pos]='\0';
02107          return 2;
02108       }
02109       if (!strchr(enders, d))
02110          s[pos++] = d;
02111       if (strchr(enders, d) || (pos >= len)) {
02112          s[pos]='\0';
02113          return 0;
02114       }
02115       to = timeout;
02116    } while(1);
02117    /* Never reached */
02118    return 0;
02119 }
02120 
02121 int ast_channel_supports_html(struct ast_channel *chan)
02122 {
02123    if (chan->pvt->send_html)
02124       return 1;
02125    return 0;
02126 }
02127 
02128 int ast_channel_sendhtml(struct ast_channel *chan, int subclass, char *data, int datalen)
02129 {
02130    if (chan->pvt->send_html)
02131       return chan->pvt->send_html(chan, subclass, data, datalen);
02132    return -1;
02133 }
02134 
02135 int ast_channel_sendurl(struct ast_channel *chan, char *url)
02136 {
02137    if (chan->pvt->send_html)
02138       return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
02139    return -1;
02140 }
02141 
02142 int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
02143 {
02144    int peerf;
02145    int chanf;
02146    int res;
02147    ast_mutex_lock(&peer->lock);
02148    peerf = peer->nativeformats;
02149    ast_mutex_unlock(&peer->lock);
02150    ast_mutex_lock(&chan->lock);
02151    chanf = chan->nativeformats;
02152    ast_mutex_unlock(&chan->lock);
02153    res = ast_translator_best_choice(&peerf, &chanf);
02154    if (res < 0) {
02155       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
02156       return -1;
02157    }
02158    /* Set read format on channel */
02159    res = ast_set_read_format(chan, peerf);
02160    if (res < 0) {
02161       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
02162       return -1;
02163    }
02164    /* Set write format on peer channel */
02165    res = ast_set_write_format(peer, peerf);
02166    if (res < 0) {
02167       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
02168       return -1;
02169    }
02170    /* Now we go the other way */
02171    peerf = peer->nativeformats;
02172    chanf = chan->nativeformats;
02173    res = ast_translator_best_choice(&chanf, &peerf);
02174    if (res < 0) {
02175       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
02176       return -1;
02177    }
02178    /* Set writeformat on channel */
02179    res = ast_set_write_format(chan, chanf);
02180    if (res < 0) {
02181       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
02182       return -1;
02183    }
02184    /* Set read format on peer channel */
02185    res = ast_set_read_format(peer, chanf);
02186    if (res < 0) {
02187       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
02188       return -1;
02189    }
02190    return 0;
02191 }
02192 
02193 int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
02194 {
02195    struct ast_frame null = { AST_FRAME_NULL, };
02196    int res = -1;
02197    ast_mutex_lock(&original->lock);
02198    while(ast_mutex_trylock(&clone->lock)) {
02199       ast_mutex_unlock(&original->lock);
02200       usleep(1);
02201       ast_mutex_lock(&original->lock);
02202    }
02203    ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
02204       clone->name, original->name);
02205    if (original->masq) {
02206       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02207          original->masq->name, original->name);
02208    } else if (clone->masqr) {
02209       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02210          clone->name, clone->masqr->name);
02211    } else {
02212       original->masq = clone;
02213       clone->masqr = original;
02214       ast_queue_frame(original, &null);
02215       ast_queue_frame(clone, &null);
02216       ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
02217       res = 0;
02218    }
02219    ast_mutex_unlock(&clone->lock);
02220    ast_mutex_unlock(&original->lock);
02221    return res;
02222 }
02223 
02224 int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone)
02225 {
02226    struct ast_frame null = { AST_FRAME_NULL, };
02227    int res = -1;
02228    ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
02229       clone->name, original->name);
02230    if (original->masq) {
02231       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02232          original->masq->name, original->name);
02233    } else if (clone->masqr) {
02234       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02235          clone->name, clone->masqr->name);
02236    } else {
02237       original->masq = clone;
02238       clone->masqr = original;
02239       ast_queue_frame(original, &null);
02240       ast_queue_frame(clone, &null);
02241       ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
02242       res = 0;
02243    }
02244    return res;
02245 }
02246 
02247 void ast_change_name(struct ast_channel *chan, char *newname)
02248 {
02249    char tmp[256];
02250    strncpy(tmp, chan->name, sizeof(tmp) - 1);
02251    strncpy(chan->name, newname, sizeof(chan->name) - 1);
02252    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid);
02253 }
02254 
02255 int ast_do_masquerade(struct ast_channel *original)
02256 {
02257    int x,i;
02258    int res=0;
02259    int origstate;
02260    char *tmp;
02261    struct ast_var_t *varptr;
02262    struct ast_frame *cur, *prev;
02263    struct ast_channel_pvt *p;
02264    struct ast_channel *clone = original->masq;
02265    int rformat = original->readformat;
02266    int wformat = original->writeformat;
02267    char newn[100];
02268    char orig[100];
02269    char masqn[100];
02270    char zombn[100];
02271 
02272 #if 1
02273    ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
02274       clone->name, clone->_state, original->name, original->_state);
02275 #endif
02276    /* XXX This is a seriously wacked out operation.  We're essentially putting the guts of
02277       the clone channel into the original channel.  Start by killing off the original
02278       channel's backend.   I'm not sure we're going to keep this function, because 
02279       while the features are nice, the cost is very high in terms of pure nastiness. XXX */
02280 
02281    /* We need the clone's lock, too */
02282    ast_mutex_lock(&clone->lock);
02283 
02284    ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock);
02285 
02286    /* Having remembered the original read/write formats, we turn off any translation on either
02287       one */
02288    free_translation(clone);
02289    free_translation(original);
02290 
02291 
02292    /* Unlink the masquerade */
02293    original->masq = NULL;
02294    clone->masqr = NULL;
02295    
02296    /* Save the original name */
02297    strncpy(orig, original->name, sizeof(orig) - 1);
02298    /* Save the new name */
02299    strncpy(newn, clone->name, sizeof(newn) - 1);
02300    /* Create the masq name */
02301    snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn);
02302       
02303    /* Copy the name from the clone channel */
02304    strncpy(original->name, newn, sizeof(original->name)-1);
02305 
02306    /* Mangle the name of the clone channel */
02307    strncpy(clone->name, masqn, sizeof(clone->name) - 1);
02308    
02309    /* Notify any managers of the change, first the masq then the other */
02310    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
02311    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
02312 
02313    /* Swap the guts */  
02314    p = original->pvt;
02315    original->pvt = clone->pvt;
02316    clone->pvt = p;
02317 
02318    /* Save any pending frames on both sides.  Start by counting
02319     * how many we're going to need... */
02320    prev = NULL;
02321    cur = clone->pvt->readq;
02322    x = 0;
02323    while(cur) {
02324       x++;
02325       prev = cur;
02326       cur = cur->next;
02327    }
02328    /* If we had any, prepend them to the ones already in the queue, and 
02329     * load up the alertpipe */
02330    if (prev) {
02331       prev->next = original->pvt->readq;
02332       original->pvt->readq = clone->pvt->readq;
02333       clone->pvt->readq = NULL;
02334       if (original->pvt->alertpipe[1] > -1) {
02335          for (i=0;i<x;i++)
02336             write(original->pvt->alertpipe[1], &x, sizeof(x));
02337       }
02338    }
02339    clone->_softhangup = AST_SOFTHANGUP_DEV;
02340 
02341 
02342    /* And of course, so does our current state.  Note we need not
02343       call ast_setstate since the event manager doesn't really consider
02344       these separate.  We do this early so that the clone has the proper
02345       state of the original channel. */
02346    origstate = original->_state;
02347    original->_state = clone->_state;
02348    clone->_state = origstate;
02349 
02350    if (clone->pvt->fixup){
02351       res = clone->pvt->fixup(original, clone);
02352       if (res) 
02353          ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
02354    }
02355 
02356    /* Start by disconnecting the original's physical side */
02357 
02358    if (clone->pvt->hangup)
02359       res = clone->pvt->hangup(clone);
02360    if (res) {
02361       ast_log(LOG_WARNING, "Hangup failed!  Strange things may happen!\n");
02362       ast_mutex_unlock(&clone->lock);
02363       return -1;
02364    }
02365    
02366    snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig);
02367    /* Mangle the name of the clone channel */
02368    strncpy(clone->name, zombn, sizeof(clone->name) - 1);
02369    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid);
02370 
02371    /* Update the type. */
02372    original->type = clone->type;
02373    
02374    /* Keep the same language.  */
02375    strncpy(original->language, clone->language, sizeof(original->language));
02376 
02377    /* Copy the FD's */
02378    for (x=0;x<AST_MAX_FDS;x++) {
02379       original->fds[x] = clone->fds[x];
02380    }
02381    /* Append variables from clone channel into original channel */
02382    /* XXX Is this always correct?  We have to in order to keep MACROS working XXX */
02383    varptr = original->varshead.first;
02384    if (varptr) {
02385       while(varptr->entries.next) {
02386          varptr = varptr->entries.next;
02387       }
02388       varptr->entries.next = clone->varshead.first;
02389    } else {
02390       original->varshead.first = clone->varshead.first;
02391    }
02392    clone->varshead.first = NULL;
02393    /* Presense of ADSI capable CPE follows clone */
02394    original->adsicpe = clone->adsicpe;
02395    /* Bridge remains the same */
02396    /* CDR fields remain the same */
02397    /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */
02398    /* Application and data remain the same */
02399    /* Clone exception  becomes real one, as with fdno */
02400    original->exception = clone->exception;
02401    original->fdno = clone->fdno;
02402    /* Schedule context remains the same */
02403    /* Stream stuff stays the same */
02404    /* Keep the original state.  The fixup code will need to work with it most likely */
02405 
02406    /* dnid and callerid change to become the new, HOWEVER, we also link the original's
02407       fields back into the defunct 'clone' so that they will be freed when
02408       ast_frfree is eventually called */
02409    tmp = original->dnid;
02410    original->dnid = clone->dnid;
02411    clone->dnid = tmp;
02412    
02413    tmp = original->callerid;
02414    original->callerid = clone->callerid;
02415    clone->callerid = tmp;
02416    
02417    /* Restore original timing file descriptor */
02418    original->fds[AST_MAX_FDS - 2] = original->timingfd;
02419    
02420    /* Our native formats are different now */
02421    original->nativeformats = clone->nativeformats;
02422    
02423    /* Context, extension, priority, app data, jump table,  remain the same */
02424    /* pvt switches.  pbx stays the same, as does next */
02425    
02426    /* Set the write format */
02427    ast_set_write_format(original, wformat);
02428 
02429    /* Set the read format */
02430    ast_set_read_format(original, rformat);
02431 
02432    /* Copy the music class */
02433    strncpy(original->musicclass, clone->musicclass, sizeof(original->musicclass) - 1);
02434 
02435    ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat);
02436 
02437    /* Okay.  Last thing is to let the channel driver know about all this mess, so he
02438       can fix up everything as best as possible */
02439    if (original->pvt->fixup) {
02440       res = original->pvt->fixup(clone, original);
02441       if (res) {
02442          ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n",
02443             original->type, original->name);
02444          ast_mutex_unlock(&clone->lock);
02445          return -1;
02446       }
02447    } else
02448       ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)!  Bad things may happen.\n",
02449          original->type, original->name);
02450    
02451    /* Now, at this point, the "clone" channel is totally F'd up.  We mark it as
02452       a zombie so nothing tries to touch it.  If it's already been marked as a
02453       zombie, then free it now (since it already is considered invalid). */
02454    if (clone->zombie) {
02455       ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name);
02456       ast_mutex_unlock(&clone->lock);
02457       ast_channel_free(clone);
02458       manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
02459    } else {
02460       struct ast_frame null_frame = { AST_FRAME_NULL, };
02461       ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name);
02462       clone->zombie=1;
02463       ast_queue_frame(clone, &null_frame);
02464       ast_mutex_unlock(&clone->lock);
02465    }
02466    
02467    /* Signal any blocker */
02468    if (original->blocking)
02469       pthread_kill(original->blocker, SIGURG);
02470    ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n",
02471       original->name, original->_state);
02472    return 0;
02473 }
02474 
02475 void ast_set_callerid(struct ast_channel *chan, char *callerid, int anitoo)
02476 {
02477    if (chan->callerid)
02478       free(chan->callerid);
02479    if (anitoo && chan->ani)
02480       free(chan->ani);
02481    if (callerid) {
02482       chan->callerid = strdup(callerid);
02483       if (anitoo)
02484          chan->ani = strdup(callerid);
02485    } else {
02486       chan->callerid = NULL;
02487       if (anitoo)
02488          chan->ani = NULL;
02489    }
02490    if (chan->cdr)
02491       ast_cdr_setcid(chan->cdr, chan);
02492    manager_event(EVENT_FLAG_CALL, "Newcallerid", 
02493             "Channel: %s\r\n"
02494             "CallerID: %s\r\n"
02495             "Uniqueid: %s\r\n",
02496             chan->name, chan->callerid ? 
02497             chan->callerid : "<Unknown>",
02498             chan->uniqueid);
02499 }
02500 
02501 int ast_setstate(struct ast_channel *chan, int state)
02502 {
02503    if (chan->_state != state) {
02504       int oldstate = chan->_state;
02505       chan->_state = state;
02506       if (oldstate == AST_STATE_DOWN) {
02507          ast_device_state_changed(chan->name);
02508          manager_event(EVENT_FLAG_CALL, "Newchannel",
02509          "Channel: %s\r\n"
02510          "State: %s\r\n"
02511          "CallerID: %s\r\n"
02512          "Uniqueid: %s\r\n",
02513          chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02514       } else {
02515          ast_device_state_changed(chan->name);
02516          manager_event(EVENT_FLAG_CALL, "Newstate", 
02517             "Channel: %s\r\n"
02518             "State: %s\r\n"
02519             "CallerID: %s\r\n"
02520             "Uniqueid: %s\r\n",
02521             chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02522       }
02523    }
02524    return 0;
02525 }
02526 
02527 static long tvdiff(struct timeval *now, struct timeval *then) 
02528 {
02529    return (((now->tv_sec * 1000) + now->tv_usec / 1000) - ((then->tv_sec * 1000) + then->tv_usec / 1000));
02530 }
02531 
02532 static void bridge_playfile(struct ast_channel *chan, struct ast_channel *peer, char *sound, int remain) 
02533 {
02534    int res=0, min=0, sec=0,check=0;
02535 
02536    check = ast_autoservice_start(peer);
02537    if(check) 
02538       return;
02539 
02540    if (remain > 0) {
02541       if (remain / 60 > 1) {
02542          min = remain / 60;
02543          sec = remain % 60;
02544       } else {
02545          sec = remain;
02546       }
02547    }
02548    
02549    if (!strcmp(sound,"timeleft")) {
02550       res = ast_streamfile(chan, "vm-youhave", chan->language);
02551       res = ast_waitstream(chan, "");
02552       if (min) {
02553          res = ast_say_number(chan, min, AST_DIGIT_ANY, chan->language, (char *) NULL);
02554          res = ast_streamfile(chan, "queue-minutes", chan->language);
02555          res = ast_waitstream(chan, "");
02556       }
02557       if (sec) {
02558          res = ast_say_number(chan, sec, AST_DIGIT_ANY, chan->language, (char *) NULL);
02559          res = ast_streamfile(chan, "queue-seconds", chan->language);
02560          res = ast_waitstream(chan, "");
02561       }
02562    } else {
02563       res = ast_streamfile(chan, sound, chan->language);
02564       res = ast_waitstream(chan, "");
02565    }
02566 
02567    check = ast_autoservice_stop(peer);
02568 }
02569 
02570 int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc) 
02571 {
02572    /* Copy voice back and forth between the two channels.   Give the peer
02573       the ability to transfer calls with '#<extension' syntax. */
02574    int flags;
02575    struct ast_channel *cs[3];
02576    int to = -1;
02577    struct ast_frame *f;
02578    struct ast_channel *who = NULL;
02579    int res=0;
02580    int nativefailed=0;
02581    int firstpass;
02582    int o0nativeformats;
02583    int o1nativeformats;
02584    struct timeval start_time,precise_now;
02585    long elapsed_ms=0, time_left_ms=0;
02586    int playit=0, playitagain=1, first_time=1;
02587 
02588    flags = (config->allowdisconnect_out||config->allowredirect_out ? AST_BRIDGE_DTMF_CHANNEL_0 : 0) + (config->allowdisconnect_in||config->allowredirect_in ? AST_BRIDGE_DTMF_CHANNEL_1 : 0);
02589 
02590    firstpass = config->firstpass;
02591    config->firstpass = 0;
02592 
02593    /* timestamp */
02594    gettimeofday(&start_time,NULL);
02595    time_left_ms = config->timelimit;
02596 
02597    if (config->play_to_caller && config->start_sound && firstpass)
02598       bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000);
02599    if (config->play_to_callee && config->start_sound && firstpass)
02600       bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000);
02601 
02602    /* Stop if we're a zombie or need a soft hangup */
02603    if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 
02604       return -1;
02605    if (c0->bridge) {
02606       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02607          c0->name, c0->bridge->name);
02608       return -1;
02609    }
02610    if (c1->bridge) {
02611       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02612          c1->name, c1->bridge->name);
02613       return -1;
02614    }
02615    
02616    /* Keep track of bridge */
02617    c0->bridge = c1;
02618    c1->bridge = c0;
02619    cs[0] = c0;
02620    cs[1] = c1;
02621    
02622    manager_event(EVENT_FLAG_CALL, "Link", 
02623          "Channel1: %s\r\n"
02624          "Channel2: %s\r\n"
02625          "Uniqueid1: %s\r\n"
02626          "Uniqueid2: %s\r\n",
02627          c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02628    o1nativeformats = c1->nativeformats;
02629    o0nativeformats = c0->nativeformats;
02630    for (/* ever */;;) {
02631       /* timestamp */
02632       if (config->timelimit) {
02633          gettimeofday(&precise_now,NULL);
02634          elapsed_ms = tvdiff(&precise_now,&start_time);
02635          time_left_ms = config->timelimit - elapsed_ms;
02636 
02637          if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) { 
02638             /* narrowing down to the end */
02639             if (config->warning_freq == 0) {
02640                playit = 1;
02641                first_time=0;
02642                playitagain=0;
02643             } else if (first_time) {
02644                playit = 1;
02645                first_time=0;
02646             } else {
02647                if ((time_left_ms % config->warning_freq) <= 50) {
02648                   playit = 1;
02649                }
02650             }
02651          }
02652          if (time_left_ms <= 0) {
02653             if (config->play_to_caller && config->end_sound)
02654                bridge_playfile(c0,c1,config->end_sound,0);
02655             if (config->play_to_callee && config->end_sound)
02656                bridge_playfile(c1,c0,config->end_sound,0);
02657             *fo = NULL;
02658             if (who) *rc = who;
02659             res = 0;
02660             break;
02661          }
02662          if (time_left_ms >= 5000 && playit) {
02663             if (config->play_to_caller && config->warning_sound && config->play_warning)
02664                bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000);
02665             if (config->play_to_callee && config->warning_sound && config->play_warning)
02666                bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000);
02667             playit = 0;
02668          }
02669          
02670       }
02671       /* Stop if we're a zombie or need a soft hangup */
02672       if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
02673          *fo = NULL;
02674          if (who) *rc = who;
02675          res = 0;
02676          ast_log(LOG_DEBUG, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",c0->name,c1->name,c0->zombie?"Yes":"No",ast_check_hangup(c0)?"Yes":"No",c1->zombie?"Yes":"No",ast_check_hangup(c1)?"Yes":"No");
02677          break;
02678       }
02679       if (c0->pvt->bridge && config->timelimit==0 &&
02680          (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
02681             /* Looks like they share a bridge code */
02682          if (option_verbose > 2) 
02683             ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
02684          if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
02685             c0->bridge = NULL;
02686             c1->bridge = NULL;
02687             manager_event(EVENT_FLAG_CALL, "Unlink", 
02688                "Channel1: %s\r\n"
02689                "Channel2: %s\r\n"
02690                "Uniqueid1: %s\r\n"
02691                "Uniqueid2: %s\r\n",
02692                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02693             ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
02694             return 0;
02695          }
02696          /* If they return non-zero then continue on normally.  Let "-2" mean don't worry about
02697             my not wanting to bridge */
02698          if ((res != -2) && (res != -3))
02699             ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
02700          if (res != -3) nativefailed++;
02701       }
02702    
02703       if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) &&
02704          !(c0->generator || c1->generator))  {
02705          if (ast_channel_make_compatible(c0, c1)) {
02706             ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
02707             manager_event(EVENT_FLAG_CALL, "Unlink", 
02708                "Channel1: %s\r\n"
02709                "Channel2: %s\r\n"
02710                "Uniqueid1: %s\r\n"
02711                "Uniqueid2: %s\r\n",
02712                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02713             return -1;
02714          }
02715          o0nativeformats = c0->nativeformats;
02716          o1nativeformats = c1->nativeformats;
02717       }
02718       who = ast_waitfor_n(cs, 2, &to);
02719       if (!who) {
02720          ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 
02721          continue;
02722       }
02723       f = ast_read(who);
02724       if (!f) {
02725          *fo = NULL;
02726          *rc = who;
02727          res = 0;
02728          ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
02729          break;
02730       }
02731 
02732       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02733          *fo = f;
02734          *rc = who;
02735          res =  0;
02736          ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
02737          break;
02738       }
02739       if ((f->frametype == AST_FRAME_VOICE) ||
02740          (f->frametype == AST_FRAME_TEXT) ||
02741          (f->frametype == AST_FRAME_VIDEO) || 
02742          (f->frametype == AST_FRAME_IMAGE) ||
02743          (f->frametype == AST_FRAME_DTMF)) {
02744          if ((f->frametype == AST_FRAME_DTMF) && 
02745             (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
02746             if ((who == c0)) {
02747                if  ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
02748                   *rc = c0;
02749                   *fo = f;
02750                   /* Take out of conference mode */
02751                   res = 0;
02752                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
02753                   break;
02754                } else 
02755                   goto tackygoto;
02756             } else
02757             if ((who == c1)) {
02758                if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
02759                   *rc = c1;
02760                   *fo = f;
02761                   res =  0;
02762                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
02763                   break;
02764                } else
02765                   goto tackygoto;
02766             }
02767          } else {
02768 #if 0
02769             ast_log(LOG_DEBUG, "Read from %s\n", who->name);
02770             if (who == last) 
02771                ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
02772             last = who;
02773 #endif
02774 tackygoto:
02775             /* Don't copy packets if there is a generator on either one, since they're
02776                not supposed to be listening anyway */
02777             if (who == c0) 
02778                ast_write(c1, f);
02779             else 
02780                ast_write(c0, f);
02781          }
02782          ast_frfree(f);
02783       } else
02784          ast_frfree(f);
02785       /* Swap who gets priority */
02786       cs[2] = cs[0];
02787       cs[0] = cs[1];
02788       cs[1] = cs[2];
02789    }
02790    c0->bridge = NULL;
02791    c1->bridge = NULL;
02792    manager_event(EVENT_FLAG_CALL, "Unlink", 
02793                "Channel1: %s\r\n"
02794                "Channel2: %s\r\n"
02795                "Uniqueid1: %s\r\n"
02796                "Uniqueid2: %s\r\n",
02797                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02798    ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name);
02799    return res;
02800 }
02801 
02802 int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int datalen, int block)
02803 {
02804    int res;
02805    if (chan->pvt->setoption) {
02806       res = chan->pvt->setoption(chan, option, data, datalen);
02807       if (res < 0)
02808          return res;
02809    } else {
02810       errno = ENOSYS;
02811       return -1;
02812    }
02813    if (block) {
02814       /* XXX Implement blocking -- just wait for our option frame reply, discarding
02815          intermediate packets. XXX */
02816       ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
02817       return -1;
02818    }
02819    return 0;
02820 }
02821 
02822 struct tonepair_def {
02823    int freq1;
02824    int freq2;
02825    int duration;
02826    int vol;
02827 };
02828 
02829 struct tonepair_state {
02830    float freq1;
02831    float freq2;
02832    float vol;
02833    int duration;
02834    int pos;
02835    int origwfmt;
02836    struct ast_frame f;
02837    unsigned char offset[AST_FRIENDLY_OFFSET];
02838    short data[4000];
02839 };
02840 
02841 static void tonepair_release(struct ast_channel *chan, void *params)
02842 {
02843    struct tonepair_state *ts = params;
02844    if (chan) {
02845       ast_set_write_format(chan, ts->origwfmt);
02846    }
02847    free(ts);
02848 }
02849 
02850 static void * tonepair_alloc(struct ast_channel *chan, void *params)
02851 {
02852    struct tonepair_state *ts;
02853    struct tonepair_def *td = params;
02854    ts = malloc(sizeof(struct tonepair_state));
02855    if (!ts)
02856       return NULL;
02857    memset(ts, 0, sizeof(struct tonepair_state));
02858    ts->origwfmt = chan->writeformat;
02859    if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
02860       ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
02861       tonepair_release(NULL, ts);
02862       ts = NULL;
02863    } else {
02864       ts->freq1 = td->freq1;
02865       ts->freq2 = td->freq2;
02866       ts->duration = td->duration;
02867       ts->vol = td->vol;
02868    }
02869    /* Let interrupts interrupt :) */
02870    chan->writeinterrupt = 1;
02871    return ts;
02872 }
02873 
02874 static int tonepair_generator(struct ast_channel *chan, void *data, int len, int samples)
02875 {
02876    struct tonepair_state *ts = data;
02877    int x;
02878 
02879    /* we need to prepare a frame with 16 * timelen samples as we're 
02880     * generating SLIN audio
02881     */
02882    len = samples * 2;
02883 
02884    if (len > sizeof(ts->data) / 2 - 1) {
02885       ast_log(LOG_WARNING, "Can't generate that much data!\n");
02886       return -1;
02887    }
02888    memset(&ts->f, 0, sizeof(ts->f));
02889    for (x=0;x<len/2;x++) {
02890       ts->data[x] = ts->vol * (
02891             sin((ts->freq1 * 2.0 * M_PI / 8000.0) * (ts->pos + x)) +
02892             sin((ts->freq2 * 2.0 * M_PI / 8000.0) * (ts->pos + x))
02893          );
02894    }
02895    ts->f.frametype = AST_FRAME_VOICE;
02896    ts->f.subclass = AST_FORMAT_SLINEAR;
02897    ts->f.datalen = len;
02898    ts->f.samples = samples;
02899    ts->f.offset = AST_FRIENDLY_OFFSET;
02900    ts->f.data = ts->data;
02901    ast_write(chan, &ts->f);
02902    ts->pos += x;
02903    if (ts->duration > 0) {
02904       if (ts->pos >= ts->duration * 8)
02905          return -1;
02906    }
02907    return 0;
02908 }
02909 
02910 static struct ast_generator tonepair = {
02911    alloc: tonepair_alloc,
02912    release: tonepair_release,
02913    generate: tonepair_generator,
02914 };
02915 
02916 int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
02917 {
02918    struct tonepair_def d = { 0, };
02919    d.freq1 = freq1;
02920    d.freq2 = freq2;
02921    d.duration = duration;
02922    if (vol < 1)
02923       d.vol = 8192;
02924    else
02925       d.vol = vol;
02926    if (ast_activate_generator(chan, &tonepair, &d))
02927       return -1;
02928    return 0;
02929 }
02930 
02931 void ast_tonepair_stop(struct ast_channel *chan)
02932 {
02933    ast_deactivate_generator(chan);
02934 }
02935 
02936 int ast_tonepair(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
02937 {
02938    struct ast_frame *f;
02939    int res;
02940    if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
02941       return res;
02942 
02943    /* Give us some wiggle room */
02944    while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
02945       f = ast_read(chan);
02946       if (f)
02947          ast_frfree(f);
02948       else
02949          return -1;
02950    }
02951    return 0;
02952 }
02953 
02954 unsigned int ast_get_group(char *s)
02955 {
02956    char *copy;
02957    char *piece;
02958    char *c=NULL;
02959    int start=0, finish=0,x;
02960    unsigned int group = 0;
02961    copy = ast_strdupa(s);
02962    if (!copy) {
02963       ast_log(LOG_ERROR, "Out of memory\n");
02964       return 0;
02965    }
02966    c = copy;
02967    
02968    while((piece = strsep(&c, ","))) {
02969       if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
02970          /* Range */
02971       } else if (sscanf(piece, "%d", &start)) {
02972          /* Just one */
02973          finish = start;
02974       } else {
02975          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.\n", s, piece);
02976          continue;
02977       }
02978       for (x=start;x<=finish;x++) {
02979          if ((x > 31) || (x < 0)) {
02980             ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x);
02981          } else
02982             group |= (1 << x);
02983       }
02984    }
02985    return group;
02986 }

Generated on Wed Mar 16 20:08:34 2005 for Asterisk by  doxygen 1.4.0