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

channel.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <math.h>
#include <sys/poll.h>
#include <asterisk/pbx.h>
#include <asterisk/frame.h>
#include <asterisk/sched.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/logger.h>
#include <asterisk/say.h>
#include <asterisk/file.h>
#include <asterisk/translate.h>
#include <asterisk/manager.h>
#include <asterisk/chanvars.h>
#include <asterisk/linkedlists.h>
#include <asterisk/indications.h>
#include <asterisk/monitor.h>
#include <asterisk/causes.h>
#include <asterisk/utils.h>
#include <asterisk/lock.h>

Go to the source code of this file.

Data Structures

struct  chanlist
struct  tonepair_def
struct  tonepair_state

Functions

 AST_MUTEX_DEFINE_STATIC (chlock)
int ast_check_hangup (struct ast_channel *chan)
 Check to see if a channel is needing hang up.
void ast_begin_shutdown (int hangup)
int ast_active_channels (void)
void ast_cancel_shutdown (void)
int ast_shutting_down (void)
void ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset)
 Set when to hang a channel up.
int ast_channel_register (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data))
 Registers a channel.
int ast_channel_register_ex (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data), int(*devicestate)(void *data))
char * ast_state2str (int state)
 Gives the string form of a given state.
int ast_best_codec (int fmts)
 Pick the best codec.
ast_channelast_channel_alloc (int needqueue)
 Create a channel structure.
int ast_queue_frame (struct ast_channel *chan, struct ast_frame *fin)
int ast_queue_hangup (struct ast_channel *chan)
int ast_queue_control (struct ast_channel *chan, int control)
int ast_channel_defer_dtmf (struct ast_channel *chan)
 Defers DTMF.
void ast_channel_undefer_dtmf (struct ast_channel *chan)
 Undeos a defer.
ast_channelast_channel_walk_locked (struct ast_channel *prev)
 Browse channels in use.
ast_channelast_get_channel_by_name_locked (char *channame)
 Get channel by name (locks channel).
int ast_safe_sleep_conditional (struct ast_channel *chan, int ms, int(*cond)(void *), void *data)
 Wait for a specied amount of time, looking for hangups and a condition argument.
int ast_safe_sleep (struct ast_channel *chan, int ms)
 Wait for a specied amount of time, looking for hangups.
void ast_channel_free (struct ast_channel *chan)
 Free a channel structure.
int ast_softhangup_nolock (struct ast_channel *chan, int cause)
int ast_softhangup (struct ast_channel *chan, int cause)
 Softly hangup up a channel.
int ast_hangup (struct ast_channel *chan)
 Hang up a channel.
void ast_channel_unregister (char *type)
 Unregister a channel class.
int ast_answer (struct ast_channel *chan)
 Answer a ringing call.
void ast_deactivate_generator (struct ast_channel *chan)
int ast_activate_generator (struct ast_channel *chan, struct ast_generator *gen, void *params)
int ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception)
 Waits for input on an fd.
ast_channelast_waitfor_nandfds (struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
 Waits for activity on a group of channels.
ast_channelast_waitfor_n (struct ast_channel **c, int n, int *ms)
 Waits for input on a group of channels.
int ast_waitfor (struct ast_channel *c, int ms)
 Wait for input on a channel.
int ast_waitfordigit (struct ast_channel *c, int ms)
 Waits for a digit.
int ast_settimeout (struct ast_channel *c, int samples, int(*func)(void *data), void *data)
int ast_waitfordigit_full (struct ast_channel *c, int ms, int audiofd, int cmdfd)
ast_frameast_read (struct ast_channel *chan)
 Reads a frame.
int ast_indicate (struct ast_channel *chan, int condition)
 Indicates condition of channel.
int ast_recvchar (struct ast_channel *chan, int timeout)
int ast_sendtext (struct ast_channel *chan, char *text)
 Sends text to a channel.
int ast_senddigit (struct ast_channel *chan, char digit)
 Receives a text character from a channel.
int ast_prod (struct ast_channel *chan)
int ast_write_video (struct ast_channel *chan, struct ast_frame *fr)
 Write video frame to a channel.
int ast_write (struct ast_channel *chan, struct ast_frame *fr)
 Write a frame to a channel.
int ast_set_write_format (struct ast_channel *chan, int fmts)
 Sets write format on channel chan.
int ast_set_read_format (struct ast_channel *chan, int fmts)
 Sets read format on channel chan.
ast_channel__ast_request_and_dial (char *type, int format, void *data, int timeout, int *outstate, char *callerid, struct outgoing_helper *oh)
ast_channelast_request_and_dial (char *type, int format, void *data, int timeout, int *outstate, char *callerid)
ast_channelast_request (char *type, int format, void *data)
 Requests a channel.
int ast_parse_device_state (char *device)
 Search the Channels by Name.
int ast_device_state (char *device)
 Asks a channel for device state.
int ast_call (struct ast_channel *chan, char *addr, int timeout)
 Make a call.
int ast_transfer (struct ast_channel *chan, char *dest)
int ast_readstring (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
 Reads multiple digits.
int ast_readstring_full (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
int ast_channel_supports_html (struct ast_channel *chan)
 Checks for HTML support on a channel.
int ast_channel_sendhtml (struct ast_channel *chan, int subclass, char *data, int datalen)
 Sends HTML on given channel.
int ast_channel_sendurl (struct ast_channel *chan, char *url)
 Sends a URL on a given link.
int ast_channel_make_compatible (struct ast_channel *chan, struct ast_channel *peer)
 Makes two channel formats compatible.
int ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone)
 Weird function made for call transfers.
void ast_change_name (struct ast_channel *chan, char *newname)
int ast_do_masquerade (struct ast_channel *original)
void ast_set_callerid (struct ast_channel *chan, char *callerid, int anitoo)
int ast_setstate (struct ast_channel *chan, int state)
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)
 Bridge two channels together.
int ast_channel_setoption (struct ast_channel *chan, int option, void *data, int datalen, int block)
 Sets an option on a channel.
int ast_tonepair_start (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
void ast_tonepair_stop (struct ast_channel *chan)
int ast_tonepair (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
unsigned int ast_get_group (char *s)

Variables

chanlistbackends
ast_channelchannels = NULL


Function Documentation

struct ast_channel* __ast_request_and_dial char *  type,
int  format,
void *  data,
int  timeout,
int *  outstate,
char *  callerid,
struct outgoing_helper oh
 

Definition at line 1758 of file channel.c.

References ast_channel::_state, ast_call(), ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_setapp(), ast_cdr_start(), ast_cdr_update(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_frfree(), ast_hangup(), ast_log(), ast_read(), ast_request(), ast_set_callerid(), AST_STATE_UP, ast_waitfor(), ast_channel::callerid, ast_channel::cdr, ast_channel::context, ast_channel::exten, ast_frame::frametype, ast_channel::hangupcause, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar(), ast_channel::priority, and ast_frame::subclass.

Referenced by ast_pbx_outgoing_exten(), and ast_request_and_dial().

01759 {
01760    int state = 0;
01761    struct ast_channel *chan;
01762    struct ast_frame *f;
01763    int res = 0;
01764    char *variable;
01765    chan = ast_request(type, format, data);
01766    if (chan) {
01767       if (oh) {
01768          char *tmp, *var;
01769          /* JDG chanvar */
01770          if (oh->variable)
01771             variable = ast_strdupa(oh->variable);
01772          else
01773             variable = NULL;
01774          tmp = variable;
01775          /* FIXME replace this call with strsep  NOT*/
01776          while( (var = strtok_r(NULL, "|", &tmp)) ) {
01777             pbx_builtin_setvar( chan, var );
01778          } /* /JDG */
01779          if (oh->callerid && *oh->callerid)
01780             ast_set_callerid(chan, oh->callerid, 1);
01781          if (oh->account && *oh->account)
01782             ast_cdr_setaccount(chan, oh->account);
01783       }
01784       if (callerid && !ast_strlen_zero(callerid))
01785          ast_set_callerid(chan, callerid, 1);
01786 
01787       if (!ast_call(chan, data, 0)) {
01788          while(timeout && (chan->_state != AST_STATE_UP)) {
01789             res = ast_waitfor(chan, timeout);
01790             if (res < 0) {
01791                /* Something not cool, or timed out */
01792                break;
01793             }
01794             /* If done, break out */
01795             if (!res)
01796                break;
01797             if (timeout > -1)
01798                timeout = res;
01799             f = ast_read(chan);
01800             if (!f) {
01801                state = AST_CONTROL_HANGUP;
01802                res = 0;
01803                break;
01804             }
01805             if (f->frametype == AST_FRAME_CONTROL) {
01806                if (f->subclass == AST_CONTROL_RINGING)
01807                   state = AST_CONTROL_RINGING;
01808                else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01809                   state = f->subclass;
01810                   ast_frfree(f);
01811                   break;
01812                } else if (f->subclass == AST_CONTROL_ANSWER) {
01813                   state = f->subclass;
01814                   ast_frfree(f);
01815                   break;
01816                } else if (f->subclass == AST_CONTROL_PROGRESS) {
01817                   /* Ignore */
01818                } else if (f->subclass == -1) {
01819                   /* Ignore -- just stopping indications */
01820                } else {
01821                   ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
01822                }
01823             }
01824             ast_frfree(f);
01825          }
01826       } else
01827          ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01828    } else
01829       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01830    if (chan) {
01831       /* Final fixups */
01832       if (oh) {
01833          if (oh->context && *oh->context)
01834             strncpy(chan->context, oh->context, sizeof(chan->context) - 1);
01835          if (oh->exten && *oh->exten)
01836             strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1);
01837          chan->priority = oh->priority;
01838       }
01839       if (chan->_state == AST_STATE_UP) 
01840          state = AST_CONTROL_ANSWER;
01841    }
01842    if (outstate)
01843       *outstate = state;
01844    if (chan && res <= 0) {
01845       if (!chan->cdr) {
01846          chan->cdr = ast_cdr_alloc();
01847          if (chan->cdr)
01848             ast_cdr_init(chan->cdr, chan);
01849       }
01850       if (chan->cdr) {
01851          char tmp[256];
01852          snprintf(tmp, 256, "%s/%s", type, (char *)data);
01853          ast_cdr_setapp(chan->cdr,"Dial",tmp);
01854          ast_cdr_update(chan);
01855          ast_cdr_start(chan->cdr);
01856          ast_cdr_end(chan->cdr);
01857          /* If the cause wasn't handled properly */
01858          if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
01859             ast_cdr_failed(chan->cdr);
01860       } else 
01861          ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01862       ast_hangup(chan);
01863       chan = NULL;
01864    }
01865    return chan;
01866 }

int ast_activate_generator struct ast_channel chan,
struct ast_generator gen,
void *  params
 

Activate a given generator

Definition at line 849 of file channel.c.

References ast_generator::alloc, ast_mutex_lock, ast_mutex_unlock, ast_prod(), ast_settimeout(), ast_channel::generator, ast_channel::generatordata, ast_channel::lock, and ast_generator::release.

Referenced by ast_linear_stream(), ast_playtones_start(), and ast_tonepair_start().

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 }

int ast_active_channels void   ) 
 

Returns number of active/allocated channels

Definition at line 120 of file channel.c.

References ast_mutex_lock, ast_mutex_unlock, and ast_channel::next.

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 }

int ast_answer struct ast_channel chan  ) 
 

Answer a ringing call.

Parameters:
chan channel to answer This function answers a channel and handles all necessary call setup functions. Returns 0 on success, -1 on failure

Definition at line 785 of file channel.c.

References ast_channel::_state, ast_channel_pvt::answer, ast_cdr_answer(), ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_channel::cdr, ast_channel::lock, ast_channel::pvt, and ast_channel::zombie.

Referenced by ast_control_streamfile().

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 }

void ast_begin_shutdown int  hangup  ) 
 

Initiate system shutdown -- prevents new channels from being allocated. If "hangup" is non-zero, all existing channels will receive soft hangups

Definition at line 105 of file channel.c.

References ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), AST_SOFTHANGUP_SHUTDOWN, and ast_channel::next.

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 }

int ast_best_codec int  fmts  ) 
 

Pick the best codec.

Definition at line 233 of file channel.c.

References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_ILBC, AST_FORMAT_LPC10, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, ast_log(), and LOG_WARNING.

Referenced by ast_codec_choose().

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 }

int ast_call struct ast_channel chan,
char *  addr,
int  timeout
 

Make a call.

Parameters:
chan which channel to make the call on
addr destination of the call
timeout time to wait on for connect Place a call, take no longer than timeout ms. Returns -1 on failure, 0 on not enough time (does not auto matically stop ringing), and the number of seconds the connect took otherwise. Returns 0 on success, -1 on failure

Definition at line 1977 of file channel.c.

References ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_channel_pvt::call, ast_channel::lock, ast_channel::pvt, and ast_channel::zombie.

Referenced by __ast_request_and_dial().

01978 {
01979    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
01980       If the remote end does not answer within the timeout, then do NOT hang up, but 
01981       return anyway.  */
01982    int res = -1;
01983    /* Stop if we're a zombie or need a soft hangup */
01984    ast_mutex_lock(&chan->lock);
01985    if (!chan->zombie && !ast_check_hangup(chan)) 
01986       if (chan->pvt->call)
01987          res = chan->pvt->call(chan, addr, timeout);
01988    ast_mutex_unlock(&chan->lock);
01989    return res;
01990 }

void ast_cancel_shutdown void   ) 
 

Cancels an existing shutdown and returns to normal operation

Definition at line 134 of file channel.c.

00135 {
00136    shutting_down = 0;
00137 }

void ast_change_name struct ast_channel chan,
char *  newname
 

Definition at line 2196 of file channel.c.

References EVENT_FLAG_CALL, manager_event(), ast_channel::name, and ast_channel::uniqueid.

02197 {
02198    char tmp[256];
02199    strncpy(tmp, chan->name, sizeof(tmp) - 1);
02200    strncpy(chan->name, newname, sizeof(chan->name) - 1);
02201    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid);
02202 }

struct ast_channel* ast_channel_alloc int  needalertpipe  ) 
 

Create a channel structure.

Returns NULL on failure to allocate

Definition at line 274 of file channel.c.

References ast_default_accountcode, ast_default_amaflags, AST_LIST_HEAD_INIT, AST_LIST_INSERT_HEAD, ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, AST_STATE_DOWN, ast_var_assign(), defaultlanguage, free, LOG_WARNING, malloc, ast_channel_pvt::pvt, and sched_context_create().

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

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 }

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
 

Bridge two channels together.

Parameters:
c0 first channel to bridge
c1 second channel to bridge
flags for the channels
fo destination frame(?)
rc destination channel(?) Bridge two channels (c0 and c1) together. If an important frame occurs, we return that frame in rf (remember, it could be NULL) and which channel (0 or 1) in rc

Definition at line 2517 of file channel.c.

References ast_bridge_config::allowdisconnect_in, ast_bridge_config::allowdisconnect_out, ast_bridge_config::allowredirect_in, ast_bridge_config::allowredirect_out, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, ast_channel_make_compatible(), ast_check_hangup(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_verbose(), ast_waitfor_n(), ast_write(), ast_channel::bridge, ast_bridge_config::end_sound, EVENT_FLAG_CALL, ast_bridge_config::firstpass, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::name, option_verbose, ast_bridge_config::play_to_callee, ast_bridge_config::play_to_caller, ast_bridge_config::play_warning, ast_bridge_config::start_sound, ast_frame::subclass, ast_bridge_config::timelimit, VERBOSE_PREFIX_3, ast_bridge_config::warning_freq, and ast_bridge_config::warning_sound.

02518 {
02519    /* Copy voice back and forth between the two channels.   Give the peer
02520       the ability to transfer calls with '#<extension' syntax. */
02521    int flags;
02522    struct ast_channel *cs[3];
02523    int to = -1;
02524    struct ast_frame *f;
02525    struct ast_channel *who = NULL;
02526    int res=0;
02527    int nativefailed=0;
02528    int firstpass;
02529    int o0nativeformats;
02530    int o1nativeformats;
02531    struct timeval start_time,precise_now;
02532    long elapsed_ms=0, time_left_ms=0;
02533    int playit=0, playitagain=1, first_time=1;
02534 
02535    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);
02536 
02537    firstpass = config->firstpass;
02538    config->firstpass = 0;
02539 
02540    /* timestamp */
02541    gettimeofday(&start_time,NULL);
02542    time_left_ms = config->timelimit;
02543 
02544    if (config->play_to_caller && config->start_sound && firstpass)
02545       bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000);
02546    if (config->play_to_callee && config->start_sound && firstpass)
02547       bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000);
02548 
02549    /* Stop if we're a zombie or need a soft hangup */
02550    if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 
02551       return -1;
02552    if (c0->bridge) {
02553       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02554          c0->name, c0->bridge->name);
02555       return -1;
02556    }
02557    if (c1->bridge) {
02558       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02559          c1->name, c1->bridge->name);
02560       return -1;
02561    }
02562    
02563    /* Keep track of bridge */
02564    c0->bridge = c1;
02565    c1->bridge = c0;
02566    cs[0] = c0;
02567    cs[1] = c1;
02568    
02569    manager_event(EVENT_FLAG_CALL, "Link", 
02570          "Channel1: %s\r\n"
02571          "Channel2: %s\r\n"
02572          "Uniqueid1: %s\r\n"
02573          "Uniqueid2: %s\r\n",
02574          c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02575    o1nativeformats = c1->nativeformats;
02576    o0nativeformats = c0->nativeformats;
02577    for (/* ever */;;) {
02578       /* timestamp */
02579       if (config->timelimit) {
02580          gettimeofday(&precise_now,NULL);
02581          elapsed_ms = tvdiff(&precise_now,&start_time);
02582          time_left_ms = config->timelimit - elapsed_ms;
02583 
02584          if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) { 
02585             /* narrowing down to the end */
02586             if (config->warning_freq == 0) {
02587                playit = 1;
02588                first_time=0;
02589                playitagain=0;
02590             } else if (first_time) {
02591                playit = 1;
02592                first_time=0;
02593             } else {
02594                if ((time_left_ms % config->warning_freq) <= 50) {
02595                   playit = 1;
02596                }
02597             }
02598          }
02599          if (time_left_ms <= 0) {
02600             if (config->play_to_caller && config->end_sound)
02601                bridge_playfile(c0,c1,config->end_sound,0);
02602             if (config->play_to_callee && config->end_sound)
02603                bridge_playfile(c1,c0,config->end_sound,0);
02604             *fo = NULL;
02605             if (who) *rc = who;
02606             res = 0;
02607             break;
02608          }
02609          if (time_left_ms >= 5000 && playit) {
02610             if (config->play_to_caller && config->warning_sound && config->play_warning)
02611                bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000);
02612             if (config->play_to_callee && config->warning_sound && config->play_warning)
02613                bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000);
02614             playit = 0;
02615          }
02616          
02617       }
02618       /* Stop if we're a zombie or need a soft hangup */
02619       if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
02620          *fo = NULL;
02621          if (who) *rc = who;
02622          res = 0;
02623          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");
02624          break;
02625       }
02626       if (c0->pvt->bridge && config->timelimit==0 &&
02627          (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
02628             /* Looks like they share a bridge code */
02629          if (option_verbose > 2) 
02630             ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
02631          if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
02632             c0->bridge = NULL;
02633             c1->bridge = NULL;
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             ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
02641             return 0;
02642          }
02643          /* If they return non-zero then continue on normally.  Let "-2" mean don't worry about
02644             my not wanting to bridge */
02645          if ((res != -2) && (res != -3))
02646             ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
02647          if (res != -3) nativefailed++;
02648       }
02649    
02650       if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) &&
02651          !(c0->generator || c1->generator))  {
02652          if (ast_channel_make_compatible(c0, c1)) {
02653             ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
02654             manager_event(EVENT_FLAG_CALL, "Unlink", 
02655                "Channel1: %s\r\n"
02656                "Channel2: %s\r\n"
02657                "Uniqueid1: %s\r\n"
02658                "Uniqueid2: %s\r\n",
02659                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02660             return -1;
02661          }
02662          o0nativeformats = c0->nativeformats;
02663          o1nativeformats = c1->nativeformats;
02664       }
02665       who = ast_waitfor_n(cs, 2, &to);
02666       if (!who) {
02667          ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 
02668          continue;
02669       }
02670       f = ast_read(who);
02671       if (!f) {
02672          *fo = NULL;
02673          *rc = who;
02674          res = 0;
02675          ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
02676          break;
02677       }
02678 
02679       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02680          *fo = f;
02681          *rc = who;
02682          res =  0;
02683          ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
02684          break;
02685       }
02686       if ((f->frametype == AST_FRAME_VOICE) ||
02687          (f->frametype == AST_FRAME_TEXT) ||
02688          (f->frametype == AST_FRAME_VIDEO) || 
02689          (f->frametype == AST_FRAME_IMAGE) ||
02690          (f->frametype == AST_FRAME_HTML) ||
02691          (f->frametype == AST_FRAME_DTMF)) {
02692          if ((f->frametype == AST_FRAME_DTMF) && 
02693             (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
02694             if ((who == c0)) {
02695                if  ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
02696                   *rc = c0;
02697                   *fo = f;
02698                   /* Take out of conference mode */
02699                   res = 0;
02700                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
02701                   break;
02702                } else 
02703                   goto tackygoto;
02704             } else
02705             if ((who == c1)) {
02706                if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
02707                   *rc = c1;
02708                   *fo = f;
02709                   res =  0;
02710                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
02711                   break;
02712                } else
02713                   goto tackygoto;
02714             }
02715          } else {
02716 #if 0
02717             ast_log(LOG_DEBUG, "Read from %s\n", who->name);
02718             if (who == last) 
02719                ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
02720             last = who;
02721 #endif
02722 tackygoto:
02723             /* Don't copy packets if there is a generator on either one, since they're
02724                not supposed to be listening anyway */
02725             if (who == c0) 
02726                ast_write(c1, f);
02727             else 
02728                ast_write(c0, f);
02729          }
02730          ast_frfree(f);
02731       } else
02732          ast_frfree(f);
02733       /* Swap who gets priority */
02734       cs[2] = cs[0];
02735       cs[0] = cs[1];
02736       cs[1] = cs[2];
02737    }
02738    c0->bridge = NULL;
02739    c1->bridge = NULL;
02740    manager_event(EVENT_FLAG_CALL, "Unlink", 
02741                "Channel1: %s\r\n"
02742                "Channel2: %s\r\n"
02743                "Uniqueid1: %s\r\n"
02744                "Uniqueid2: %s\r\n",
02745                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02746    ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name);
02747    return res;
02748 }

int ast_channel_defer_dtmf struct ast_channel chan  ) 
 

Defers DTMF.

Defer DTMF so that you only read things like hangups and audio. Returns non-zero if channel was already DTMF-deferred or 0 if channel is just now being DTMF-deferred

Definition at line 441 of file channel.c.

References ast_channel::deferdtmf.

00442 {
00443    int pre = 0;
00444    if (chan) {
00445       pre = chan->deferdtmf;
00446       chan->deferdtmf = 1;
00447    }
00448    return pre;
00449 }

void ast_channel_free struct ast_channel chan  ) 
 

Free a channel structure.

Definition at line 561 of file channel.c.

References ast_channel_pvt::alertpipe, ast_channel::ani, AST_CHANNEL_NAME, ast_device_state_changed(), ast_frfree(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_REMOVE_HEAD, ast_log(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_translator_free_path(), ast_var_delete(), ast_channel::callerid, ast_channel::dnid, free, ast_channel::lock, LOG_WARNING, ast_channel::monitor, ast_channel::name, ast_channel::next, ast_frame::next, ast_channel::pbx, ast_channel::pvt, ast_channel_pvt::pvt, ast_channel::rdnis, ast_channel_pvt::readq, ast_channel_pvt::readtrans, ast_channel_monitor::stop, ast_channel::timingfd, and ast_channel_pvt::writetrans.

Referenced by ast_do_masquerade(), and ast_hangup().

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 }

int ast_channel_make_compatible struct ast_channel c0,
struct ast_channel c1
 

Makes two channel formats compatible.

Parameters:
c0 first channel to make compatible
c1 other channel to make compatible Set two channels to compatible formats -- call before ast_channel_bridge in general . Returns 0 on success and -1 if it could not be done

Definition at line 2114 of file channel.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_set_read_format(), ast_set_write_format(), ast_translator_best_choice(), ast_channel::lock, LOG_WARNING, ast_channel::name, and ast_channel::nativeformats.

Referenced by ast_channel_bridge().

02115 {
02116    int peerf;
02117    int chanf;
02118    int res;
02119    ast_mutex_lock(&peer->lock);
02120    peerf = peer->nativeformats;
02121    ast_mutex_unlock(&peer->lock);
02122    ast_mutex_lock(&chan->lock);
02123    chanf = chan->nativeformats;
02124    ast_mutex_unlock(&chan->lock);
02125    res = ast_translator_best_choice(&peerf, &chanf);
02126    if (res < 0) {
02127       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
02128       return -1;
02129    }
02130    /* Set read format on channel */
02131    res = ast_set_read_format(chan, peerf);
02132    if (res < 0) {
02133       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
02134       return -1;
02135    }
02136    /* Set write format on peer channel */
02137    res = ast_set_write_format(peer, peerf);
02138    if (res < 0) {
02139       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
02140       return -1;
02141    }
02142    /* Now we go the other way */
02143    peerf = peer->nativeformats;
02144    chanf = chan->nativeformats;
02145    res = ast_translator_best_choice(&chanf, &peerf);
02146    if (res < 0) {
02147       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
02148       return -1;
02149    }
02150    /* Set writeformat on channel */
02151    res = ast_set_write_format(chan, chanf);
02152    if (res < 0) {
02153       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
02154       return -1;
02155    }
02156    /* Set read format on peer channel */
02157    res = ast_set_read_format(peer, chanf);
02158    if (res < 0) {
02159       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
02160       return -1;
02161    }
02162    return 0;
02163 }

int ast_channel_masquerade struct ast_channel original,
struct ast_channel clone
 

Weird function made for call transfers.

Parameters:
original channel to make a copy of
clone copy of the original channel This is a very strange and freaky function used primarily for transfer. Suppose that "original" and "clone" are two channels in random situations. This function takes the guts out of "clone" and puts them into the "original" channel, then alerts the channel driver of the change, asking it to fixup any private information (like the p->owner pointer) that is affected by the change. The physical layer of the original channel is hung up.

Definition at line 2165 of file channel.c.

References AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_queue_frame(), ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, and ast_channel::name.

Referenced by ast_async_goto().

02166 {
02167    struct ast_frame null = { AST_FRAME_NULL, };
02168    int res = -1;
02169    ast_mutex_lock(&original->lock);
02170    while(ast_mutex_trylock(&clone->lock)) {
02171       ast_mutex_unlock(&original->lock);
02172       usleep(1);
02173       ast_mutex_lock(&original->lock);
02174    }
02175    ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
02176       clone->name, original->name);
02177    if (original->masq) {
02178       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02179          original->masq->name, original->name);
02180    } else if (clone->masqr) {
02181       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02182          clone->name, clone->masqr->name);
02183    } else {
02184       original->masq = clone;
02185       clone->masqr = original;
02186       ast_queue_frame(original, &null);
02187       ast_queue_frame(clone, &null);
02188       ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
02189       res = 0;
02190    }
02191    ast_mutex_unlock(&clone->lock);
02192    ast_mutex_unlock(&original->lock);
02193    return res;
02194 }

int ast_channel_register char *  type,
char *  description,
int  capabilities,
struct ast_channel *(*)(char *type, int format, void *data)  requester
 

Registers a channel.

Parameters:
type type of channel you are registering
description short description of the channel
capabilities a bit mask of the capabilities of the channel
requester a function pointer that properly responds to a call. See one of the channel drivers for details. Called by a channel module to register the kind of channels it supports. It supplies a brief type, a longer, but still short description, and a routine that creates a channel Returns 0 on success, -1 on failure.

Definition at line 156 of file channel.c.

References ast_channel_register_ex().

00158 {
00159    return ast_channel_register_ex(type, description, capabilities, requester, NULL);
00160 }

int ast_channel_register_ex char *  type,
char *  description,
int  capabilities,
struct ast_channel *(*)(char *type, int format, void *data)  requester,
int(*)(void *data)  devicestate
 

Definition at line 162 of file channel.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), backends, chanlist::capabilities, chanlist::description, chanlist::devicestate, LOG_DEBUG, LOG_WARNING, malloc, chanlist::next, option_debug, option_verbose, chanlist::requester, chanlist::type, and VERBOSE_PREFIX_2.

Referenced by ast_channel_register().

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 }

int ast_channel_sendhtml struct ast_channel channel,
int  subclass,
char *  data,
int  datalen
 

Sends HTML on given channel.

Send HTML or URL on link. Returns 0 on success or -1 on failure

Definition at line 2100 of file channel.c.

References ast_channel::pvt, and ast_channel_pvt::send_html.

02101 {
02102    if (chan->pvt->send_html)
02103       return chan->pvt->send_html(chan, subclass, data, datalen);
02104    return -1;
02105 }

int ast_channel_sendurl struct ast_channel channel,
char *  url
 

Sends a URL on a given link.

Send URL on link. Returns 0 on success or -1 on failure

Definition at line 2107 of file channel.c.

References AST_HTML_URL, ast_channel::pvt, and ast_channel_pvt::send_html.

02108 {
02109    if (chan->pvt->send_html)
02110       return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
02111    return -1;
02112 }

int ast_channel_setoption struct ast_channel channel,
int  option,
void *  data,
int  datalen,
int  block
 

Sets an option on a channel.

Parameters:
channel channel to set options on
option option to change
data data specific to option
datalen length of the data
block blocking or not Set an option on a channel (see frame.h), optionally blocking awaiting the reply Returns 0 on success and -1 on failure

Definition at line 2750 of file channel.c.

References ast_log(), LOG_ERROR, ast_channel::pvt, and ast_channel_pvt::setoption.

02751 {
02752    int res;
02753    if (chan->pvt->setoption) {
02754       res = chan->pvt->setoption(chan, option, data, datalen);
02755       if (res < 0)
02756          return res;
02757    } else {
02758       errno = ENOSYS;
02759       return -1;
02760    }
02761    if (block) {
02762       /* XXX Implement blocking -- just wait for our option frame reply, discarding
02763          intermediate packets. XXX */
02764       ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
02765       return -1;
02766    }
02767    return 0;
02768 }

void ast_channel_setwhentohangup struct ast_channel chan,
time_t  offset
 

Set when to hang a channel up.

Parameters:
chan channel on which to check for hang up
offset offset in seconds from current time of when to hang up This function sets the absolute time out on a channel (when to hang up).

Definition at line 144 of file channel.c.

References ast_channel::whentohangup.

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 }

int ast_channel_supports_html struct ast_channel channel  ) 
 

Checks for HTML support on a channel.

Returns 0 if channel does not support HTML or non-zero if it does

Definition at line 2093 of file channel.c.

References ast_channel::pvt, and ast_channel_pvt::send_html.

02094 {
02095    if (chan->pvt->send_html)
02096       return 1;
02097    return 0;
02098 }

void ast_channel_undefer_dtmf struct ast_channel chan  ) 
 

Undeos a defer.

Undo defer. ast_read will return any dtmf characters that were queued

Definition at line 451 of file channel.c.

References ast_channel::deferdtmf.

00452 {
00453    if (chan)
00454       chan->deferdtmf = 0;
00455 }

void ast_channel_unregister char *  type  ) 
 

Unregister a channel class.

Definition at line 756 of file channel.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), backends, free, LOG_DEBUG, LOG_WARNING, chanlist::next, option_debug, option_verbose, chanlist::type, and VERBOSE_PREFIX_2.

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 }

struct ast_channel* ast_channel_walk_locked struct ast_channel prev  ) 
 

Browse channels in use.

Parameters:
prev where you want to start in the channel list Browse the channels currently in use Returns the next channel in the list, NULL on end. If it returns a channel, that channel *has been locked*!

Definition at line 457 of file channel.c.

References ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, and ast_channel::next.

Referenced by ast_async_goto_by_name(), ast_get_channel_by_name_locked(), and ast_parse_device_state().

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 }

int ast_check_hangup struct ast_channel chan  ) 
 

Check to see if a channel is needing hang up.

Parameters:
chan channel on which to check for hang up This function determines if the channel is being requested to be hung up. Returns 0 if not, or 1 if hang up is requested (including time-out).

Definition at line 79 of file channel.c.

References ast_channel::_softhangup, AST_SOFTHANGUP_TIMEOUT, ast_channel::pvt, ast_channel_pvt::pvt, and ast_channel::whentohangup.

Referenced by ast_answer(), ast_call(), ast_channel_bridge(), ast_indicate(), ast_read(), ast_readstring(), ast_readstring_full(), ast_recvchar(), ast_rtp_bridge(), ast_sendtext(), ast_transfer(), ast_waitfordigit(), ast_waitfordigit_full(), and ast_write().

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 }

void ast_deactivate_generator struct ast_channel chan  ) 
 

Deactive an active generator

Definition at line 816 of file channel.c.

References ast_mutex_lock, ast_mutex_unlock, ast_settimeout(), ast_channel::generator, ast_channel::generatordata, ast_channel::lock, ast_generator::release, and ast_channel::writeinterrupt.

Referenced by ast_openstream(), ast_playtones_stop(), ast_read(), ast_tonepair_stop(), and ast_write().

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 }

int ast_device_state char *  device  ) 
 

Asks a channel for device state.

Parameters:
device like a dialstring Asks a channel for device state, data is normaly a number from dialstring used by the low level module Trys the channel devicestate callback if not supported search in the active channels list for the device. Returns an AST_DEVICE_??? state -1 on failure

Definition at line 1938 of file channel.c.

References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_log(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parse_device_state(), backends, chanlist::devicestate, LOG_WARNING, chanlist::next, and chanlist::type.

01939 {
01940    char tech[AST_MAX_EXTENSION] = "";
01941    char *number;
01942    struct chanlist *chanls;
01943    int res = 0;
01944    
01945    strncpy(tech, device, sizeof(tech)-1);
01946    number = strchr(tech, '/');
01947    if (!number) {
01948        return AST_DEVICE_INVALID;
01949    }
01950    *number = 0;
01951    number++;
01952       
01953    if (ast_mutex_lock(&chlock)) {
01954       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01955       return -1;
01956    }
01957    chanls = backends;
01958    while(chanls) {
01959       if (!strcasecmp(tech, chanls->type)) {
01960          ast_mutex_unlock(&chlock);
01961          if (!chanls->devicestate) 
01962             return ast_parse_device_state(device);
01963          else {
01964             res = chanls->devicestate(number);
01965             if (res == AST_DEVICE_UNKNOWN)
01966                return ast_parse_device_state(device);
01967             else
01968                return res;
01969          }
01970       }
01971       chanls = chanls->next;
01972    }
01973    ast_mutex_unlock(&chlock);
01974    return AST_DEVICE_INVALID;
01975 }

int ast_do_masquerade struct ast_channel original  ) 
 

Definition at line 2204 of file channel.c.

References ast_channel::_softhangup, ast_channel::_state, ast_channel::adsicpe, ast_channel_pvt::alertpipe, ast_channel_free(), AST_FRAME_NULL, ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_queue_frame(), ast_set_read_format(), ast_set_write_format(), AST_SOFTHANGUP_DEV, ast_channel::blocker, ast_channel::blocking, ast_channel::callerid, ast_channel::dnid, EVENT_FLAG_CALL, ast_channel::exception, ast_channel::fdno, ast_channel::fds, ast_channel_pvt::fixup, ast_channel_pvt::hangup, ast_channel::language, ast_channel::lock, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::masq, ast_channel::masqr, ast_channel::musicclass, ast_channel::name, ast_channel::nativeformats, ast_frame::next, ast_frame::prev, ast_channel::pvt, ast_channel::readformat, ast_channel_pvt::readq, ast_channel::timingfd, ast_channel::type, ast_channel::uniqueid, ast_channel::writeformat, and ast_channel::zombie.

Referenced by ast_async_goto(), ast_hangup(), ast_read(), ast_waitfor_nandfds(), and ast_write().

02205 {
02206    int x,i;
02207    int res=0;
02208    int origstate;
02209    char *tmp;
02210    struct ast_var_t *varptr;
02211    struct ast_frame *cur, *prev;
02212    struct ast_channel_pvt *p;
02213    struct ast_channel *clone = original->masq;
02214    int rformat = original->readformat;
02215    int wformat = original->writeformat;
02216    char newn[100];
02217    char orig[100];
02218    char masqn[100];
02219    char zombn[100];
02220 
02221 #if 1
02222    ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
02223       clone->name, clone->_state, original->name, original->_state);
02224 #endif
02225    /* XXX This is a seriously wacked out operation.  We're essentially putting the guts of
02226       the clone channel into the original channel.  Start by killing off the original
02227       channel's backend.   I'm not sure we're going to keep this function, because 
02228       while the features are nice, the cost is very high in terms of pure nastiness. XXX */
02229 
02230    /* We need the clone's lock, too */
02231    ast_mutex_lock(&clone->lock);
02232 
02233    ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock);
02234 
02235    /* Having remembered the original read/write formats, we turn off any translation on either
02236       one */
02237    free_translation(clone);
02238    free_translation(original);
02239 
02240 
02241    /* Unlink the masquerade */
02242    original->masq = NULL;
02243    clone->masqr = NULL;
02244    
02245    /* Save the original name */
02246    strncpy(orig, original->name, sizeof(orig) - 1);
02247    /* Save the new name */
02248    strncpy(newn, clone->name, sizeof(newn) - 1);
02249    /* Create the masq name */
02250    snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn);
02251       
02252    /* Copy the name from the clone channel */
02253    strncpy(original->name, newn, sizeof(original->name)-1);
02254 
02255    /* Mangle the name of the clone channel */
02256    strncpy(clone->name, masqn, sizeof(clone->name) - 1);
02257    
02258    /* Notify any managers of the change, first the masq then the other */
02259    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
02260    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
02261 
02262    /* Swap the guts */  
02263    p = original->pvt;
02264    original->pvt = clone->pvt;
02265    clone->pvt = p;
02266 
02267    /* Save any pending frames on both sides.  Start by counting
02268     * how many we're going to need... */
02269    prev = NULL;
02270    cur = clone->pvt->readq;
02271    x = 0;
02272    while(cur) {
02273       x++;
02274       prev = cur;
02275       cur = cur->next;
02276    }
02277    /* If we had any, prepend them to the ones already in the queue, and 
02278     * load up the alertpipe */
02279    if (prev) {
02280       prev->next = original->pvt->readq;
02281       original->pvt->readq = clone->pvt->readq;
02282       clone->pvt->readq = NULL;
02283       if (original->pvt->alertpipe[1] > -1) {
02284          for (i=0;i<x;i++)
02285             write(original->pvt->alertpipe[1], &x, sizeof(x));
02286       }
02287    }
02288    clone->_softhangup = AST_SOFTHANGUP_DEV;
02289 
02290 
02291    /* And of course, so does our current state.  Note we need not
02292       call ast_setstate since the event manager doesn't really consider
02293       these separate.  We do this early so that the clone has the proper
02294       state of the original channel. */
02295    origstate = original->_state;
02296    original->_state = clone->_state;
02297    clone->_state = origstate;
02298 
02299    if (clone->pvt->fixup){
02300       res = clone->pvt->fixup(original, clone);
02301       if (res) 
02302          ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
02303    }
02304 
02305    /* Start by disconnecting the original's physical side */
02306    if (clone->pvt->hangup)
02307       res = clone->pvt->hangup(clone);
02308    if (res) {
02309       ast_log(LOG_WARNING, "Hangup failed!  Strange things may happen!\n");
02310       ast_mutex_unlock(&clone->lock);
02311       return -1;
02312    }
02313    
02314    snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig);
02315    /* Mangle the name of the clone channel */
02316    strncpy(clone->name, zombn, sizeof(clone->name) - 1);
02317    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid);
02318 
02319    /* Update the type. */
02320    original->type = clone->type;
02321    
02322    /* Keep the same language.  */
02323    strncpy(original->language, clone->language, sizeof(original->language));
02324 
02325    /* Copy the FD's */
02326    for (x=0;x<AST_MAX_FDS;x++) {
02327       original->fds[x] = clone->fds[x];
02328    }
02329    /* Append variables from clone channel into original channel */
02330    /* XXX Is this always correct?  We have to in order to keep MACROS working XXX */
02331    varptr = original->varshead.first;
02332    if (varptr) {
02333       while(varptr->entries.next) {
02334          varptr = varptr->entries.next;
02335       }
02336       varptr->entries.next = clone->varshead.first;
02337    } else {
02338       original->varshead.first = clone->varshead.first;
02339    }
02340    clone->varshead.first = NULL;
02341    /* Presense of ADSI capable CPE follows clone */
02342    original->adsicpe = clone->adsicpe;
02343    /* Bridge remains the same */
02344    /* CDR fields remain the same */
02345    /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */
02346    /* Application and data remain the same */
02347    /* Clone exception  becomes real one, as with fdno */
02348    original->exception = clone->exception;
02349    original->fdno = clone->fdno;
02350    /* Schedule context remains the same */
02351    /* Stream stuff stays the same */
02352    /* Keep the original state.  The fixup code will need to work with it most likely */
02353 
02354    /* dnid and callerid change to become the new, HOWEVER, we also link the original's
02355       fields back into the defunct 'clone' so that they will be freed when
02356       ast_frfree is eventually called */
02357    tmp = original->dnid;
02358    original->dnid = clone->dnid;
02359    clone->dnid = tmp;
02360    
02361    tmp = original->callerid;
02362    original->callerid = clone->callerid;
02363    clone->callerid = tmp;
02364    
02365    /* Restore original timing file descriptor */
02366    original->fds[AST_MAX_FDS - 2] = original->timingfd;
02367    
02368    /* Our native formats are different now */
02369    original->nativeformats = clone->nativeformats;
02370    
02371    /* Context, extension, priority, app data, jump table,  remain the same */
02372    /* pvt switches.  pbx stays the same, as does next */
02373    
02374    /* Set the write format */
02375    ast_set_write_format(original, wformat);
02376 
02377    /* Set the read format */
02378    ast_set_read_format(original, rformat);
02379 
02380    /* Copy the music class */
02381    strncpy(original->musicclass, clone->musicclass, sizeof(original->musicclass) - 1);
02382 
02383    ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat);
02384 
02385    /* Okay.  Last thing is to let the channel driver know about all this mess, so he
02386       can fix up everything as best as possible */
02387    if (original->pvt->fixup) {
02388       res = original->pvt->fixup(clone, original);
02389       if (res) {
02390          ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n",
02391             original->type, original->name);
02392          ast_mutex_unlock(&clone->lock);
02393          return -1;
02394       }
02395    } else
02396       ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)!  Bad things may happen.\n",
02397          original->type, original->name);
02398    
02399    /* Now, at this point, the "clone" channel is totally F'd up.  We mark it as
02400       a zombie so nothing tries to touch it.  If it's already been marked as a
02401       zombie, then free it now (since it already is considered invalid). */
02402    if (clone->zombie) {
02403       ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name);
02404       ast_mutex_unlock(&clone->lock);
02405       ast_channel_free(clone);
02406       manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
02407    } else {
02408       struct ast_frame null_frame = { AST_FRAME_NULL, };
02409       ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name);
02410       clone->zombie=1;
02411       ast_queue_frame(clone, &null_frame);
02412       ast_mutex_unlock(&clone->lock);
02413    }
02414    
02415    /* Signal any blocker */
02416    if (original->blocking)
02417       pthread_kill(original->blocker, SIGURG);
02418    ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n",
02419       original->name, original->_state);
02420    return 0;
02421 }

struct ast_channel* ast_get_channel_by_name_locked char *  channame  ) 
 

Get channel by name (locks channel).

Definition at line 510 of file channel.c.

References ast_channel_walk_locked(), ast_mutex_unlock, ast_channel::lock, and ast_channel::name.

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 }

unsigned int ast_get_group char *  s  ) 
 

Definition at line 2902 of file channel.c.

References ast_log(), LOG_ERROR, and LOG_WARNING.

02903 {
02904    char *copy;
02905    char *piece;
02906    char *c=NULL;
02907    int start=0, finish=0,x;
02908    unsigned int group = 0;
02909    copy = ast_strdupa(s);
02910    if (!copy) {
02911       ast_log(LOG_ERROR, "Out of memory\n");
02912       return 0;
02913    }
02914    c = copy;
02915    
02916    while((piece = strsep(&c, ","))) {
02917       if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
02918          /* Range */
02919       } else if (sscanf(piece, "%d", &start)) {
02920          /* Just one */
02921          finish = start;
02922       } else {
02923          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.\n", s, piece);
02924          continue;
02925       }
02926       for (x=start;x<=finish;x++) {
02927          if ((x > 31) || (x < 0)) {
02928             ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x);
02929          } else
02930             group |= (1 << x);
02931       }
02932    }
02933    return group;
02934 }

int ast_hangup struct ast_channel chan  ) 
 

Hang up a channel.

Parameters:
chan channel to hang up This function performs a hard hangup on a channel. Unlike the soft-hangup, this function performs all stream stopping, etc, on the channel that needs to end. chan is no longer valid after this call. Returns 0 on success, -1 on failure.

Definition at line 689 of file channel.c.

References ast_cdr_end(), ast_cdr_free(), ast_cdr_post(), ast_channel_free(), ast_closestream(), ast_do_masquerade(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_channel::blocker, ast_channel::blocking, ast_channel::blockproc, ast_channel::cdr, CRASH, EVENT_FLAG_CALL, ast_channel::generator, ast_channel::generatordata, ast_channel_pvt::hangup, ast_channel::hangupcause, ast_channel::lock, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::masq, ast_channel::masqr, ast_channel::name, option_debug, ast_channel::pvt, ast_generator::release, ast_channel::sched, sched_context_destroy(), ast_channel::stream, ast_channel::uniqueid, ast_channel::vstream, and ast_channel::zombie.

Referenced by __ast_request_and_dial(), ast_async_goto(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), and ast_pbx_run().

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 }

int ast_indicate struct ast_channel chan,
int  condition
 

Indicates condition of channel.

Parameters:
chan channel to change the indication
condition which condition to indicate on the channel Indicate a condition such as AST_CONTROL_BUSY, AST_CONTROL_RINGING, or AST_CONTROL_CONGESTION on a channel Returns 0 on success, -1 on failure

Definition at line 1411 of file channel.c.

References ast_check_hangup(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_get_indication_tone(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_playtones_start(), ast_playtones_stop(), tone_zone_sound::data, ast_channel_pvt::indicate, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel::pvt, ast_channel::zombie, and ast_channel::zone.

01412 {
01413    int res = -1;
01414    /* Stop if we're a zombie or need a soft hangup */
01415    if (chan->zombie || ast_check_hangup(chan)) 
01416       return -1;
01417    ast_mutex_lock(&chan->lock);
01418    if (chan->pvt->indicate)
01419       res = chan->pvt->indicate(chan, condition);
01420    ast_mutex_unlock(&chan->lock);
01421    if (!chan->pvt->indicate || res) {
01422       /*
01423        * Device does not support (that) indication, lets fake
01424        * it by doing our own tone generation. (PM2002)
01425        */
01426       if (condition >= 0) {
01427          const struct tone_zone_sound *ts = NULL;
01428          switch (condition) {
01429           case AST_CONTROL_RINGING:
01430             ts = ast_get_indication_tone(chan->zone, "ring");
01431             break;
01432           case AST_CONTROL_BUSY:
01433             ts = ast_get_indication_tone(chan->zone, "busy");
01434             break;
01435           case AST_CONTROL_CONGESTION:
01436             ts = ast_get_indication_tone(chan->zone, "congestion");
01437             break;
01438          }
01439          if (ts && ts->data[0]) {
01440             ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
01441             ast_playtones_start(chan,0,ts->data, 1);
01442             res = 0;
01443          } else if (condition == AST_CONTROL_PROGRESS) {
01444             /* ast_playtones_stop(chan); */
01445          } else if (condition == AST_CONTROL_PROCEEDING) {
01446             /* Do nothing, really */
01447          } else {
01448             /* not handled */
01449             ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
01450             res = -1;
01451          }
01452       }
01453       else ast_playtones_stop(chan);
01454    }
01455    return res;
01456 }

AST_MUTEX_DEFINE_STATIC chlock   ) 
 

int ast_parse_device_state char *  device  ) 
 

Search the Channels by Name.

Parameters:
device like a dialstring Search the Device in active channels by compare the channelname against the devicename. Compared are only the first chars to the first '-' char. Returns an AST_DEVICE_UNKNOWN if no channel found or AST_DEVICE_INUSE if a channel is found

Definition at line 1918 of file channel.c.

References AST_CHANNEL_NAME, ast_channel_walk_locked(), AST_DEVICE_INUSE, AST_DEVICE_UNKNOWN, ast_mutex_unlock, ast_channel::lock, and ast_channel::name.

Referenced by ast_device_state().

01919 {
01920    char name[AST_CHANNEL_NAME] = "";
01921    char *cut;
01922    struct ast_channel *chan;
01923 
01924    chan = ast_channel_walk_locked(NULL);
01925    while (chan) {
01926       strncpy(name, chan->name, sizeof(name)-1);
01927       ast_mutex_unlock(&chan->lock);
01928       cut = strchr(name,'-');
01929       if (cut)
01930               *cut = 0;
01931       if (!strcmp(name, device))
01932               return AST_DEVICE_INUSE;
01933       chan = ast_channel_walk_locked(chan);
01934    }
01935    return AST_DEVICE_UNKNOWN;
01936 }

int ast_prod struct ast_channel chan  ) 
 

Definition at line 1549 of file channel.c.

References ast_channel::_state, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), AST_STATE_UP, ast_write(), ast_frame::data, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel::pvt, ast_channel_pvt::rawwriteformat, and ast_frame::subclass.

Referenced by ast_activate_generator().

01550 {
01551    struct ast_frame a = { AST_FRAME_VOICE };
01552    char nothing[128];
01553    /* Send an empty audio frame to get things moving */
01554    if (chan->_state != AST_STATE_UP) {
01555       ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
01556       a.subclass = chan->pvt->rawwriteformat;
01557       a.data = nothing + AST_FRIENDLY_OFFSET;
01558       if (ast_write(chan, &a))
01559          ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name);
01560    }
01561    return 0;
01562 }

int ast_queue_control struct ast_channel chan,
int  control
 

Definition at line 434 of file channel.c.

References AST_FRAME_CONTROL, ast_queue_frame(), and ast_frame::subclass.

00435 {
00436    struct ast_frame f = { AST_FRAME_CONTROL, };
00437    f.subclass = control;
00438    return ast_queue_frame(chan, &f);
00439 }

int ast_queue_frame struct ast_channel chan,
struct ast_frame f
 

Queue an outgoing frame

Definition at line 370 of file channel.c.

References ast_channel_pvt::alertpipe, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_VOICE, ast_frdup(), ast_frfree(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_channel::blocker, ast_channel::blocking, CRASH, ast_frame::frametype, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_frame::next, ast_frame::prev, ast_channel::pvt, ast_channel_pvt::readq, ast_frame::subclass, and ast_channel::timingfd.

Referenced by ast_channel_masquerade(), ast_do_masquerade(), ast_dsp_process(), ast_queue_control(), ast_queue_hangup(), and ast_softhangup_nolock().

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 }

int ast_queue_hangup struct ast_channel chan  ) 
 

Definition at line 427 of file channel.c.

References ast_channel::_softhangup, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_queue_frame(), and AST_SOFTHANGUP_DEV.

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 }

struct ast_frame* ast_read struct ast_channel chan  ) 
 

Reads a frame.

Parameters:
chan channel to read a frame from Read a frame. Returns a frame, or NULL on error. If it returns NULL, you best just stop reading frames and assume the channel has been disconnected.

Definition at line 1192 of file channel.c.

References ast_channel::_softhangup, ast_channel::_state, ast_channel_pvt::alertpipe, ast_cdr_answer(), ast_cdr_end(), ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, ast_deactivate_generator(), ast_do_masquerade(), AST_FRAME_CNG, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dump(), AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_seekstream(), ast_setstate(), ast_settimeout(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_translate(), ast_writestream(), ast_channel::blocker, ast_channel::cdr, ast_frame::datalen, ast_channel::deferdtmf, ast_channel::dtmff, ast_channel::dtmfq, ast_channel::exception, ast_channel_pvt::exception, ast_channel::fdno, ast_channel::fin, ast_frame::frametype, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, ast_channel::insmpl, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::masq, ast_channel::monitor, ast_channel::name, ast_channel::nativeformats, ast_frame::next, ast_channel::outsmpl, ast_channel::pvt, ast_channel_pvt::read, ast_channel_monitor::read_stream, ast_channel_pvt::readq, ast_channel_pvt::readtrans, ast_frame::samples, SEEK_FORCECUR, ast_frame::subclass, ast_channel::timingdata, ast_channel::timingfd, ast_channel::timingfunc, and ast_channel::zombie.

Referenced by __ast_request_and_dial(), ast_app_getvoice(), ast_channel_bridge(), ast_play_and_prepend(), ast_play_and_record(), ast_recvchar(), ast_rtp_bridge(), ast_safe_sleep(), ast_safe_sleep_conditional(), ast_tonepair(), ast_waitfordigit(), ast_waitfordigit_full(), ast_waitstream(), ast_waitstream_fr(), and ast_waitstream_full().

01193 {
01194    struct ast_frame *f = NULL;
01195    int blah;
01196 #ifdef ZAPTEL_OPTIMIZATIONS
01197    int (*func)(void *);
01198    void *data;
01199    int res;
01200 #endif
01201    static struct ast_frame null_frame = 
01202    {
01203       AST_FRAME_NULL,
01204    };
01205    
01206    ast_mutex_lock(&chan->lock);
01207    if (chan->masq) {
01208       if (ast_do_masquerade(chan)) {
01209          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01210          f = NULL;
01211       } else
01212          f =  &null_frame;
01213       ast_mutex_unlock(&chan->lock);
01214       return f;
01215    }
01216 
01217    /* Stop if we're a zombie or need a soft hangup */
01218    if (chan->zombie || ast_check_hangup(chan)) {
01219       if (chan->generator)
01220          ast_deactivate_generator(chan);
01221       ast_mutex_unlock(&chan->lock);
01222       return NULL;
01223    }
01224 
01225    if (!chan->deferdtmf && !ast_strlen_zero(chan->dtmfq)) {
01226       /* We have DTMF that has been deferred.  Return it now */
01227       chan->dtmff.frametype = AST_FRAME_DTMF;
01228       chan->dtmff.subclass = chan->dtmfq[0];
01229       /* Drop first digit */
01230       memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
01231       ast_mutex_unlock(&chan->lock);
01232       return &chan->dtmff;
01233    }
01234    
01235    /* Read and ignore anything on the alertpipe, but read only
01236       one sizeof(blah) per frame that we send from it */
01237    if (chan->pvt->alertpipe[0] > -1) {
01238       read(chan->pvt->alertpipe[0], &blah, sizeof(blah));
01239    }
01240 #ifdef ZAPTEL_OPTIMIZATIONS
01241    if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) {
01242       chan->exception = 0;
01243       blah = -1;
01244       /* IF we can't get event, assume it's an expired as-per the old interface */
01245       res = ioctl(chan->timingfd, ZT_GETEVENT, &blah);
01246       if (res) 
01247          blah = ZT_EVENT_TIMER_EXPIRED;
01248 
01249       if (blah == ZT_EVENT_TIMER_PING) {
01250 #if 0
01251          ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
01252 #endif         
01253          if (!chan->pvt->readq || !chan->pvt->readq->next) {
01254             /* Acknowledge PONG unless we need it again */
01255 #if 0
01256             ast_log(LOG_NOTICE, "Sending a PONG!\n");
01257 #endif            
01258             if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) {
01259                ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno));
01260             }
01261          }
01262       } else if (blah == ZT_EVENT_TIMER_EXPIRED) {
01263          ioctl(chan->timingfd, ZT_TIMERACK, &blah);
01264          func = chan->timingfunc;
01265          data = chan->timingdata;
01266          ast_mutex_unlock(&chan->lock);
01267          if (func) {
01268 #if 0
01269             ast_log(LOG_DEBUG, "Calling private function\n");
01270 #endif         
01271             func(data);
01272          } else {
01273             blah = 0;
01274             ast_mutex_lock(&chan->lock);
01275             ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
01276             chan->timingdata = NULL;
01277             ast_mutex_unlock(&chan->lock);
01278          }
01279          f =  &null_frame;
01280          return f;
01281       } else
01282          ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
01283    }
01284 #endif
01285    /* Check for pending read queue */
01286    if (chan->pvt->readq) {
01287       f = chan->pvt->readq;
01288       chan->pvt->readq = f->next;
01289       /* Interpret hangup and return NULL */
01290       if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
01291          ast_frfree(f);
01292          f = NULL;
01293       }
01294    } else {
01295       chan->blocker = pthread_self();
01296       if (chan->exception) {
01297          if (chan->pvt->exception) 
01298             f = chan->pvt->exception(chan);
01299          else {
01300             ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
01301             f = &null_frame;
01302          }
01303          /* Clear the exception flag */
01304          chan->exception = 0;
01305       } else
01306       if (chan->pvt->read)
01307          f = chan->pvt->read(chan);
01308       else
01309          ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
01310    }
01311 
01312 
01313    if (f && (f->frametype == AST_FRAME_VOICE)) {
01314       if (!(f->subclass & chan->nativeformats)) {
01315          /* This frame can't be from the current native formats -- drop it on the
01316             floor */
01317          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));
01318          ast_frfree(f);
01319          f = &null_frame;
01320       } else {
01321          if (chan->monitor && chan->monitor->read_stream ) {
01322 #ifndef MONITOR_CONSTANT_DELAY
01323             int jump = chan->outsmpl - chan->insmpl - 2 * f->samples;
01324             if (jump >= 0) {
01325                if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01326                   ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01327                chan->insmpl += jump + 2 * f->samples;
01328             } else
01329                chan->insmpl+= f->samples;
01330 #else
01331             int jump = chan->outsmpl - chan->insmpl;
01332             if (jump - MONITOR_DELAY >= 0) {
01333                if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01334                   ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01335                chan->insmpl += jump;
01336             } else
01337                chan->insmpl += f->samples;
01338 #endif
01339             if (ast_writestream(chan->monitor->read_stream, f) < 0)
01340                ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
01341          }
01342          if (chan->pvt->readtrans) {
01343             f = ast_translate(chan->pvt->readtrans, f, 1);
01344             if (!f)
01345                f = &null_frame;
01346          }
01347       }
01348    }
01349 
01350    /* Make sure we always return NULL in the future */
01351    if (!f) {
01352       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01353       if (chan->generator)
01354          ast_deactivate_generator(chan);
01355       /* End the CDR if appropriate */
01356       if (chan->cdr)
01357          ast_cdr_end(chan->cdr);
01358    } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
01359       if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
01360          chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
01361       else
01362          ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
01363       f = &null_frame;
01364    } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
01365       if (chan->_state == AST_STATE_UP) {
01366          ast_log(LOG_DEBUG, "Dropping duplicate answer!\n");
01367          f = &null_frame;
01368       }
01369       /* Answer the CDR */
01370       ast_setstate(chan, AST_STATE_UP);
01371       ast_cdr_answer(chan->cdr);
01372    } 
01373 
01374    /* Run any generator sitting on the line */
01375    if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
01376       /* Mask generator data temporarily and apply.  If there is a timing function, it
01377          will be calling the generator instead */
01378       void *tmp;
01379       int res;
01380       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
01381       if (chan->timingfunc) {
01382          ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
01383          ast_settimeout(chan, 0, NULL, NULL);
01384       }
01385       tmp = chan->generatordata;
01386       chan->generatordata = NULL;
01387       generate = chan->generator->generate;
01388       res = generate(chan, tmp, f->datalen, f->samples);
01389       chan->generatordata = tmp;
01390       if (res) {
01391          ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
01392          ast_deactivate_generator(chan);
01393       }
01394    } else if (f && (f->frametype == AST_FRAME_CNG)) {
01395       if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) {
01396          ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n");
01397          ast_settimeout(chan, 160, generator_force, chan);
01398       }
01399    }
01400    /* High bit prints debugging */
01401    if (chan->fin & 0x80000000)
01402       ast_frame_dump(chan->name, f, "<<");
01403    if ((chan->fin & 0x7fffffff) == 0x7fffffff)
01404       chan->fin &= 0x80000000;
01405    else
01406       chan->fin++;
01407    ast_mutex_unlock(&chan->lock);
01408    return f;
01409 }

int ast_readstring struct ast_channel c,
char *  s,
int  len,
int  timeout,
int  rtimeout,
char *  enders
 

Reads multiple digits.

Parameters:
c channel to read from
s string to read in to. Must be at least the size of your length
len how many digits to read (maximum)
timeout how long to timeout between digits
rtimeout timeout to wait on the first digit
enders digits to end the string Read in a digit string "s", max length "len", maximum timeout between digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout for the first digit. Returns 0 on normal return, or 1 on a timeout. In the case of a timeout, any digits that were read before the timeout will still be available in s. RETURNS 2 in full version when ctrlfd is available, NOT 1

Definition at line 2012 of file channel.c.

References ast_check_hangup(), AST_DIGIT_ANY, ast_stopstream(), ast_waitfordigit(), ast_waitstream(), ast_channel::stream, and ast_channel::zombie.

Referenced by ast_app_getdata().

02013 {
02014    int pos=0;
02015    int to = ftimeout;
02016    int d;
02017    /* XXX Merge with full version? XXX */
02018    /* Stop if we're a zombie or need a soft hangup */
02019    if (c->zombie || ast_check_hangup(c)) 
02020       return -1;
02021    if (!len)
02022       return -1;
02023    do {
02024       if (c->stream) {
02025          d = ast_waitstream(c, AST_DIGIT_ANY);
02026          ast_stopstream(c);
02027          usleep(1000);
02028          if (!d)
02029             d = ast_waitfordigit(c, to);
02030       } else {
02031          d = ast_waitfordigit(c, to);
02032       }
02033       if (d < 0)
02034          return -1;
02035       if (d == 0) {
02036          s[pos]='\0';
02037          return 1;
02038       }
02039       if (!strchr(enders, d))
02040          s[pos++] = d;
02041       if (strchr(enders, d) || (pos >= len)) {
02042          s[pos]='\0';
02043          return 0;
02044       }
02045       to = timeout;
02046    } while(1);
02047    /* Never reached */
02048    return 0;
02049 }

int ast_readstring_full struct ast_channel c,
char *  s,
int  len,
int  timeout,
int  ftimeout,
char *  enders,
int  audiofd,
int  ctrlfd
 

Definition at line 2051 of file channel.c.

References ast_check_hangup(), AST_DIGIT_ANY, ast_stopstream(), ast_waitfordigit_full(), ast_waitstream_full(), ast_channel::stream, and ast_channel::zombie.

Referenced by ast_app_getdata_full().

02052 {
02053    int pos=0;
02054    int to = ftimeout;
02055    int d;
02056    /* Stop if we're a zombie or need a soft hangup */
02057    if (c->zombie || ast_check_hangup(c)) 
02058       return -1;
02059    if (!len)
02060       return -1;
02061    do {
02062       if (c->stream) {
02063          d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
02064          ast_stopstream(c);
02065          usleep(1000);
02066          if (!d)
02067             d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02068       } else {
02069          d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02070       }
02071       if (d < 0)
02072          return -1;
02073       if (d == 0) {
02074          s[pos]='\0';
02075          return 1;
02076       }
02077       if (d == 1) {
02078          s[pos]='\0';
02079          return 2;
02080       }
02081       if (!strchr(enders, d))
02082          s[pos++] = d;
02083       if (strchr(enders, d) || (pos >= len)) {
02084          s[pos]='\0';
02085          return 0;
02086       }
02087       to = timeout;
02088    } while(1);
02089    /* Never reached */
02090    return 0;
02091 }

int ast_recvchar struct ast_channel chan,
int  timeout
 

Definition at line 1458 of file channel.c.

References ast_check_hangup(), AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_frfree(), ast_read(), ast_waitfor(), ast_frame::data, ast_frame::frametype, and ast_frame::subclass.

01459 {
01460    int res,ourto,c;
01461    struct ast_frame *f;
01462    
01463    ourto = timeout;
01464    for(;;)
01465       {
01466       if (ast_check_hangup(chan)) return -1;
01467       res = ast_waitfor(chan,ourto);
01468       if (res <= 0) /* if timeout */
01469          {
01470          return 0;
01471          }
01472       ourto = res;
01473       f = ast_read(chan);
01474       if (f == NULL) return -1; /* if hangup */
01475       if ((f->frametype == AST_FRAME_CONTROL) &&
01476           (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
01477       if (f->frametype == AST_FRAME_TEXT)  /* if a text frame */
01478          {
01479          c = *((char *)f->data);  /* get the data */
01480          ast_frfree(f);
01481          return(c);
01482          }
01483       ast_frfree(f);
01484    }
01485 }

struct ast_channel* ast_request char *  type,
int  format,
void *  data
 

Requests a channel.

Parameters:
type type of channel to request
format requested channel format
data data to pass to the channel requester Request a channel of a given type, with data as optional information used by the low level module Returns an ast_channel on success, NULL on failure.

Definition at line 1873 of file channel.c.

References ast_channel::_state, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_state2str(), AST_STATE_DOWN, ast_translator_best_choice(), backends, ast_channel::callerid, chanlist::capabilities, EVENT_FLAG_CALL, LOG_WARNING, manager_event(), ast_channel::name, chanlist::next, chanlist::requester, chanlist::type, and ast_channel::uniqueid.

Referenced by __ast_request_and_dial().

01874 {
01875    struct chanlist *chan;
01876    struct ast_channel *c = NULL;
01877    int capabilities;
01878    int fmt;
01879    int res;
01880    if (ast_mutex_lock(&chlock)) {
01881       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01882       return NULL;
01883    }
01884    chan = backends;
01885    while(chan) {
01886       if (!strcasecmp(type, chan->type)) {
01887          capabilities = chan->capabilities;
01888          fmt = format;
01889          res = ast_translator_best_choice(&fmt, &capabilities);
01890          if (res < 0) {
01891             ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
01892             ast_mutex_unlock(&chlock);
01893             return NULL;
01894          }
01895          ast_mutex_unlock(&chlock);
01896          if (chan->requester)
01897             c = chan->requester(type, capabilities, data);
01898          if (c) {
01899             if (c->_state == AST_STATE_DOWN) {
01900                manager_event(EVENT_FLAG_CALL, "Newchannel",
01901                "Channel: %s\r\n"
01902                "State: %s\r\n"
01903                "CallerID: %s\r\n"
01904                "Uniqueid: %s\r\n",
01905                c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid);
01906             }
01907          }
01908          return c;
01909       }
01910       chan = chan->next;
01911    }
01912    if (!chan)
01913       ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
01914    ast_mutex_unlock(&chlock);
01915    return c;
01916 }

struct ast_channel* ast_request_and_dial char *  type,
int  format,
void *  data,
int  timeout,
int *  reason,
char *  callerid
 

Parameters:
type type of channel to request
format requested channel format
data data to pass to the channel requester
timeout maximum amount of time to wait for an answer
why unsuccessful (if unsuceessful) Request a channel of a given type, with data as optional information used by the low level module and attempt to place a call on it Returns an ast_channel on success or no answer, NULL on failure. Check the value of chan->_state to know if the call was answered or not.

Definition at line 1868 of file channel.c.

References __ast_request_and_dial().

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

01869 {
01870    return __ast_request_and_dial(type, format, data, timeout, outstate, callerid, NULL);
01871 }

int ast_safe_sleep struct ast_channel chan,
int  ms
 

Wait for a specied amount of time, looking for hangups.

Parameters:
chan channel to wait for
ms length of time in milliseconds to sleep Waits for a specified amount of time, servicing the channel as required. returns -1 on hangup, otherwise 0.

Definition at line 544 of file channel.c.

References ast_frfree(), ast_read(), and ast_waitfor().

Referenced by ast_dtmf_stream().

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 }

int ast_safe_sleep_conditional struct ast_channel chan,
int  ms,
int(*)(void *)  cond,
void *  data
 

Wait for a specied amount of time, looking for hangups and a condition argument.

Parameters:
chan channel to wait for
ms length of time in milliseconds to sleep
cond a function pointer for testing continue condition
data argument to be passed to the condition test function Waits for a specified amount of time, servicing the channel as required. If cond returns 0, this function returns. returns -1 on hangup, otherwise 0.

Definition at line 523 of file channel.c.

References ast_frfree(), ast_read(), and ast_waitfor().

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 }

int ast_senddigit struct ast_channel chan,
char  digit
 

Receives a text character from a channel.

Parameters:
chan channel to act upon
timeout timeout in milliseconds (0 for infinite wait) Read a char of text from a channel Returns 0 on success, -1 on failure

Definition at line 1544 of file channel.c.

01545 {
01546    return do_senddigit(chan, digit);
01547 }

int ast_sendtext struct ast_channel chan,
char *  text
 

Sends text to a channel.

Parameters:
chan channel to act upon
text string of text to send on the channel Write text to a display on a channel Returns 0 on success, -1 on failure

Definition at line 1487 of file channel.c.

References ast_check_hangup(), ast_channel::blocking, CHECK_BLOCKING, ast_channel::pvt, ast_channel_pvt::send_text, and ast_channel::zombie.

01488 {
01489    int res = 0;
01490    /* Stop if we're a zombie or need a soft hangup */
01491    if (chan->zombie || ast_check_hangup(chan)) 
01492       return -1;
01493    CHECK_BLOCKING(chan);
01494    if (chan->pvt->send_text)
01495       res = chan->pvt->send_text(chan, text);
01496    chan->blocking = 0;
01497    return res;
01498 }

void ast_set_callerid struct ast_channel chan,
char *  callerid,
int  anitoo
 

Definition at line 2423 of file channel.c.

References ast_channel::ani, ast_cdr_setcid(), ast_channel::callerid, ast_channel::cdr, EVENT_FLAG_CALL, free, manager_event(), ast_channel::name, strdup, and ast_channel::uniqueid.

Referenced by __ast_request_and_dial().

02424 {
02425    if (chan->callerid)
02426       free(chan->callerid);
02427    if (anitoo && chan->ani)
02428       free(chan->ani);
02429    if (callerid) {
02430       chan->callerid = strdup(callerid);
02431       if (anitoo)
02432          chan->ani = strdup(callerid);
02433    } else {
02434       chan->callerid = NULL;
02435       if (anitoo)
02436          chan->ani = NULL;
02437    }
02438    if (chan->cdr)
02439       ast_cdr_setcid(chan->cdr, chan);
02440    manager_event(EVENT_FLAG_CALL, "Newcallerid", 
02441             "Channel: %s\r\n"
02442             "CallerID: %s\r\n"
02443             "Uniqueid: %s\r\n",
02444             chan->name, chan->callerid ? 
02445             chan->callerid : "<Unknown>",
02446             chan->uniqueid);
02447 }

int ast_set_read_format struct ast_channel chan,
int  format
 

Sets read format on channel chan.

Parameters:
chan channel to change
format format to change to Set read format for channel to whichever component of "format" is best. Returns 0 on success, -1 on failure

Definition at line 1724 of file channel.c.

References ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), ast_channel::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::name, ast_channel::nativeformats, option_debug, ast_channel::pvt, ast_channel_pvt::rawreadformat, ast_channel::readformat, and ast_channel_pvt::readtrans.

Referenced by ast_app_getvoice(), ast_channel_make_compatible(), ast_do_masquerade(), ast_play_and_prepend(), and ast_play_and_record().

01725 {
01726    int fmt;
01727    int native;
01728    int res;
01729    
01730    ast_mutex_lock(&chan->lock);
01731    native = chan->nativeformats;
01732    fmt = fmts;
01733    /* Find a translation path from the native read format to one of the user's read formats */
01734    res = ast_translator_best_choice(&fmt, &native);
01735    if (res < 0) {
01736       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01737          ast_getformatname(chan->nativeformats), ast_getformatname(fmts));
01738       ast_mutex_unlock(&chan->lock);
01739       return -1;
01740    }
01741    
01742    /* Now we have a good choice for both.  We'll write using our native format. */
01743    chan->pvt->rawreadformat = native;
01744    /* User perspective is fmt */
01745    chan->readformat = fmt;
01746    /* Free any read translation we have right now */
01747    if (chan->pvt->readtrans)
01748       ast_translator_free_path(chan->pvt->readtrans);
01749    /* Build a translation path from the raw read format to the user reading format */
01750    chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
01751    if (option_debug)
01752       ast_log(LOG_DEBUG, "Set channel %s to read format %s\n", 
01753          chan->name, ast_getformatname(chan->readformat));
01754    ast_mutex_unlock(&chan->lock);
01755    return 0;
01756 }

int ast_set_write_format struct ast_channel chan,
int  format
 

Sets write format on channel chan.

Parameters:
chan channel to change
format new format for writing Set write format for channel to whichever compoent of "format" is best. Returns 0 on success, -1 on failure

Definition at line 1691 of file channel.c.

References ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), ast_channel::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::name, ast_channel::nativeformats, option_debug, ast_channel::pvt, ast_channel_pvt::rawwriteformat, ast_channel::writeformat, and ast_channel_pvt::writetrans.

Referenced by ast_channel_make_compatible(), ast_do_masquerade(), ast_openstream(), and ast_stopstream().

01692 {
01693    int fmt;
01694    int native;
01695    int res;
01696    
01697    ast_mutex_lock(&chan->lock);
01698    native = chan->nativeformats;
01699    fmt = fmts;
01700    
01701    res = ast_translator_best_choice(&native, &fmt);
01702    if (res < 0) {
01703       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01704          ast_getformatname(fmts), ast_getformatname(chan->nativeformats));
01705       ast_mutex_unlock(&chan->lock);
01706       return -1;
01707    }
01708    
01709    /* Now we have a good choice for both.  We'll write using our native format. */
01710    chan->pvt->rawwriteformat = native;
01711    /* User perspective is fmt */
01712    chan->writeformat = fmt;
01713    /* Free any write translation we have right now */
01714    if (chan->pvt->writetrans)
01715       ast_translator_free_path(chan->pvt->writetrans);
01716    /* Build a translation path from the user write format to the raw writing format */
01717    chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
01718    if (option_debug)
01719       ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat));
01720    ast_mutex_unlock(&chan->lock);
01721    return 0;
01722 }

int ast_setstate struct ast_channel chan,
int  state
 

Change the state of a channel

Definition at line 2449 of file channel.c.

References ast_channel::_state, ast_device_state_changed(), ast_state2str(), AST_STATE_DOWN, ast_channel::callerid, EVENT_FLAG_CALL, manager_event(), ast_channel::name, and ast_channel::uniqueid.

Referenced by ast_answer(), ast_async_goto(), and ast_read().

02450 {
02451    if (chan->_state != state) {
02452       int oldstate = chan->_state;
02453       chan->_state = state;
02454       if (oldstate == AST_STATE_DOWN) {
02455          ast_device_state_changed(chan->name);
02456          manager_event(EVENT_FLAG_CALL, "Newchannel",
02457          "Channel: %s\r\n"
02458          "State: %s\r\n"
02459          "CallerID: %s\r\n"
02460          "Uniqueid: %s\r\n",
02461          chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02462       } else {
02463          manager_event(EVENT_FLAG_CALL, "Newstate", 
02464             "Channel: %s\r\n"
02465             "State: %s\r\n"
02466             "CallerID: %s\r\n"
02467             "Uniqueid: %s\r\n",
02468             chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02469       }
02470    }
02471    return 0;
02472 }

int ast_settimeout struct ast_channel c,
int  samples,
int(*)(void *data)  func,
void *  data
 

Definition at line 1119 of file channel.c.

References ast_log(), LOG_DEBUG, ast_channel::timingdata, ast_channel::timingfd, and ast_channel::timingfunc.

Referenced by ast_activate_generator(), ast_closestream(), ast_deactivate_generator(), and ast_read().

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 }

int ast_shutting_down void   ) 
 

Returns non-zero if Asterisk is being shut down

Definition at line 139 of file channel.c.

00140 {
00141    return shutting_down;
00142 }

int ast_softhangup struct ast_channel chan,
int  cause
 

Softly hangup up a channel.

Parameters:
chan channel to be soft-hung-up Call the protocol layer, but don't destroy the channel structure (use this if you are trying to safely hangup a channel managed by another thread. Returns 0 regardless

Definition at line 668 of file channel.c.

References ast_mutex_lock, ast_mutex_unlock, ast_softhangup_nolock(), and ast_channel::lock.

Referenced by ast_begin_shutdown().

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 }

int ast_softhangup_nolock struct ast_channel chan,
int  cause
 

Definition at line 653 of file channel.c.

References ast_channel::_softhangup, AST_FRAME_NULL, ast_log(), ast_queue_frame(), ast_channel::blocker, ast_channel::blocking, LOG_DEBUG, ast_channel::name, and option_debug.

Referenced by ast_async_goto(), and ast_softhangup().

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 }

char* ast_state2str int  state  ) 
 

Gives the string form of a given state.

Parameters:
state state to get the name of Give a name to a state Pretty self explanatory. Returns the text form of the binary state given

Definition at line 205 of file channel.c.

References AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_OFFHOOK, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, and AST_STATE_UP.

Referenced by ast_request(), and ast_setstate().

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 }

int ast_tonepair struct ast_channel chan,
int  freq1,
int  freq2,
int  duration,
int  vol
 

Play a tone pair for a given amount of time

Definition at line 2884 of file channel.c.

References ast_frfree(), ast_read(), ast_tonepair_start(), ast_waitfor(), and ast_channel::generatordata.

02885 {
02886    struct ast_frame *f;
02887    int res;
02888    if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
02889       return res;
02890 
02891    /* Give us some wiggle room */
02892    while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
02893       f = ast_read(chan);
02894       if (f)
02895          ast_frfree(f);
02896       else
02897          return -1;
02898    }
02899    return 0;
02900 }

int ast_tonepair_start struct ast_channel chan,
int  freq1,
int  freq2,
int  duration,
int  vol
 

Start a tone going

Definition at line 2864 of file channel.c.

References ast_activate_generator(), tonepair_def::duration, tonepair_def::freq1, tonepair_def::freq2, and tonepair_def::vol.

Referenced by ast_tonepair().

02865 {
02866    struct tonepair_def d = { 0, };
02867    d.freq1 = freq1;
02868    d.freq2 = freq2;
02869    d.duration = duration;
02870    if (vol < 1)
02871       d.vol = 8192;
02872    else
02873       d.vol = vol;
02874    if (ast_activate_generator(chan, &tonepair, &d))
02875       return -1;
02876    return 0;
02877 }

void ast_tonepair_stop struct ast_channel chan  ) 
 

Stop a tone from playing

Definition at line 2879 of file channel.c.

References ast_deactivate_generator().

02880 {
02881    ast_deactivate_generator(chan);
02882 }

int ast_transfer struct ast_channel chan,
char *  dest
 

Definition at line 1992 of file channel.c.

References ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_channel::lock, ast_channel::pvt, ast_channel_pvt::transfer, and ast_channel::zombie.

01993 {
01994    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
01995       If the remote end does not answer within the timeout, then do NOT hang up, but 
01996       return anyway.  */
01997    int res = -1;
01998    /* Stop if we're a zombie or need a soft hangup */
01999    ast_mutex_lock(&chan->lock);
02000    if (!chan->zombie && !ast_check_hangup(chan)) {
02001       if (chan->pvt->transfer) {
02002          res = chan->pvt->transfer(chan, dest);
02003          if (!res)
02004             res = 1;
02005       } else
02006          res = 0;
02007    }
02008    ast_mutex_unlock(&chan->lock);
02009    return res;
02010 }

int ast_waitfor struct ast_channel chan,
int  ms
 

Wait for input on a channel.

Parameters:
chan channel to wait on
ms length of time to wait on the channel Wait for input on a channel for a given # of milliseconds (<0 for indefinite). Returns < 0 on failure, 0 if nothing ever arrived, and the # of ms remaining otherwise

Definition at line 1078 of file channel.c.

References ast_waitfor_n().

Referenced by __ast_request_and_dial(), ast_app_getvoice(), ast_dtmf_stream(), ast_play_and_prepend(), ast_play_and_record(), ast_recvchar(), ast_safe_sleep(), ast_safe_sleep_conditional(), ast_tonepair(), ast_waitfordigit(), ast_waitstream(), and ast_waitstream_fr().

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 }

struct ast_channel* ast_waitfor_n struct ast_channel **  chan,
int  n,
int *  ms
 

Waits for input on a group of channels.

Wait for input on an array of channels for a given # of milliseconds. Return channel with activity, or NULL if none has activity. time "ms" is modified in-place, if applicable

Definition at line 1073 of file channel.c.

References ast_waitfor_nandfds().

Referenced by ast_channel_bridge(), ast_rtp_bridge(), and ast_waitfor().

01074 {
01075    return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
01076 }

int ast_waitfor_n_fd int *  fds,
int  n,
int *  ms,
int *  exception
 

Waits for input on an fd.

This version works on fd's only. Be careful with it.

Definition at line 869 of file channel.c.

References ast_log(), pollfd::events, pollfd::fd, LOG_WARNING, poll(), POLLIN, and POLLPRI.

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 }

struct ast_channel* ast_waitfor_nandfds struct ast_channel **  chan,
int  n,
int *  fds,
int  nfds,
int *  exception,
int *  outfd,
int *  ms
 

Waits for activity on a group of channels.

Parameters:
chan an array of pointers to channels
n number of channels that are to be waited upon
fds an array of fds to wait upon
nfds the number of fds to wait upon
exception exception flag
outfd fd that had activity on it
ms how long the wait was Big momma function here. Wait for activity on any of the n channels, or any of the nfds file descriptors. Returns the channel with activity, or NULL on error or if an FD came first. If the FD came first, it will be returned in outfd, otherwise, outfd will be -1

Definition at line 930 of file channel.c.

References ast_channel::_softhangup, ast_do_masquerade(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_TIMEOUT, ast_channel::blocking, CHECK_BLOCKING, pollfd::events, ast_channel::exception, pollfd::fd, ast_channel::fdno, ast_channel::fds, ast_channel::lock, LOG_WARNING, ast_channel::masq, poll(), POLLIN, POLLPRI, and ast_channel::whentohangup.

Referenced by ast_waitfor_n(), ast_waitfordigit_full(), and ast_waitstream_full().

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 }

int ast_waitfordigit struct ast_channel c,
int  ms
 

Waits for a digit.

Parameters:
c channel to wait for a digit on
ms how many milliseconds to wait Wait for a digit. Returns <0 on error, 0 on no entry, and the digit on success.

Definition at line 1092 of file channel.c.

References ast_check_hangup(), AST_FRAME_DTMF, ast_frfree(), ast_read(), ast_waitfor(), ast_frame::frametype, ast_frame::subclass, and ast_channel::zombie.

Referenced by ast_control_streamfile(), ast_pbx_run(), and ast_readstring().

01093 {
01094    /* XXX Should I be merged with waitfordigit_full XXX */
01095    struct ast_frame *f;
01096    int 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 }

int ast_waitfordigit_full struct ast_channel c,
int  ms,
int  audiofd,
int  cmdfd
 

Definition at line 1136 of file channel.c.

References ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_waitfor_nandfds(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, ast_frame::subclass, and ast_channel::zombie.

Referenced by ast_readstring_full().

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       errno = 0;
01148       rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01149       if ((!rchan) && (outfd < 0) && (ms)) { 
01150          if (errno == 0 || errno == EINTR)
01151             continue;
01152          ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01153          return -1;
01154       } else if (outfd > -1) {
01155          /* The FD we were watching has something waiting */
01156          return 1;
01157       } else if (rchan) {
01158          f = ast_read(c);
01159          if(!f) {
01160             return -1;
01161          }
01162 
01163          switch(f->frametype) {
01164          case AST_FRAME_DTMF:
01165             res = f->subclass;
01166             ast_frfree(f);
01167             return res;
01168          case AST_FRAME_CONTROL:
01169             switch(f->subclass) {
01170             case AST_CONTROL_HANGUP:
01171                ast_frfree(f);
01172                return -1;
01173             case AST_CONTROL_RINGING:
01174             case AST_CONTROL_ANSWER:
01175                /* Unimportant */
01176                break;
01177             default:
01178                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass);
01179             }
01180          case AST_FRAME_VOICE:
01181             /* Write audio if appropriate */
01182             if (audiofd > -1)
01183                write(audiofd, f->data, f->datalen);
01184          }
01185          /* Ignore */
01186          ast_frfree(f);
01187       }
01188    }
01189    return 0; // Time is up
01190 }

int ast_write struct ast_channel chan,
struct ast_frame frame
 

Write a frame to a channel.

Parameters:
chan destination channel of the frame
frame frame that will be written This function writes the given frame to the indicated channel. It returns 0 on success, -1 on failure.

Definition at line 1575 of file channel.c.

References ast_channel::_softhangup, ast_check_hangup(), ast_deactivate_generator(), ast_do_masquerade(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dump(), AST_FRAME_HTML, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_seekstream(), AST_SOFTHANGUP_DEV, ast_translate(), ast_writestream(), ast_channel::blocking, CHECK_BLOCKING, ast_frame::data, ast_frame::datalen, ast_channel::fout, ast_frame::frametype, ast_channel::generatordata, ast_channel::insmpl, ast_channel::lock, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, ast_channel::name, ast_channel::outsmpl, ast_channel::pvt, ast_frame::samples, SEEK_FORCECUR, ast_channel_pvt::send_html, ast_channel_pvt::send_text, ast_frame::subclass, ast_channel_pvt::write, ast_channel_monitor::write_stream, ast_channel_pvt::write_video, ast_channel::writeinterrupt, ast_channel_pvt::writetrans, and ast_channel::zombie.

Referenced by ast_channel_bridge(), ast_dtmf_stream(), ast_prod(), ast_rtp_bridge(), and ast_write_video().

01576 {
01577    int res = -1;
01578    struct ast_frame *f = NULL;
01579    /* Stop if we're a zombie or need a soft hangup */
01580    ast_mutex_lock(&chan->lock);
01581    if (chan->zombie || ast_check_hangup(chan))  {
01582       ast_mutex_unlock(&chan->lock);
01583       return -1;
01584    }
01585    /* Handle any pending masquerades */
01586    if (chan->masq) {
01587       if (ast_do_masquerade(chan)) {
01588          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01589          ast_mutex_unlock(&chan->lock);
01590          return -1;
01591       }
01592    }
01593    if (chan->masqr) {
01594       ast_mutex_unlock(&chan->lock);
01595       return 0;
01596    }
01597    if (chan->generatordata) {
01598       if (chan->writeinterrupt)
01599          ast_deactivate_generator(chan);
01600       else {
01601          ast_mutex_unlock(&chan->lock);
01602          return 0;
01603       }
01604    }
01605    /* High bit prints debugging */
01606    if (chan->fout & 0x80000000)
01607       ast_frame_dump(chan->name, fr, ">>");
01608    CHECK_BLOCKING(chan);
01609    switch(fr->frametype) {
01610    case AST_FRAME_CONTROL:
01611       /* XXX Interpret control frames XXX */
01612       ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
01613       break;
01614    case AST_FRAME_DTMF:
01615       chan->blocking = 0;
01616       ast_mutex_unlock(&chan->lock);
01617       res = do_senddigit(chan,fr->subclass);
01618       ast_mutex_lock(&chan->lock);
01619       CHECK_BLOCKING(chan);
01620       break;
01621    case AST_FRAME_TEXT:
01622       if (chan->pvt->send_text)
01623          res = chan->pvt->send_text(chan, (char *) fr->data);
01624       else
01625          res = 0;
01626       break;
01627    case AST_FRAME_HTML:
01628       if (chan->pvt->send_html)
01629          res = chan->pvt->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen);
01630       else
01631          res = 0;
01632       break;
01633    case AST_FRAME_VIDEO:
01634       /* XXX Handle translation of video codecs one day XXX */
01635       if (chan->pvt->write_video)
01636          res = chan->pvt->write_video(chan, fr);
01637       else
01638          res = 0;
01639       break;
01640    default:
01641       if (chan->pvt->write) {
01642          if (chan->pvt->writetrans) {
01643             f = ast_translate(chan->pvt->writetrans, fr, 0);
01644          } else
01645             f = fr;
01646          if (f) {
01647             res = chan->pvt->write(chan, f);
01648             if( chan->monitor &&
01649                   chan->monitor->write_stream &&
01650                   f && ( f->frametype == AST_FRAME_VOICE ) ) {
01651 #ifndef MONITOR_CONSTANT_DELAY
01652                int jump = chan->insmpl - chan->outsmpl - 2 * f->samples;
01653                if (jump >= 0) {
01654                   if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01655                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01656                   chan->outsmpl += jump + 2 * f->samples;
01657                } else
01658                   chan->outsmpl += f->samples;
01659 #else
01660                int jump = chan->insmpl - chan->outsmpl;
01661                if (jump - MONITOR_DELAY >= 0) {
01662                   if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01663                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01664                   chan->outsmpl += jump;
01665                } else
01666                   chan->outsmpl += f->samples;
01667 #endif
01668             if (ast_writestream(chan->monitor->write_stream, f) < 0)
01669                   ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
01670             }
01671          } else
01672             res = 0;
01673       }
01674    }
01675    if (f && (f != fr))
01676       ast_frfree(f);
01677    chan->blocking = 0;
01678    /* Consider a write failure to force a soft hangup */
01679    if (res < 0)
01680       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01681    else {
01682       if ((chan->fout & 0x7fffffff) == 0x7fffffff)
01683          chan->fout &= 0x80000000;
01684       else
01685          chan->fout++;
01686    }
01687    ast_mutex_unlock(&chan->lock);
01688    return res;
01689 }

int ast_write_video struct ast_channel chan,
struct ast_frame frame
 

Write video frame to a channel.

Parameters:
chan destination channel of the frame
frame frame that will be written This function writes the given frame to the indicated channel. It returns 1 on success, 0 if not implemented, and -1 on failure.

Definition at line 1564 of file channel.c.

References ast_write(), ast_channel::pvt, and ast_channel_pvt::write_video.

01565 {
01566    int res;
01567    if (!chan->pvt->write_video)
01568       return 0;
01569    res = ast_write(chan, fr);
01570    if (!res)
01571       res = 1;
01572    return res;
01573 }


Variable Documentation

struct chanlist * backends
 

Referenced by ast_channel_register_ex(), ast_channel_unregister(), ast_device_state(), and ast_request().

struct ast_channel* channels = NULL
 

Definition at line 72 of file channel.c.


Generated on Wed Aug 10 11:36:33 2005 for Asterisk by  doxygen 1.4.4