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

Generated on Thu Oct 28 11:32:53 2004 for Asterisk by doxygen1.2.15