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

channel.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <math.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/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>

Go to the source code of this file.

Data Structures

struct  chanlist
struct  tonepair_def
struct  tonepair_state

Functions

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 lock)
int ast_queue_hangup (struct ast_channel *chan, int lock)
int ast_queue_control (struct ast_channel *chan, int control, int lock)
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 (struct ast_channel *prev)
 Browse channels in use.

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.

char 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)
char ast_waitfordigit_full (struct ast_channel *c, int ms, int audio, int ctrl)
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)
 Receives a text character from a channel.

int ast_sendtext (struct ast_channel *chan, char *text)
 Sends text to 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)
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, int flags, 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)

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 1501 of file channel.c.

References ast_channel::_state, outgoing_helper::account, 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_RINGING, AST_FRAME_CONTROL, ast_frfree(), ast_hangup(), ast_log(), ast_read(), ast_request(), ast_set_callerid(), AST_STATE_UP, ast_waitfor(), outgoing_helper::callerid, ast_channel::cdr, outgoing_helper::context, ast_channel::context, outgoing_helper::exten, ast_channel::exten, ast_channel::hangupcause, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar(), ast_channel::priority, outgoing_helper::priority, type, and outgoing_helper::variable.

Referenced by ast_request_and_dial().

01502 {
01503    int state = 0;
01504    struct ast_channel *chan;
01505    struct ast_frame *f;
01506    int res = 0;
01507    chan = ast_request(type, format, data);
01508    if (chan) {
01509       if (oh) {
01510          char *tmp, *var;
01511          /* JDG chanvar */
01512          tmp = oh->variable;
01513          /* FIXME replace this call with strsep  NOT*/
01514          while( (var = strtok_r(NULL, "|", &tmp)) ) {
01515             pbx_builtin_setvar( chan, var );
01516          } /* /JDG */
01517          if (oh->callerid && *oh->callerid)
01518             ast_set_callerid(chan, oh->callerid, 1);
01519          if (oh->account && *oh->account)
01520             ast_cdr_setaccount(chan, oh->account);
01521       }
01522       if (callerid && strlen(callerid))
01523          ast_set_callerid(chan, callerid, 1);
01524 
01525       if (!ast_call(chan, data, 0)) {
01526          while(timeout && (chan->_state != AST_STATE_UP)) {
01527             res = ast_waitfor(chan, timeout);
01528             if (res < 0) {
01529                /* Something not cool, or timed out */
01530                break;
01531             }
01532             /* If done, break out */
01533             if (!res)
01534                break;
01535             if (timeout > -1)
01536                timeout = res;
01537             f = ast_read(chan);
01538             if (!f) {
01539                state = AST_CONTROL_HANGUP;
01540                res = 0;
01541                break;
01542             }
01543             if (f->frametype == AST_FRAME_CONTROL) {
01544                if (f->subclass == AST_CONTROL_RINGING)
01545                   state = AST_CONTROL_RINGING;
01546                else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01547                   state = f->subclass;
01548                   ast_frfree(f);
01549                   break;
01550                } else if (f->subclass == AST_CONTROL_ANSWER) {
01551                   state = f->subclass;
01552                   ast_frfree(f);
01553                   break;
01554                } else {
01555                   ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
01556                }
01557             }
01558             ast_frfree(f);
01559          }
01560       } else
01561          ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01562    } else
01563       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01564    if (chan) {
01565       /* Final fixups */
01566       if (oh) {
01567          if (oh->context && *oh->context)
01568             strncpy(chan->context, oh->context, sizeof(chan->context) - 1);
01569          if (oh->exten && *oh->exten)
01570             strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1);
01571          chan->priority = oh->priority;
01572       }
01573       if (chan->_state == AST_STATE_UP) 
01574          state = AST_CONTROL_ANSWER;
01575    }
01576    if (outstate)
01577       *outstate = state;
01578    if (chan && res <= 0) {
01579       if (!chan->cdr) {
01580          chan->cdr = ast_cdr_alloc();
01581          if (chan->cdr)
01582             ast_cdr_init(chan->cdr, chan);
01583       }
01584       if (chan->cdr) {
01585          char tmp[256];
01586          sprintf(tmp, "%s/%s",type,(char *)data);
01587          ast_cdr_setapp(chan->cdr,"Dial",tmp);
01588          ast_cdr_update(chan);
01589          ast_cdr_start(chan->cdr);
01590          ast_cdr_end(chan->cdr);
01591          /* If the cause wasn't handled properly */
01592          if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
01593             ast_cdr_failed(chan->cdr);
01594       } else 
01595          ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01596       ast_hangup(chan);
01597       chan = NULL;
01598    }
01599    return chan;
01600 }

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

Activate a given generator

Definition at line 743 of file channel.c.

References ast_generator::alloc, ast_prod(), ast_channel::generator, ast_channel::generatordata, and ast_generator::release.

Referenced by ast_playtones_start(), and ast_tonepair_start().

00744 {
00745    if (chan->generatordata) {
00746       chan->generator->release(chan, chan->generatordata);
00747       chan->generatordata = NULL;
00748    }
00749    ast_prod(chan);
00750    if ((chan->generatordata = gen->alloc(chan, params))) {
00751       chan->generator = gen;
00752    } else {
00753       return -1;
00754    }
00755    return 0;
00756 }

int ast_active_channels void   ) 
 

Returns number of active/allocated channels

Definition at line 110 of file channel.c.

References ast_mutex_lock, ast_mutex_unlock, channels, and ast_channel::next.

00111 {
00112    struct ast_channel *c;
00113    int cnt = 0;
00114    ast_mutex_lock(&chlock);
00115    c = channels;
00116    while(c) {
00117       cnt++;
00118       c = c->next;
00119    }
00120    ast_mutex_unlock(&chlock);
00121    return cnt;
00122 }

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 707 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.

00708 {
00709    int res = 0;
00710    /* Stop if we're a zombie or need a soft hangup */
00711    if (chan->zombie || ast_check_hangup(chan)) 
00712       return -1;
00713    switch(chan->_state) {
00714    case AST_STATE_RINGING:
00715    case AST_STATE_RING:
00716       ast_mutex_lock(&chan->lock);
00717       if (chan->pvt->answer)
00718          res = chan->pvt->answer(chan);
00719       ast_mutex_unlock(&chan->lock);
00720       ast_setstate(chan, AST_STATE_UP);
00721       if (chan->cdr)
00722          ast_cdr_answer(chan->cdr);
00723       return res;
00724       break;
00725    case AST_STATE_UP:
00726       if (chan->cdr)
00727          ast_cdr_answer(chan->cdr);
00728       break;
00729    }
00730    return 0;
00731 }

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 95 of file channel.c.

References ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), AST_SOFTHANGUP_SHUTDOWN, and channels.

00096 {
00097    struct ast_channel *c;
00098    shutting_down = 1;
00099    if (hangup) {
00100       ast_mutex_lock(&chlock);
00101       c = channels;
00102       while(c) {
00103          ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
00104          c = c->next;
00105       }
00106       ast_mutex_unlock(&chlock);
00107    }
00108 }

int ast_best_codec int  fmts  ) 
 

Pick the best codec.

Definition at line 223 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.

00224 {
00225    /* This just our opinion, expressed in code.  We are asked to choose
00226       the best codec to use, given no information */
00227    int x;
00228    static int prefs[] = 
00229    {
00230       /* Okay, ulaw is used by all telephony equipment, so start with it */
00231       AST_FORMAT_ULAW,
00232       /* Unless of course, you're a silly European, so then prefer ALAW */
00233       AST_FORMAT_ALAW,
00234       /* Okay, well, signed linear is easy to translate into other stuff */
00235       AST_FORMAT_SLINEAR,
00236       /* G.726 is standard ADPCM */
00237       AST_FORMAT_G726,
00238       /* ADPCM has great sound quality and is still pretty easy to translate */
00239       AST_FORMAT_ADPCM,
00240       /* Okay, we're down to vocoders now, so pick GSM because it's small and easier to
00241          translate and sounds pretty good */
00242       AST_FORMAT_GSM,
00243       /* iLBC is not too bad */
00244       AST_FORMAT_ILBC,
00245       /* Speex is free, but computationally more expensive than GSM */
00246       AST_FORMAT_SPEEX,
00247       /* Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough
00248          to use it */
00249       AST_FORMAT_LPC10,
00250       /* G.729a is faster than 723 and slightly less expensive */
00251       AST_FORMAT_G729A,
00252       /* Down to G.723.1 which is proprietary but at least designed for voice */
00253       AST_FORMAT_G723_1,
00254    };
00255    
00256    
00257    for (x=0;x<sizeof(prefs) / sizeof(prefs[0]); x++)
00258       if (fmts & prefs[x])
00259          return prefs[x];
00260    ast_log(LOG_WARNING, "Don't know any of 0x%x formats\n", fmts);
00261    return 0;
00262 }

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 1710 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().

01711 {
01712    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
01713       If the remote end does not answer within the timeout, then do NOT hang up, but 
01714       return anyway.  */
01715    int res = -1;
01716    /* Stop if we're a zombie or need a soft hangup */
01717    ast_mutex_lock(&chan->lock);
01718    if (!chan->zombie && !ast_check_hangup(chan)) 
01719       if (chan->pvt->call)
01720          res = chan->pvt->call(chan, addr, timeout);
01721    ast_mutex_unlock(&chan->lock);
01722    return res;
01723 }

void ast_cancel_shutdown void   ) 
 

Cancels an existing shutdown and returns to normal operation

Definition at line 124 of file channel.c.

00125 {
00126    shutting_down = 0;
00127 }

void ast_change_name struct ast_channel chan,
char *  newname
 

Definition at line 1919 of file channel.c.

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

01920 {
01921    char tmp[256];
01922    strncpy(tmp, chan->name, 256);
01923    strncpy(chan->name, newname, sizeof(chan->name) - 1);
01924    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid);
01925 }

struct ast_channel* ast_channel_alloc int  needalertpipe  ) 
 

Create a channel structure.

Returns NULL on failure to allocate

Definition at line 264 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_init, ast_mutex_lock, ast_mutex_unlock, AST_STATE_DOWN, ast_var_assign(), channels, defaultlanguage, free, LOG_WARNING, malloc, and sched_context_create().

00265 {
00266    struct ast_channel *tmp;
00267    struct ast_channel_pvt *pvt;
00268    int x;
00269    int flags;
00270    struct varshead *headp;        
00271            
00272    
00273    /* If shutting down, don't allocate any new channels */
00274    if (shutting_down)
00275       return NULL;
00276    ast_mutex_lock(&chlock);
00277    tmp = malloc(sizeof(struct ast_channel));
00278    if (tmp) {
00279       memset(tmp, 0, sizeof(struct ast_channel));
00280       pvt = malloc(sizeof(struct ast_channel_pvt));
00281       if (pvt) {
00282          memset(pvt, 0, sizeof(struct ast_channel_pvt));
00283          tmp->sched = sched_context_create();
00284          if (tmp->sched) {
00285             for (x=0;x<AST_MAX_FDS - 1;x++)
00286                tmp->fds[x] = -1;
00287             if (needqueue &&  
00288                pipe(pvt->alertpipe)) {
00289                ast_log(LOG_WARNING, "Alert pipe creation failed!\n");
00290                free(pvt);
00291                free(tmp);
00292                tmp = NULL;
00293                pvt = NULL;
00294             } else {
00295                /* Make sure we've got it done right if they don't */
00296                if (needqueue) {
00297                   flags = fcntl(pvt->alertpipe[0], F_GETFL);
00298                   fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK);
00299                   flags = fcntl(pvt->alertpipe[1], F_GETFL);
00300                   fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK);
00301                } else
00302                   pvt->alertpipe[0] = pvt->alertpipe[1] = -1;
00303 #ifdef ZAPTEL_OPTIMIZATIONS
00304                tmp->timingfd = open("/dev/zap/timer", O_RDWR);
00305 #else
00306                tmp->timingfd = -1;              
00307 #endif
00308                /* Always watch the alertpipe */
00309                tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0];
00310                /* And timing pipe */
00311                tmp->fds[AST_MAX_FDS-2] = tmp->timingfd;
00312                strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1);
00313                tmp->pvt = pvt;
00314                /* Initial state */
00315                tmp->_state = AST_STATE_DOWN;
00316                tmp->stack = -1;
00317                tmp->streamid = -1;
00318                tmp->appl = NULL;
00319                tmp->data = NULL;
00320                tmp->fin = 0;
00321                tmp->fout = 0;
00322                snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long)time(NULL), uniqueint++);
00323                headp=&tmp->varshead;
00324                ast_mutex_init(&tmp->lock);
00325                     AST_LIST_HEAD_INIT(headp);
00326                tmp->vars=ast_var_assign("tempvar","tempval");
00327                AST_LIST_INSERT_HEAD(headp,tmp->vars,entries);
00328                strncpy(tmp->context, "default", sizeof(tmp->context)-1);
00329                strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1);
00330                strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
00331                tmp->priority=1;
00332                tmp->amaflags = ast_default_amaflags;
00333                strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1);
00334                tmp->next = channels;
00335                channels= tmp;
00336             }
00337          } else {
00338             ast_log(LOG_WARNING, "Unable to create schedule context\n");
00339             free(tmp);
00340             tmp = NULL;
00341          }
00342       } else {
00343          ast_log(LOG_WARNING, "Out of memory\n");
00344          free(tmp);
00345          tmp = NULL;
00346       }
00347    } else 
00348       ast_log(LOG_WARNING, "Out of memory\n");
00349    ast_mutex_unlock(&chlock);
00350    return tmp;
00351 }

int ast_channel_bridge struct ast_channel c0,
struct ast_channel c1,
int  flags,
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 2182 of file channel.c.

References 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_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, EVENT_FLAG_CALL, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::name, option_verbose, VERBOSE_PREFIX_3, and ast_channel::zombie.

02183 {
02184    /* Copy voice back and forth between the two channels.  Give the peer
02185       the ability to transfer calls with '#<extension' syntax. */
02186    struct ast_channel *cs[3];
02187    int to = -1;
02188    struct ast_frame *f;
02189    struct ast_channel *who = NULL;
02190    int res;
02191    int nativefailed=0;
02192 
02193    /* Stop if we're a zombie or need a soft hangup */
02194    if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 
02195       return -1;
02196    if (c0->bridge) {
02197       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02198          c0->name, c0->bridge->name);
02199       return -1;
02200    }
02201    if (c1->bridge) {
02202       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02203          c1->name, c1->bridge->name);
02204       return -1;
02205    }
02206    
02207    /* Keep track of bridge */
02208    c0->bridge = c1;
02209    c1->bridge = c0;
02210    cs[0] = c0;
02211    cs[1] = c1;
02212    
02213    manager_event(EVENT_FLAG_CALL, "Link", 
02214          "Channel1: %s\r\n"
02215          "Channel2: %s\r\n",
02216          c0->name, c1->name);
02217 
02218    for (/* ever */;;) {
02219       /* Stop if we're a zombie or need a soft hangup */
02220       if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
02221          *fo = NULL;
02222          if (who) *rc = who;
02223          res = 0;
02224          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");
02225          break;
02226       }
02227       if (c0->pvt->bridge && 
02228          (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
02229             /* Looks like they share a bridge code */
02230          if (option_verbose > 2) 
02231             ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
02232          if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
02233             c0->bridge = NULL;
02234             c1->bridge = NULL;
02235             manager_event(EVENT_FLAG_CALL, "Unlink", 
02236                "Channel1: %s\r\n"
02237                "Channel2: %s\r\n",
02238                c0->name, c1->name);
02239             ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
02240             return 0;
02241          }
02242          /* If they return non-zero then continue on normally.  Let "-2" mean don't worry about
02243             my not wanting to bridge */
02244          if ((res != -2) && (res != -3))
02245             ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
02246          if (res != -3) nativefailed++;
02247       }
02248    
02249          
02250       if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat)) &&
02251          !(c0->generator || c1->generator))  {
02252          if (ast_channel_make_compatible(c0, c1)) {
02253             ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
02254             manager_event(EVENT_FLAG_CALL, "Unlink", 
02255                "Channel1: %s\r\n"
02256                "Channel2: %s\r\n",
02257                c0->name, c1->name);
02258             return -1;
02259          }
02260       }
02261       who = ast_waitfor_n(cs, 2, &to);
02262       if (!who) {
02263          ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 
02264          continue;
02265       }
02266       f = ast_read(who);
02267       if (!f) {
02268          *fo = NULL;
02269          *rc = who;
02270          res = 0;
02271          ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
02272          break;
02273       }
02274 
02275       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02276          *fo = f;
02277          *rc = who;
02278          res =  0;
02279          ast_log(LOG_DEBUG, "Got a FRAME_CONTROL frame on channel %s\n",who->name);
02280          break;
02281       }
02282       if ((f->frametype == AST_FRAME_VOICE) ||
02283          (f->frametype == AST_FRAME_TEXT) ||
02284          (f->frametype == AST_FRAME_VIDEO) || 
02285          (f->frametype == AST_FRAME_IMAGE) ||
02286          (f->frametype == AST_FRAME_DTMF)) {
02287          if ((f->frametype == AST_FRAME_DTMF) && 
02288             (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
02289             if ((who == c0)) {
02290                if  ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
02291                   *rc = c0;
02292                   *fo = f;
02293                   /* Take out of conference mode */
02294                   res = 0;
02295                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
02296                   break;
02297                } else 
02298                   goto tackygoto;
02299             } else
02300             if ((who == c1)) {
02301                if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
02302                   *rc = c1;
02303                   *fo = f;
02304                   res =  0;
02305                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
02306                   break;
02307                } else
02308                   goto tackygoto;
02309             }
02310          } else {
02311 #if 0
02312             ast_log(LOG_DEBUG, "Read from %s\n", who->name);
02313             if (who == last) 
02314                ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
02315             last = who;
02316 #endif
02317 tackygoto:
02318             /* Don't copy packets if there is a generator on either one, since they're
02319                not supposed to be listening anyway */
02320             if (who == c0) 
02321                ast_write(c1, f);
02322             else 
02323                ast_write(c0, f);
02324          }
02325          ast_frfree(f);
02326       } else
02327          ast_frfree(f);
02328       /* Swap who gets priority */
02329       cs[2] = cs[0];
02330       cs[0] = cs[1];
02331       cs[1] = cs[2];
02332    }
02333    c0->bridge = NULL;
02334    c1->bridge = NULL;
02335    manager_event(EVENT_FLAG_CALL, "Unlink", 
02336                "Channel1: %s\r\n"
02337                "Channel2: %s\r\n",
02338                c0->name, c1->name);
02339    ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name);
02340    return res;
02341 }

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 417 of file channel.c.

References ast_channel::deferdtmf.

00418 {
00419    int pre = 0;
00420    if (chan) {
00421       pre = chan->deferdtmf;
00422       chan->deferdtmf = 1;
00423    }
00424    return pre;
00425 }

void ast_channel_free struct ast_channel chan  ) 
 

Free a channel structure.

Definition at line 490 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, channels, 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_hangup().

00491 {
00492    struct ast_channel *last=NULL, *cur;
00493    int fd;
00494    struct ast_var_t *vardata;
00495    struct ast_frame *f, *fp;
00496    struct varshead *headp;
00497    char name[AST_CHANNEL_NAME];
00498    
00499    headp=&chan->varshead;
00500    
00501    ast_mutex_lock(&chlock);
00502    cur = channels;
00503    while(cur) {
00504       if (cur == chan) {
00505          if (last)
00506             last->next = cur->next;
00507          else
00508             channels = cur->next;
00509          break;
00510       }
00511       last = cur;
00512       cur = cur->next;
00513    }
00514    if (!cur)
00515       ast_log(LOG_WARNING, "Unable to find channel in list\n");
00516    if (chan->pvt->pvt)
00517       ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
00518 
00519    strncpy(name, chan->name, sizeof(name)-1);
00520    
00521    /* Stop monitoring */
00522    if (chan->monitor) {
00523       chan->monitor->stop( chan, 0 );
00524    }
00525 
00526    /* Free translatosr */
00527    if (chan->pvt->readtrans)
00528       ast_translator_free_path(chan->pvt->readtrans);
00529    if (chan->pvt->writetrans)
00530       ast_translator_free_path(chan->pvt->writetrans);
00531    if (chan->pbx) 
00532       ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
00533    if (chan->dnid)
00534       free(chan->dnid);
00535    if (chan->callerid)
00536       free(chan->callerid);   
00537    if (chan->ani)
00538       free(chan->ani);
00539    if (chan->rdnis)
00540       free(chan->rdnis);
00541    ast_mutex_destroy(&chan->lock);
00542    /* Close pipes if appropriate */
00543    if ((fd = chan->pvt->alertpipe[0]) > -1)
00544       close(fd);
00545    if ((fd = chan->pvt->alertpipe[1]) > -1)
00546       close(fd);
00547    if ((fd = chan->timingfd) > -1)
00548       close(fd);
00549    f = chan->pvt->readq;
00550    chan->pvt->readq = NULL;
00551    while(f) {
00552       fp = f;
00553       f = f->next;
00554       ast_frfree(fp);
00555    }
00556    
00557    /* loop over the variables list, freeing all data and deleting list items */
00558    /* no need to lock the list, as the channel is already locked */
00559    
00560    while (!AST_LIST_EMPTY(headp)) {           /* List Deletion. */
00561                vardata = AST_LIST_FIRST(headp);
00562                AST_LIST_REMOVE_HEAD(headp, entries);
00563 //             printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata));
00564                ast_var_delete(vardata);
00565    }
00566                                                     
00567 
00568    free(chan->pvt);
00569    chan->pvt = NULL;
00570    free(chan);
00571    ast_mutex_unlock(&chlock);
00572 
00573    ast_device_state_changed(name);
00574 }

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 1847 of file channel.c.

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

Referenced by ast_channel_bridge().

01848 {
01849    int peerf;
01850    int chanf;
01851    int res;
01852    peerf = peer->nativeformats;
01853    chanf = chan->nativeformats;
01854    res = ast_translator_best_choice(&peerf, &chanf);
01855    if (res < 0) {
01856       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
01857       return -1;
01858    }
01859    /* Set read format on channel */
01860    res = ast_set_read_format(chan, peerf);
01861    if (res < 0) {
01862       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
01863       return -1;
01864    }
01865    /* Set write format on peer channel */
01866    res = ast_set_write_format(peer, peerf);
01867    if (res < 0) {
01868       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
01869       return -1;
01870    }
01871    /* Now we go the other way */
01872    peerf = peer->nativeformats;
01873    chanf = chan->nativeformats;
01874    res = ast_translator_best_choice(&chanf, &peerf);
01875    if (res < 0) {
01876       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
01877       return -1;
01878    }
01879    /* Set writeformat on channel */
01880    res = ast_set_write_format(chan, chanf);
01881    if (res < 0) {
01882       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
01883       return -1;
01884    }
01885    /* Set read format on peer channel */
01886    res = ast_set_read_format(peer, chanf);
01887    if (res < 0) {
01888       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
01889       return -1;
01890    }
01891    return 0;
01892 }

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 1894 of file channel.c.

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

01895 {
01896    struct ast_frame null = { AST_FRAME_NULL, };
01897    ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
01898       clone->name, original->name);
01899    if (original->masq) {
01900       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
01901          original->masq->name, original->name);
01902       return -1;
01903    }
01904    if (clone->masqr) {
01905       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
01906          clone->name, clone->masqr->name);
01907       return -1;
01908    }
01909    original->masq = clone;
01910    clone->masqr = original;
01911    /* XXX can't really hold the lock here, but at the same time, it' s
01912       not really safe not to XXX */
01913    ast_queue_frame(original, &null, 0);
01914    ast_queue_frame(clone, &null, 0);
01915    ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
01916    return 0;
01917 }

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

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 146 of file channel.c.

References ast_channel_register_ex(), description(), and type.

00148 {
00149     return ast_channel_register_ex(type, description, capabilities, requester, NULL);
00150 }

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)
 

Definition at line 152 of file channel.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), backends, description(), LOG_DEBUG, LOG_WARNING, malloc, option_debug, option_verbose, type, and VERBOSE_PREFIX_2.

Referenced by ast_channel_register().

00155 {
00156    struct chanlist *chan, *last=NULL;
00157    if (ast_mutex_lock(&chlock)) {
00158       ast_log(LOG_WARNING, "Unable to lock channel list\n");
00159       return -1;
00160    }
00161    chan = backends;
00162    while(chan) {
00163       if (!strcasecmp(type, chan->type)) {
00164          ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
00165          ast_mutex_unlock(&chlock);
00166          return -1;
00167       }
00168       last = chan;
00169       chan = chan->next;
00170    }
00171    chan = malloc(sizeof(struct chanlist));
00172    if (!chan) {
00173       ast_log(LOG_WARNING, "Out of memory\n");
00174       ast_mutex_unlock(&chlock);
00175       return -1;
00176    }
00177    strncpy(chan->type, type, sizeof(chan->type)-1);
00178    strncpy(chan->description, description, sizeof(chan->description)-1);
00179    chan->capabilities = capabilities;
00180    chan->requester = requester;
00181    chan->devicestate = devicestate;
00182    chan->next = NULL;
00183    if (last)
00184       last->next = chan;
00185    else
00186       backends = chan;
00187    if (option_debug)
00188       ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
00189    else if (option_verbose > 1)
00190       ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
00191    ast_mutex_unlock(&chlock);
00192    return 0;
00193 }

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 1833 of file channel.c.

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

01834 {
01835    if (chan->pvt->send_html)
01836       return chan->pvt->send_html(chan, subclass, data, datalen);
01837    return -1;
01838 }

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 1840 of file channel.c.

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

01841 {
01842    if (chan->pvt->send_html)
01843       return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
01844    return -1;
01845 }

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 2343 of file channel.c.

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

02344 {
02345    int res;
02346    if (chan->pvt->setoption) {
02347       res = chan->pvt->setoption(chan, option, data, datalen);
02348       if (res < 0)
02349          return res;
02350    } else {
02351       errno = ENOSYS;
02352       return -1;
02353    }
02354    if (block) {
02355       /* XXX Implement blocking -- just wait for our option frame reply, discarding
02356          intermediate packets. XXX */
02357       ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
02358       return -1;
02359    }
02360    return 0;
02361 }

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 134 of file channel.c.

References ast_channel::whentohangup.

00135 {
00136 time_t   myt;
00137 
00138    time(&myt);
00139         if (offset)
00140      chan->whentohangup = myt + offset;
00141         else
00142           chan->whentohangup = 0;
00143    return;
00144 }

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 1826 of file channel.c.

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

01827 {
01828    if (chan->pvt->send_html)
01829       return 1;
01830    return 0;
01831 }

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 427 of file channel.c.

References ast_channel::deferdtmf.

00428 {
00429    if (chan)
00430       chan->deferdtmf = 0;
00431 }

void ast_channel_unregister char *  type  ) 
 

Unregister a channel class.

Definition at line 678 of file channel.c.

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

00679 {
00680    struct chanlist *chan, *last=NULL;
00681    if (option_debug)
00682       ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type);
00683    if (ast_mutex_lock(&chlock)) {
00684       ast_log(LOG_WARNING, "Unable to lock channel list\n");
00685       return;
00686    }
00687    if (option_verbose > 1)
00688       ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type);
00689 
00690    chan = backends;
00691    while(chan) {
00692       if (!strcasecmp(chan->type, type)) {
00693          if (last)
00694             last->next = chan->next;
00695          else
00696             backends = backends->next;
00697          free(chan);
00698          ast_mutex_unlock(&chlock);
00699          return;
00700       }
00701       last = chan;
00702       chan = chan->next;
00703    }
00704    ast_mutex_unlock(&chlock);
00705 }

struct ast_channel* ast_channel_walk 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.

Definition at line 433 of file channel.c.

References ast_mutex_lock, ast_mutex_unlock, and channels.

Referenced by ast_parse_device_state().

00434 {
00435    struct ast_channel *l, *ret=NULL;
00436    ast_mutex_lock(&chlock);
00437    l = channels;
00438    if (!prev) {
00439       ast_mutex_unlock(&chlock);
00440       return l;
00441    }
00442    while(l) {
00443       if (l == prev)
00444          ret = l->next;
00445       l = l->next;
00446    }
00447    ast_mutex_unlock(&chlock);
00448    return ret;
00449    
00450 }

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 69 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().

00070 {
00071 time_t   myt;
00072 
00073      /* if soft hangup flag, return true */
00074    if (chan->_softhangup) return 1;
00075      /* if no private structure, return true */
00076    if (!chan->pvt->pvt) return 1;
00077      /* if no hangup scheduled, just return here */
00078    if (!chan->whentohangup) return 0;
00079    time(&myt); /* get current time */
00080      /* return, if not yet */
00081    if (chan->whentohangup > myt) return 0;
00082    chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
00083    return 1;
00084 }

void ast_deactivate_generator struct ast_channel chan  ) 
 

Deactive an active generator

Definition at line 733 of file channel.c.

References ast_channel::generator, ast_channel::generatordata, ast_generator::release, and ast_channel::writeinterrupt.

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

00734 {
00735    if (chan->generatordata) {
00736       chan->generator->release(chan, chan->generatordata);
00737       chan->generatordata = NULL;
00738       chan->generator = NULL;
00739       chan->writeinterrupt = 0;
00740    }
00741 }

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 1671 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, and LOG_WARNING.

01672 {
01673    char tech[AST_MAX_EXTENSION] = "";
01674    char *number;
01675    struct chanlist *chanls;
01676    int res = 0;
01677    
01678    strncpy(tech, device, sizeof(tech)-1);
01679    number = strchr(tech, '/');
01680    if (!number) {
01681        return AST_DEVICE_INVALID;
01682    }
01683    *number = 0;
01684    number++;
01685       
01686    if (ast_mutex_lock(&chlock)) {
01687       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01688       return -1;
01689    }
01690    chanls = backends;
01691    while(chanls) {
01692       if (!strcasecmp(tech, chanls->type)) {
01693          ast_mutex_unlock(&chlock);
01694          if (!chanls->devicestate) 
01695             return ast_parse_device_state(device);
01696          else {
01697             res = chanls->devicestate(number);
01698             if (res == AST_DEVICE_UNKNOWN)
01699                return ast_parse_device_state(device);
01700             else
01701                return res;
01702          }
01703       }
01704       chanls = chanls->next;
01705    }
01706    ast_mutex_unlock(&chlock);
01707    return AST_DEVICE_INVALID;
01708 }

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 614 of file channel.c.

References ast_cdr_end(), ast_cdr_free(), ast_cdr_post(), ast_channel_free(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_stopstream(), 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::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, and ast_channel::zombie.

Referenced by __ast_request_and_dial(), and ast_pbx_run().

00615 {
00616    int res = 0;
00617    /* Don't actually hang up a channel that will masquerade as someone else, or
00618       if someone is going to masquerade as us */
00619    ast_mutex_lock(&chan->lock);
00620    if (chan->masq) {
00621       if (ast_do_masquerade(chan)) 
00622          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
00623    }
00624 
00625    if (chan->masq) {
00626       ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
00627       ast_mutex_unlock(&chan->lock);
00628       return 0;
00629    }
00630    /* If this channel is one which will be masqueraded into something, 
00631       mark it as a zombie already, so we know to free it later */
00632    if (chan->masqr) {
00633       ast_mutex_unlock(&chan->lock);
00634       chan->zombie=1;
00635       return 0;
00636    }
00637    free_translation(chan);
00638    if (chan->stream)
00639       ast_stopstream(chan);
00640    if (chan->sched)
00641       sched_context_destroy(chan->sched);
00642    /* Clear any tone stuff remaining */
00643    if (chan->generatordata)
00644       chan->generator->release(chan, chan->generatordata);
00645    chan->generatordata = NULL;
00646    chan->generator = NULL;
00647    if (chan->cdr) {
00648       /* End the CDR if it hasn't already */
00649       ast_cdr_end(chan->cdr);
00650       /* Post and Free the CDR */
00651       ast_cdr_post(chan->cdr);
00652       ast_cdr_free(chan->cdr);
00653    }
00654    if (chan->blocking) {
00655       ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
00656                "is blocked by thread %ld in procedure %s!  Expect a failure\n",
00657                (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc);
00658       CRASH;
00659    }
00660    if (!chan->zombie) {
00661       if (option_debug)
00662          ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
00663       if (chan->pvt->hangup)
00664          res = chan->pvt->hangup(chan);
00665    } else
00666       if (option_debug)
00667          ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
00668          
00669    ast_mutex_unlock(&chan->lock);
00670    manager_event(EVENT_FLAG_CALL, "Hangup", 
00671          "Channel: %s\r\n"
00672          "Uniqueid: %s\r\n",
00673          chan->name, chan->uniqueid);
00674    ast_channel_free(chan);
00675    return res;
00676 }

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 1174 of file channel.c.

References ast_check_hangup(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_get_indication_tone(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_playtones_start(), ast_playtones_stop(), ast_channel::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.

01175 {
01176    int res = -1;
01177    /* Stop if we're a zombie or need a soft hangup */
01178    if (chan->zombie || ast_check_hangup(chan)) 
01179       return -1;
01180    ast_mutex_lock(&chan->lock);
01181    if (chan->pvt->indicate)
01182       res = chan->pvt->indicate(chan, condition);
01183    ast_mutex_unlock(&chan->lock);
01184    if (!chan->pvt->indicate || res) {
01185       /*
01186        * Device does not support (that) indication, lets fake
01187        * it by doing our own tone generation. (PM2002)
01188        */
01189       if (condition >= 0) {
01190          const struct tone_zone_sound *ts = NULL;
01191          switch (condition) {
01192           case AST_CONTROL_RINGING:
01193             ts = ast_get_indication_tone(chan->zone, "ring");
01194             break;
01195           case AST_CONTROL_BUSY:
01196             ts = ast_get_indication_tone(chan->zone, "busy");
01197             break;
01198           case AST_CONTROL_CONGESTION:
01199             ts = ast_get_indication_tone(chan->zone, "congestion");
01200             break;
01201          }
01202          if (ts && ts->data[0]) {
01203             ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
01204             ast_playtones_start(chan,0,ts->data, 1);
01205             res = 0;
01206          } else if (condition == AST_CONTROL_PROGRESS) {
01207             /* ast_playtones_stop(chan); */
01208          } else {
01209             /* not handled */
01210             ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
01211             res = -1;
01212          }
01213       }
01214       else ast_playtones_stop(chan);
01215    }
01216    return res;
01217 }

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 1652 of file channel.c.

References AST_CHANNEL_NAME, ast_channel_walk(), AST_DEVICE_INUSE, AST_DEVICE_UNKNOWN, and ast_channel::name.

Referenced by ast_device_state().

01653 {
01654    char name[AST_CHANNEL_NAME] = "";
01655    char *cut;
01656    struct ast_channel *chan;
01657 
01658    chan = ast_channel_walk(NULL);
01659    while (chan) {
01660       strncpy(name, chan->name, sizeof(name)-1);
01661       cut = strchr(name,'-');
01662       if (cut)
01663               *cut = 0;
01664       if (!strcmp(name, device))
01665               return AST_DEVICE_INUSE;
01666       chan = ast_channel_walk(chan);
01667    }
01668    return AST_DEVICE_UNKNOWN;
01669 }

int ast_prod struct ast_channel chan  ) 
 

Definition at line 1306 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().

01307 {
01308    struct ast_frame a = { AST_FRAME_VOICE };
01309    char nothing[128];
01310    /* Send an empty audio frame to get things moving */
01311    if (chan->_state != AST_STATE_UP) {
01312       ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
01313       a.subclass = chan->pvt->rawwriteformat;
01314       a.data = nothing + AST_FRIENDLY_OFFSET;
01315       if (ast_write(chan, &a))
01316          ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name);
01317    }
01318    return 0;
01319 }

int ast_queue_control struct ast_channel chan,
int  control,
int  lock
 

Definition at line 410 of file channel.c.

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

00411 {
00412    struct ast_frame f = { AST_FRAME_CONTROL, };
00413    f.subclass = control;
00414    return ast_queue_frame(chan, &f, lock);
00415 }

int ast_queue_frame struct ast_channel chan,
struct ast_frame f,
int  lock
 

Queue an outgoing frame, locking if necessary

Definition at line 353 of file channel.c.

References ast_channel_pvt::alertpipe, 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_channel::pvt, and ast_channel_pvt::readq.

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

00354 {
00355    struct ast_frame *f;
00356    struct ast_frame *prev, *cur;
00357    int blah = 1;
00358    int qlen = 0;
00359    /* Build us a copy and free the original one */
00360    f = ast_frdup(fin);
00361    if (!f) {
00362       ast_log(LOG_WARNING, "Unable to duplicate frame\n");
00363       return -1;
00364    }
00365    if (lock)
00366       ast_mutex_lock(&chan->lock);
00367    prev = NULL;
00368    cur = chan->pvt->readq;
00369    while(cur) {
00370       prev = cur;
00371       cur = cur->next;
00372       qlen++;
00373    }
00374    /* Allow up to 96 voice frames outstanding, and up to 128 total frames */
00375    if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen  > 128)) {
00376       if (fin->frametype != AST_FRAME_VOICE) {
00377          ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
00378          CRASH;
00379       } else {
00380          ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name);
00381          ast_frfree(f);
00382          if (lock)
00383             ast_mutex_unlock(&chan->lock);
00384          return 0;
00385       }
00386    }
00387    if (prev)
00388       prev->next = f;
00389    else
00390       chan->pvt->readq = f;
00391    if (chan->pvt->alertpipe[1] > -1) {
00392       if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah))
00393          ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
00394             chan->name, f->frametype, f->subclass, qlen, strerror(errno));
00395    } else if (chan->blocking) {
00396       pthread_kill(chan->blocker, SIGURG);
00397    }
00398    if (lock)
00399       ast_mutex_unlock(&chan->lock);
00400    return 0;
00401 }

int ast_queue_hangup struct ast_channel chan,
int  lock
 

Definition at line 403 of file channel.c.

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

00404 {
00405    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
00406    chan->_softhangup |= AST_SOFTHANGUP_DEV;
00407    return ast_queue_frame(chan, &f, lock);
00408 }

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 994 of file channel.c.

References ast_channel::_softhangup, ast_channel_pvt::alertpipe, ast_cdr_answer(), ast_cdr_end(), ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, ast_deactivate_generator(), 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_SOFTHANGUP_DEV, AST_STATE_UP, ast_translate(), ast_writestream(), ast_channel::blocker, ast_channel::cdr, 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, 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_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().

00995 {
00996    struct ast_frame *f = NULL;
00997    int blah;
00998 #ifdef ZAPTEL_OPTIMIZATIONS
00999    int (*func)(void *);
01000    void *data;
01001 #endif
01002    static struct ast_frame null_frame = 
01003    {
01004       AST_FRAME_NULL,
01005    };
01006    
01007    ast_mutex_lock(&chan->lock);
01008    if (chan->masq) {
01009       if (ast_do_masquerade(chan)) {
01010          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01011          f = NULL;
01012       } else
01013          f =  &null_frame;
01014       ast_mutex_unlock(&chan->lock);
01015       return f;
01016    }
01017 
01018    /* Stop if we're a zombie or need a soft hangup */
01019    if (chan->zombie || ast_check_hangup(chan)) {
01020       if (chan->generator)
01021          ast_deactivate_generator(chan);
01022       ast_mutex_unlock(&chan->lock);
01023       return NULL;
01024    }
01025 
01026    if (!chan->deferdtmf && strlen(chan->dtmfq)) {
01027       /* We have DTMF that has been deferred.  Return it now */
01028       chan->dtmff.frametype = AST_FRAME_DTMF;
01029       chan->dtmff.subclass = chan->dtmfq[0];
01030       /* Drop first digit */
01031       memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
01032       ast_mutex_unlock(&chan->lock);
01033       return &chan->dtmff;
01034    }
01035    
01036    /* Read and ignore anything on the alertpipe, but read only
01037       one sizeof(blah) per frame that we send from it */
01038    if (chan->pvt->alertpipe[0] > -1) {
01039       read(chan->pvt->alertpipe[0], &blah, sizeof(blah));
01040    }
01041 #ifdef ZAPTEL_OPTIMIZATIONS
01042    if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) {
01043       chan->exception = 0;
01044       blah = -1;
01045       ioctl(chan->timingfd, ZT_TIMERACK, &blah);
01046       func = chan->timingfunc;
01047       data = chan->timingdata;
01048       ast_mutex_unlock(&chan->lock);
01049       if (func) {
01050 #if 0
01051          ast_log(LOG_DEBUG, "Calling private function\n");
01052 #endif         
01053          func(data);
01054       } else {
01055          blah = 0;
01056          ast_mutex_lock(&chan->lock);
01057          ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
01058          chan->timingdata = NULL;
01059          ast_mutex_unlock(&chan->lock);
01060       }
01061       f =  &null_frame;
01062       return f;
01063    }
01064 #endif
01065    /* Check for pending read queue */
01066    if (chan->pvt->readq) {
01067       f = chan->pvt->readq;
01068       chan->pvt->readq = f->next;
01069       /* Interpret hangup and return NULL */
01070       if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
01071          ast_frfree(f);
01072          f = NULL;
01073       }
01074    } else {
01075       chan->blocker = pthread_self();
01076       if (chan->exception) {
01077          if (chan->pvt->exception) 
01078             f = chan->pvt->exception(chan);
01079          else {
01080             ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
01081             f = &null_frame;
01082          }
01083          /* Clear the exception flag */
01084          chan->exception = 0;
01085       } else
01086       if (chan->pvt->read)
01087          f = chan->pvt->read(chan);
01088       else
01089          ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
01090    }
01091 
01092 
01093    if (f && (f->frametype == AST_FRAME_VOICE)) {
01094       if (!(f->subclass & chan->nativeformats)) {
01095          /* This frame can't be from the current native formats -- drop it on the
01096             floor */
01097          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));
01098          ast_frfree(f);
01099          f = &null_frame;
01100       } else {
01101          if (chan->monitor && chan->monitor->read_stream ) {
01102 #ifndef MONITOR_CONSTANT_DELAY
01103             int jump = chan->outsmpl - chan->insmpl - 2 * f->samples;
01104             if (jump >= 0) {
01105                if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01106                   ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01107                chan->insmpl += jump + 2 * f->samples;
01108             } else
01109                chan->insmpl+= f->samples;
01110 #else
01111             int jump = chan->outsmpl - chan->insmpl;
01112             if (jump - MONITOR_DELAY >= 0) {
01113                if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01114                   ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01115                chan->insmpl += jump;
01116             } else
01117                chan->insmpl += f->samples;
01118 #endif
01119             if (ast_writestream(chan->monitor->read_stream, f) < 0)
01120                ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
01121          }
01122          if (chan->pvt->readtrans) {
01123             f = ast_translate(chan->pvt->readtrans, f, 1);
01124             if (!f)
01125                f = &null_frame;
01126          }
01127       }
01128    }
01129 
01130    /* Make sure we always return NULL in the future */
01131    if (!f) {
01132       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01133       if (chan->generator)
01134          ast_deactivate_generator(chan);
01135       /* End the CDR if appropriate */
01136       if (chan->cdr)
01137          ast_cdr_end(chan->cdr);
01138    } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
01139       if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
01140          chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
01141       else
01142          ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
01143       f = &null_frame;
01144    } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
01145       /* Answer the CDR */
01146       ast_setstate(chan, AST_STATE_UP);
01147       ast_cdr_answer(chan->cdr);
01148    } 
01149    ast_mutex_unlock(&chan->lock);
01150 
01151    /* Run any generator sitting on the line */
01152    if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
01153       /* Mask generator data temporarily */
01154       void *tmp;
01155       int res;
01156       tmp = chan->generatordata;
01157       chan->generatordata = NULL;
01158       res = chan->generator->generate(chan, tmp, f->datalen, f->samples);
01159       chan->generatordata = tmp;
01160       if (res) {
01161          ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
01162          ast_deactivate_generator(chan);
01163       }
01164    }
01165    if (chan->fin & 0x80000000)
01166       ast_frame_dump(chan->name, f, "<<");
01167    if ((chan->fin & 0x7fffffff) == 0x7fffffff)
01168       chan->fin &= 0x80000000;
01169    else
01170       chan->fin++;
01171    return f;
01172 }

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 1745 of file channel.c.

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

Referenced by ast_app_getdata().

01746 {
01747    int pos=0;
01748    int to = ftimeout;
01749    char d;
01750    /* XXX Merge with full version? XXX */
01751    /* Stop if we're a zombie or need a soft hangup */
01752    if (c->zombie || ast_check_hangup(c)) 
01753       return -1;
01754    if (!len)
01755       return -1;
01756    do {
01757       if (c->stream) {
01758          d = ast_waitstream(c, AST_DIGIT_ANY);
01759          ast_stopstream(c);
01760          usleep(1000);
01761          if (!d)
01762             d = ast_waitfordigit(c, to);
01763       } else {
01764          d = ast_waitfordigit(c, to);
01765       }
01766       if (d < 0)
01767          return -1;
01768       if (d == 0) {
01769          s[pos]='\0';
01770          return 1;
01771       }
01772       if (!strchr(enders, d))
01773          s[pos++] = d;
01774       if (strchr(enders, d) || (pos >= len)) {
01775          s[pos]='\0';
01776          return 0;
01777       }
01778       to = timeout;
01779    } while(1);
01780    /* Never reached */
01781    return 0;
01782 }

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 1784 of file channel.c.

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

Referenced by ast_app_getdata_full().

01785 {
01786    int pos=0;
01787    int to = ftimeout;
01788    char d;
01789    /* Stop if we're a zombie or need a soft hangup */
01790    if (c->zombie || ast_check_hangup(c)) 
01791       return -1;
01792    if (!len)
01793       return -1;
01794    do {
01795       if (c->stream) {
01796          d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
01797          ast_stopstream(c);
01798          usleep(1000);
01799          if (!d)
01800             d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
01801       } else {
01802          d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
01803       }
01804       if (d < 0)
01805          return -1;
01806       if (d == 0) {
01807          s[pos]='\0';
01808          return 1;
01809       }
01810       if (d == 1) {
01811          s[pos]='\0';
01812          return 2;
01813       }
01814       if (!strchr(enders, d))
01815          s[pos++] = d;
01816       if (strchr(enders, d) || (pos >= len)) {
01817          s[pos]='\0';
01818          return 0;
01819       }
01820       to = timeout;
01821    } while(1);
01822    /* Never reached */
01823    return 0;
01824 }

int ast_recvchar struct ast_channel chan,
int  timeout
 

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 1219 of file channel.c.

References ast_check_hangup(), AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_frfree(), ast_read(), and ast_waitfor().

01220 {
01221    int res,ourto,c;
01222    struct ast_frame *f;
01223    
01224    ourto = timeout;
01225    for(;;)
01226       {
01227       if (ast_check_hangup(chan)) return -1;
01228       res = ast_waitfor(chan,ourto);
01229       if (res <= 0) /* if timeout */
01230          {
01231          return 0;
01232          }
01233       ourto = res;
01234       f = ast_read(chan);
01235       if (f == NULL) return -1; /* if hangup */
01236       if ((f->frametype == AST_FRAME_CONTROL) &&
01237           (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
01238       if (f->frametype == AST_FRAME_TEXT)  /* if a text frame */
01239          {
01240          c = *((char *)f->data);  /* get the data */
01241          ast_frfree(f);
01242          return(c);
01243          }
01244       ast_frfree(f);
01245    }
01246 }

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 1607 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, EVENT_FLAG_CALL, LOG_WARNING, manager_event(), ast_channel::name, ast_channel::next, type, ast_channel::type, and ast_channel::uniqueid.

Referenced by __ast_request_and_dial().

01608 {
01609    struct chanlist *chan;
01610    struct ast_channel *c = NULL;
01611    int capabilities;
01612    int fmt;
01613    int res;
01614    if (ast_mutex_lock(&chlock)) {
01615       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01616       return NULL;
01617    }
01618    chan = backends;
01619    while(chan) {
01620       if (!strcasecmp(type, chan->type)) {
01621          capabilities = chan->capabilities;
01622          fmt = format;
01623          res = ast_translator_best_choice(&fmt, &capabilities);
01624          if (res < 0) {
01625             ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
01626             ast_mutex_unlock(&chlock);
01627             return NULL;
01628          }
01629          ast_mutex_unlock(&chlock);
01630          if (chan->requester)
01631             c = chan->requester(type, capabilities, data);
01632          if (c) {
01633             if (c->_state == AST_STATE_DOWN) {
01634                manager_event(EVENT_FLAG_CALL, "Newchannel",
01635                "Channel: %s\r\n"
01636                "State: %s\r\n"
01637                "Callerid: %s\r\n"
01638                "Uniqueid: %s\r\n",
01639                c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid);
01640             }
01641          }
01642          return c;
01643       }
01644       chan = chan->next;
01645    }
01646    if (!chan)
01647       ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
01648    ast_mutex_unlock(&chlock);
01649    return c;
01650 }

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 1602 of file channel.c.

References __ast_request_and_dial(), and type.

01603 {
01604    return __ast_request_and_dial(type, format, data, timeout, outstate, callerid, NULL);
01605 }

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 473 of file channel.c.

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

00474 {
00475    struct ast_frame *f;
00476    while(ms > 0) {
00477       ms = ast_waitfor(chan, ms);
00478       if (ms <0)
00479          return -1;
00480       if (ms > 0) {
00481          f = ast_read(chan);
00482          if (!f)
00483             return -1;
00484          ast_frfree(f);
00485       }
00486    }
00487    return 0;
00488 }

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.

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 452 of file channel.c.

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

00454 {
00455    struct ast_frame *f;
00456 
00457    while(ms > 0) {
00458       if( cond && ((*cond)(data) == 0 ) )
00459          return 0;
00460       ms = ast_waitfor(chan, ms);
00461       if (ms <0)
00462          return -1;
00463       if (ms > 0) {
00464          f = ast_read(chan);
00465          if (!f)
00466             return -1;
00467          ast_frfree(f);
00468       }
00469    }
00470    return 0;
00471 }

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 1248 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.

01249 {
01250    int res = 0;
01251    /* Stop if we're a zombie or need a soft hangup */
01252    if (chan->zombie || ast_check_hangup(chan)) 
01253       return -1;
01254    CHECK_BLOCKING(chan);
01255    if (chan->pvt->send_text)
01256       res = chan->pvt->send_text(chan, text);
01257    chan->blocking = 0;
01258    return res;
01259 }

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

Definition at line 2131 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().

02132 {
02133    if (chan->callerid)
02134       free(chan->callerid);
02135    if (anitoo && chan->ani)
02136       free(chan->ani);
02137    if (callerid) {
02138       chan->callerid = strdup(callerid);
02139       if (anitoo)
02140          chan->ani = strdup(callerid);
02141    } else {
02142       chan->callerid = NULL;
02143       if (anitoo)
02144          chan->ani = NULL;
02145    }
02146    if (chan->cdr)
02147       ast_cdr_setcid(chan->cdr, chan);
02148    manager_event(EVENT_FLAG_CALL, "Newcallerid", 
02149             "Channel: %s\r\n"
02150             "Callerid: %s\r\n"
02151             "Uniqueid: %s\r\n",
02152             chan->name, chan->callerid ? 
02153             chan->callerid : "<Unknown>",
02154             chan->uniqueid);
02155 }

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 1470 of file channel.c.

References ast_getformatname(), ast_log(), ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), 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(), and ast_channel_make_compatible().

01471 {
01472    int fmt;
01473    int native;
01474    int res;
01475    
01476    native = chan->nativeformats;
01477    fmt = fmts;
01478    /* Find a translation path from the native read format to one of the user's read formats */
01479    res = ast_translator_best_choice(&fmt, &native);
01480    if (res < 0) {
01481       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01482          ast_getformatname(chan->nativeformats), ast_getformatname(fmts));
01483       return -1;
01484    }
01485    
01486    /* Now we have a good choice for both.  We'll write using our native format. */
01487    chan->pvt->rawreadformat = native;
01488    /* User perspective is fmt */
01489    chan->readformat = fmt;
01490    /* Free any read translation we have right now */
01491    if (chan->pvt->readtrans)
01492       ast_translator_free_path(chan->pvt->readtrans);
01493    /* Build a translation path from the raw read format to the user reading format */
01494    chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
01495    if (option_debug)
01496       ast_log(LOG_DEBUG, "Set channel %s to read format %s\n", 
01497          chan->name, ast_getformatname(chan->readformat));
01498    return 0;
01499 }

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 1440 of file channel.c.

References ast_getformatname(), ast_log(), ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), 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_openstream(), and ast_stopstream().

01441 {
01442    int fmt;
01443    int native;
01444    int res;
01445    
01446    native = chan->nativeformats;
01447    fmt = fmts;
01448    
01449    res = ast_translator_best_choice(&native, &fmt);
01450    if (res < 0) {
01451       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01452          ast_getformatname(fmts), ast_getformatname(chan->nativeformats));
01453       return -1;
01454    }
01455    
01456    /* Now we have a good choice for both.  We'll write using our native format. */
01457    chan->pvt->rawwriteformat = native;
01458    /* User perspective is fmt */
01459    chan->writeformat = fmt;
01460    /* Free any write translation we have right now */
01461    if (chan->pvt->writetrans)
01462       ast_translator_free_path(chan->pvt->writetrans);
01463    /* Build a translation path from the user write format to the raw writing format */
01464    chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
01465    if (option_debug)
01466       ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat));
01467    return 0;
01468 }

int ast_setstate struct ast_channel chan,
int  state
 

Change the state of a channel

Definition at line 2157 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(), and ast_read().

02158 {
02159    if (chan->_state != state) {
02160       int oldstate = chan->_state;
02161       chan->_state = state;
02162       if (oldstate == AST_STATE_DOWN) {
02163          ast_device_state_changed(chan->name);
02164          manager_event(EVENT_FLAG_CALL, "Newchannel",
02165          "Channel: %s\r\n"
02166          "State: %s\r\n"
02167          "Callerid: %s\r\n"
02168          "Uniqueid: %s\r\n",
02169          chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02170       } else {
02171          manager_event(EVENT_FLAG_CALL, "Newstate", 
02172             "Channel: %s\r\n"
02173             "State: %s\r\n"
02174             "Callerid: %s\r\n"
02175             "Uniqueid: %s\r\n",
02176             chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02177       }
02178    }
02179    return 0;
02180 }

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

Definition at line 947 of file channel.c.

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

Referenced by ast_closestream().

00948 {
00949    int res = -1;
00950 #ifdef ZAPTEL_OPTIMIZATIONS
00951    if (c->timingfd > -1) {
00952       if (!func) {
00953          samples = 0;
00954          data = 0;
00955       }
00956       ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples);
00957       res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples);
00958       c->timingfunc = func;
00959       c->timingdata = data;
00960    }
00961 #endif   
00962    return res;
00963 }

int ast_shutting_down void   ) 
 

Returns non-zero if Asterisk is being shut down

Definition at line 129 of file channel.c.

00130 {
00131    return shutting_down;
00132 }

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 591 of file channel.c.

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

Referenced by ast_begin_shutdown().

00592 {
00593    int res;
00594    ast_mutex_lock(&chan->lock);
00595    res = ast_softhangup_nolock(chan, cause);
00596    ast_mutex_unlock(&chan->lock);
00597    return res;
00598 }

int ast_softhangup_nolock struct ast_channel chan,
int  cause
 

Definition at line 576 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_softhangup().

00577 {
00578    int res = 0;
00579    struct ast_frame f = { AST_FRAME_NULL };
00580    if (option_debug)
00581       ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name);
00582    /* Inform channel driver that we need to be hung up, if it cares */
00583    chan->_softhangup |= cause;
00584    ast_queue_frame(chan, &f, 0);
00585    /* Interrupt any select call or such */
00586    if (chan->blocking)
00587       pthread_kill(chan->blocker, SIGURG);
00588    return res;
00589 }

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 195 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().

00196 {
00197    /* XXX Not reentrant XXX */
00198    static char localtmp[256];
00199    switch(state) {
00200    case AST_STATE_DOWN:
00201       return "Down";
00202    case AST_STATE_RESERVED:
00203       return "Rsrvd";
00204    case AST_STATE_OFFHOOK:
00205       return "OffHook";
00206    case AST_STATE_DIALING:
00207       return "Dialing";
00208    case AST_STATE_RING:
00209       return "Ring";
00210    case AST_STATE_RINGING:
00211       return "Ringing";
00212    case AST_STATE_UP:
00213       return "Up";
00214    case AST_STATE_BUSY:
00215       return "Busy";
00216    default:
00217       snprintf(localtmp, sizeof(localtmp), "Unknown (%d)\n", state);
00218       return localtmp;
00219    }
00220 }

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 2477 of file channel.c.

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

02478 {
02479    struct ast_frame *f;
02480    int res;
02481    if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
02482       return res;
02483 
02484    /* Give us some wiggle room */
02485    while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
02486       f = ast_read(chan);
02487       if (f)
02488          ast_frfree(f);
02489       else
02490          return -1;
02491    }
02492    return 0;
02493 }

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

Start a tone going

Definition at line 2457 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().

02458 {
02459    struct tonepair_def d = { 0, };
02460    d.freq1 = freq1;
02461    d.freq2 = freq2;
02462    d.duration = duration;
02463    if (vol < 1)
02464       d.vol = 8192;
02465    else
02466       d.vol = vol;
02467    if (ast_activate_generator(chan, &tonepair, &d))
02468       return -1;
02469    return 0;
02470 }

void ast_tonepair_stop struct ast_channel chan  ) 
 

Stop a tone from playing

Definition at line 2472 of file channel.c.

References ast_deactivate_generator().

02473 {
02474    ast_deactivate_generator(chan);
02475 }

int ast_transfer struct ast_channel chan,
char *  dest
 

Definition at line 1725 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.

01726 {
01727    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
01728       If the remote end does not answer within the timeout, then do NOT hang up, but 
01729       return anyway.  */
01730    int res = -1;
01731    /* Stop if we're a zombie or need a soft hangup */
01732    ast_mutex_lock(&chan->lock);
01733    if (!chan->zombie && !ast_check_hangup(chan)) {
01734       if (chan->pvt->transfer) {
01735          res = chan->pvt->transfer(chan, dest);
01736          if (!res)
01737             res = 1;
01738       } else
01739          res = 0;
01740    }
01741    ast_mutex_unlock(&chan->lock);
01742    return res;
01743 }

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 906 of file channel.c.

References ast_waitfor_n().

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

00907 {
00908    struct ast_channel *chan;
00909    int oldms = ms;
00910    chan = ast_waitfor_n(&c, 1, &ms);
00911    if (ms < 0) {
00912       if (oldms < 0)
00913          return 0;
00914       else
00915          return -1;
00916    }
00917    return ms;
00918 }

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 901 of file channel.c.

References ast_waitfor_nandfds().

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

00902 {
00903    return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
00904 }

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 758 of file channel.c.

00759 {
00760    /* Wait for x amount of time on a file descriptor to have input.  */
00761    struct timeval tv;
00762    fd_set rfds, efds;
00763    int res;
00764    int x, max=-1;
00765    int winner = -1;
00766    
00767    tv.tv_sec = *ms / 1000;
00768    tv.tv_usec = (*ms % 1000) * 1000;
00769    FD_ZERO(&rfds);
00770    FD_ZERO(&efds);
00771    for (x=0;x<n;x++) {
00772       if (fds[x] > -1) {
00773          FD_SET(fds[x], &rfds);
00774          FD_SET(fds[x], &efds);
00775          if (fds[x] > max)
00776             max = fds[x];
00777       }
00778    }
00779    if (*ms >= 0)
00780       res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
00781    else
00782       res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
00783 
00784    if (res < 0) {
00785       /* Simulate a timeout if we were interrupted */
00786       if (errno != EINTR)
00787          *ms = -1;
00788       else
00789          *ms = 0;
00790       return -1;
00791    }
00792 
00793    for (x=0;x<n;x++) {
00794       if ((fds[x] > -1) && (FD_ISSET(fds[x], &rfds) || FD_ISSET(fds[x], &efds)) && (winner < 0)) {
00795          if (exception)
00796             *exception = FD_ISSET(fds[x], &efds);
00797          winner = fds[x];
00798       }
00799    }
00800    *ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
00801    return winner;
00802 }

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 804 of file channel.c.

References ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_channel::blocking, CHECK_BLOCKING, ast_channel::exception, ast_channel::fdno, ast_channel::fds, LOG_WARNING, and ast_channel::masq.

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

00806 {
00807    /* Wait for x amount of time on a file descriptor to have input.  */
00808    struct timeval tv;
00809    fd_set rfds, efds;
00810    int res;
00811    int x, y, max=-1;
00812    struct ast_channel *winner = NULL;
00813    if (outfd)
00814       *outfd = -1;
00815    if (exception)
00816       *exception = 0;
00817    
00818    /* Perform any pending masquerades */
00819    for (x=0;x<n;x++) {
00820       ast_mutex_lock(&c[x]->lock);
00821       if (c[x]->masq) {
00822          if (ast_do_masquerade(c[x])) {
00823             ast_log(LOG_WARNING, "Masquerade failed\n");
00824             *ms = -1;
00825             ast_mutex_unlock(&c[x]->lock);
00826             return NULL;
00827          }
00828       }
00829       ast_mutex_unlock(&c[x]->lock);
00830    }
00831    
00832    tv.tv_sec = *ms / 1000;
00833    tv.tv_usec = (*ms % 1000) * 1000;
00834    FD_ZERO(&rfds);
00835    FD_ZERO(&efds);
00836 
00837    for (x=0;x<n;x++) {
00838       for (y=0;y<AST_MAX_FDS;y++) {
00839          if (c[x]->fds[y] > -1) {
00840             FD_SET(c[x]->fds[y], &rfds);
00841             FD_SET(c[x]->fds[y], &efds);
00842             if (c[x]->fds[y] > max)
00843                max = c[x]->fds[y];
00844          }
00845       }
00846       CHECK_BLOCKING(c[x]);
00847    }
00848    for (x=0;x<nfds; x++) {
00849       FD_SET(fds[x], &rfds);
00850       FD_SET(fds[x], &efds);
00851       if (fds[x] > max)
00852          max = fds[x];
00853    }
00854    if (*ms >= 0)
00855       res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
00856    else
00857       res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
00858 
00859    if (res < 0) {
00860       for (x=0;x<n;x++) 
00861          c[x]->blocking = 0;
00862       /* Simulate a timeout if we were interrupted */
00863       if (errno != EINTR)
00864          *ms = -1;
00865       else {
00866          /* Just an interrupt */
00867 #if 0
00868          *ms = 0;
00869 #endif         
00870       }
00871       return NULL;
00872    }
00873 
00874    for (x=0;x<n;x++) {
00875       c[x]->blocking = 0;
00876       for (y=0;y<AST_MAX_FDS;y++) {
00877          if (c[x]->fds[y] > -1) {
00878             if ((FD_ISSET(c[x]->fds[y], &rfds) || FD_ISSET(c[x]->fds[y], &efds)) && !winner) {
00879                /* Set exception flag if appropriate */
00880                if (FD_ISSET(c[x]->fds[y], &efds))
00881                   c[x]->exception = 1;
00882                c[x]->fdno = y;
00883                winner = c[x];
00884             }
00885          }
00886       }
00887    }
00888    for (x=0;x<nfds;x++) {
00889       if ((FD_ISSET(fds[x], &rfds) || FD_ISSET(fds[x], &efds)) && !winner) {
00890          if (outfd)
00891             *outfd = fds[x];
00892          if (FD_ISSET(fds[x], &efds) && exception)
00893             *exception = 1;
00894          winner = NULL;
00895       }
00896    }
00897    *ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
00898    return winner;
00899 }

char 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 920 of file channel.c.

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

Referenced by ast_pbx_run(), and ast_readstring().

00921 {
00922    /* XXX Should I be merged with waitfordigit_full XXX */
00923    struct ast_frame *f;
00924    char result = 0;
00925    /* Stop if we're a zombie or need a soft hangup */
00926    if (c->zombie || ast_check_hangup(c)) 
00927       return -1;
00928    /* Wait for a digit, no more than ms milliseconds total. */
00929    while(ms && !result) {
00930       ms = ast_waitfor(c, ms);
00931       if (ms < 0) /* Error */
00932          result = -1; 
00933       else if (ms > 0) {
00934          /* Read something */
00935          f = ast_read(c);
00936          if (f) {
00937             if (f->frametype == AST_FRAME_DTMF) 
00938                result = f->subclass;
00939             ast_frfree(f);
00940          } else
00941             result = -1;
00942       }
00943    }
00944    return result;
00945 }

char ast_waitfordigit_full struct ast_channel c,
int  ms,
int  audio,
int  ctrl
 

Definition at line 964 of file channel.c.

References ast_check_hangup(), AST_FRAME_DTMF, ast_frfree(), ast_read(), ast_waitfor_nandfds(), and ast_channel::zombie.

Referenced by ast_readstring_full().

00965 {
00966    struct ast_frame *f;
00967    char result = 0;
00968    struct ast_channel *rchan;
00969    int outfd;
00970    /* Stop if we're a zombie or need a soft hangup */
00971    if (c->zombie || ast_check_hangup(c)) 
00972       return -1;
00973    /* Wait for a digit, no more than ms milliseconds total. */
00974    while(ms && !result) {
00975       rchan = ast_waitfor_nandfds(&c, 1, &audio, (audio > -1) ? 1 : 0, NULL, &outfd, &ms);
00976       if ((!rchan) && (outfd < 0) && (ms)) /* Error */
00977          result = -1; 
00978       else if (outfd > -1) {
00979          result = 1;
00980       } else if (rchan) {
00981          /* Read something */
00982          f = ast_read(c);
00983          if (f) {
00984             if (f->frametype == AST_FRAME_DTMF) 
00985                result = f->subclass;
00986             ast_frfree(f);
00987          } else
00988             result = -1;
00989       }
00990    }
00991    return result;
00992 }

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 1332 of file channel.c.

References ast_channel::_softhangup, ast_check_hangup(), ast_deactivate_generator(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dump(), 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_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, SEEK_FORCECUR, 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_prod(), ast_rtp_bridge(), and ast_write_video().

01333 {
01334    int res = -1;
01335    struct ast_frame *f = NULL;
01336    /* Stop if we're a zombie or need a soft hangup */
01337    ast_mutex_lock(&chan->lock);
01338    if (chan->zombie || ast_check_hangup(chan))  {
01339       ast_mutex_unlock(&chan->lock);
01340       return -1;
01341    }
01342    /* Handle any pending masquerades */
01343    if (chan->masq) {
01344       if (ast_do_masquerade(chan)) {
01345          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01346          ast_mutex_unlock(&chan->lock);
01347          return -1;
01348       }
01349    }
01350    if (chan->masqr) {
01351       ast_mutex_unlock(&chan->lock);
01352       return 0;
01353    }
01354    if (chan->generatordata) {
01355       if (chan->writeinterrupt)
01356          ast_deactivate_generator(chan);
01357       else {
01358          ast_mutex_unlock(&chan->lock);
01359          return 0;
01360       }
01361    }
01362    if (chan->fout & 0x80000000)
01363       ast_frame_dump(chan->name, fr, ">>");
01364    CHECK_BLOCKING(chan);
01365    switch(fr->frametype) {
01366    case AST_FRAME_CONTROL:
01367       /* XXX Interpret control frames XXX */
01368       ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
01369       break;
01370    case AST_FRAME_DTMF:
01371       chan->blocking = 0;
01372       ast_mutex_unlock(&chan->lock);
01373       res = do_senddigit(chan,fr->subclass);
01374       ast_mutex_lock(&chan->lock);
01375       CHECK_BLOCKING(chan);
01376       break;
01377    case AST_FRAME_TEXT:
01378       if (chan->pvt->send_text)
01379          res = chan->pvt->send_text(chan, (char *) fr->data);
01380       break;
01381    case AST_FRAME_VIDEO:
01382       /* XXX Handle translation of video codecs one day XXX */
01383       if (chan->pvt->write_video)
01384          res = chan->pvt->write_video(chan, fr);
01385       else
01386          res = 0;
01387       break;
01388    default:
01389       if (chan->pvt->write) {
01390          if (chan->pvt->writetrans) {
01391             f = ast_translate(chan->pvt->writetrans, fr, 0);
01392          } else
01393             f = fr;
01394          if (f) {
01395             res = chan->pvt->write(chan, f);
01396             if( chan->monitor &&
01397                   chan->monitor->write_stream &&
01398                   f && ( f->frametype == AST_FRAME_VOICE ) ) {
01399 #ifndef MONITOR_CONSTANT_DELAY
01400                int jump = chan->insmpl - chan->outsmpl - 2 * f->samples;
01401                if (jump >= 0) {
01402                   if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01403                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01404                   chan->outsmpl += jump + 2 * f->samples;
01405                } else
01406                   chan->outsmpl += f->samples;
01407 #else
01408                int jump = chan->insmpl - chan->outsmpl;
01409                if (jump - MONITOR_DELAY >= 0) {
01410                   if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01411                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01412                   chan->outsmpl += jump;
01413                } else
01414                   chan->outsmpl += f->samples;
01415 #endif
01416             if (ast_writestream(chan->monitor->write_stream, f) < 0)
01417                   ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
01418             }
01419          } else
01420             res = 0;
01421       }
01422    }
01423    if (f && (f != fr))
01424       ast_frfree(f);
01425    chan->blocking = 0;
01426    /* Consider a write failure to force a soft hangup */
01427    if (res < 0)
01428       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01429    else {
01430       if ((chan->fout & 0x7fffffff) == 0x7fffffff)
01431          chan->fout &= 0x80000000;
01432       else
01433          chan->fout++;
01434       chan->fout++;
01435    }
01436    ast_mutex_unlock(&chan->lock);
01437    return res;
01438 }

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 1321 of file channel.c.

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

01322 {
01323    int res;
01324    if (!chan->pvt->write_video)
01325       return 0;
01326    res = ast_write(chan, fr);
01327    if (!res)
01328       res = 1;
01329    return res;
01330 }


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 62 of file channel.c.

Referenced by ast_active_channels(), ast_begin_shutdown(), ast_channel_alloc(), ast_channel_free(), and ast_channel_walk().


Generated on Fri Feb 27 12:19:47 2004 for Asterisk by doxygen 1.3.5