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

channel.c File Reference

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

Go to the source code of this file.

Functions

 AST_MUTEX_DEFINE_STATIC (uniquelock)
 AST_MUTEX_DEFINE_STATIC (chlock)
int ast_check_hangup (struct ast_channel *chan)
 Check to see if a channel is needing hang up.
void ast_begin_shutdown (int hangup)
int ast_active_channels (void)
void ast_cancel_shutdown (void)
int ast_shutting_down (void)
void ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset)
 Set when to hang a channel up.
int ast_channel_register (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data))
 Registers a channel.
int ast_channel_register_ex (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data), int(*devicestate)(void *data))
char * ast_state2str (int state)
 Gives the string form of a given state.
int ast_best_codec (int fmts)
 Pick the best codec.
char * ast_alloc_uniqueid (void)
ast_channelast_channel_alloc (int needqueue)
 Create a channel structure.
int ast_queue_frame (struct ast_channel *chan, struct ast_frame *fin)
int ast_queue_hangup (struct ast_channel *chan)
int ast_queue_control (struct ast_channel *chan, int control)
int ast_channel_defer_dtmf (struct ast_channel *chan)
 Defers DTMF.
void ast_channel_undefer_dtmf (struct ast_channel *chan)
 Undeos a defer.
ast_channelast_channel_walk_locked (struct ast_channel *prev)
 Browse channels in use.
ast_channelast_get_channel_by_name_locked (char *channame)
 Get channel by name (locks channel).
ast_channelast_get_channel_by_uniqueid_locked (char *uniqueid)
 Get channel by uniqueid (locks channel).
int ast_safe_sleep_conditional (struct ast_channel *chan, int ms, int(*cond)(void *), void *data)
 Wait for a specied amount of time, looking for hangups and a condition argument.
int ast_safe_sleep (struct ast_channel *chan, int ms)
 Wait for a specied amount of time, looking for hangups.
void ast_channel_free (struct ast_channel *chan)
 Free a channel structure.
int ast_softhangup_nolock (struct ast_channel *chan, int cause)
int ast_softhangup (struct ast_channel *chan, int cause)
 Softly hangup up a channel.
int ast_hangup (struct ast_channel *chan)
 Hang up a channel.
void ast_channel_unregister (char *type)
 Unregister a channel class.
int ast_answer (struct ast_channel *chan)
 Answer a ringing call.
void ast_deactivate_generator (struct ast_channel *chan)
int ast_activate_generator (struct ast_channel *chan, struct ast_generator *gen, void *params)
int ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception)
 Waits for input on an fd.
ast_channelast_waitfor_nandfds (struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
 Waits for activity on a group of channels.
ast_channelast_waitfor_n (struct ast_channel **c, int n, int *ms)
 Waits for input on a group of channels.
int ast_waitfor (struct ast_channel *c, int ms)
 Wait for input on a channel.
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 audiofd, int cmdfd)
ast_frameast_read (struct ast_channel *chan)
 Reads a frame.
int ast_indicate (struct ast_channel *chan, int condition)
 Indicates condition of channel.
int ast_recvchar (struct ast_channel *chan, int timeout)
int ast_sendtext (struct ast_channel *chan, char *text)
 Sends text to a channel.
int ast_senddigit (struct ast_channel *chan, char digit)
 Receives a text character from a channel.
int ast_prod (struct ast_channel *chan)
int ast_write_video (struct ast_channel *chan, struct ast_frame *fr)
 Write video frame to a channel.
int ast_write (struct ast_channel *chan, struct ast_frame *fr)
 Write a frame to a channel.
int ast_set_write_format (struct ast_channel *chan, int fmts)
 Sets write format on channel chan.
int ast_set_read_format (struct ast_channel *chan, int fmts)
 Sets read format on channel chan.
ast_channel__ast_request_and_dial (char *type, int format, void *data, int timeout, int *outstate, int callingpres, char *callerid, struct outgoing_helper *oh, char *uniqueid)
ast_channelast_request_and_dial (char *type, int format, void *data, int timeout, int *outstate, int callingpres, char *callerid, char *uniqueid)
ast_channelast_request (char *type, int format, void *data, char *uniqueid)
 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.
int ast_channel_masquerade_locked (struct ast_channel *original, struct ast_channel *clone)
void ast_change_name (struct ast_channel *chan, char *newname)
int ast_do_masquerade (struct ast_channel *original)
void ast_set_callerid (struct ast_channel *chan, char *callerid, int anitoo)
int ast_setstate (struct ast_channel *chan, int state)
int ast_channel_bridge (struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
 Bridge two channels together.
int ast_channel_setoption (struct ast_channel *chan, int option, void *data, int datalen, int block)
 Sets an option on a channel.
int ast_tonepair_start (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
void ast_tonepair_stop (struct ast_channel *chan)
int ast_tonepair (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
unsigned int ast_get_group (char *s)

Variables

int ast_mainpid
chanlistbackends
ast_channelchannels = NULL


Function Documentation

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

Definition at line 1779 of file channel.c.

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

Referenced by ast_pbx_outgoing_exten(), and ast_request_and_dial().

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

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

Activate a given generator

Definition at line 882 of file channel.c.

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

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

00883 {
00884    int res = 0;
00885    ast_mutex_lock(&chan->lock);
00886    if (chan->generatordata) {
00887       if (chan->generator && chan->generator->release)
00888          chan->generator->release(chan, chan->generatordata);
00889       chan->generatordata = NULL;
00890    }
00891    ast_prod(chan);
00892    if ((chan->generatordata = gen->alloc(chan, params))) {
00893       ast_settimeout(chan, 160, generator_force, chan);
00894       chan->generator = gen;
00895    } else {
00896       res = -1;
00897    }
00898    ast_mutex_unlock(&chan->lock);
00899    return res;
00900 }

int ast_active_channels void   ) 
 

Returns number of active/allocated channels

Definition at line 123 of file channel.c.

References ast_mutex_lock, ast_mutex_unlock, and ast_channel::next.

00124 {
00125    struct ast_channel *c;
00126    int cnt = 0;
00127    ast_mutex_lock(&chlock);
00128    c = channels;
00129    while(c) {
00130       cnt++;
00131       c = c->next;
00132    }
00133    ast_mutex_unlock(&chlock);
00134    return cnt;
00135 }

char* ast_alloc_uniqueid void   ) 
 

Definition at line 277 of file channel.c.

References ast_config_AST_SYMBOLIC_NAME, ast_mainpid, ast_mutex_lock, ast_mutex_unlock, and malloc.

Referenced by ast_channel_alloc().

00277                                {
00278     char *uniqueid;
00279     uniqueid = malloc(64);
00280     if (!uniqueid) return NULL;
00281     ast_mutex_lock(&uniquelock);
00282     snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYMBOLIC_NAME, ast_mainpid, (long)time(NULL), uniqueint++);
00283     ast_mutex_unlock(&uniquelock);
00284 //    ast_log(LOG_NOTICE,"uid = %s\n",uniqueid);
00285     return uniqueid;
00286 }

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 818 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::lock, ast_channel::pvt, and ast_channel::zombie.

Referenced by ast_control_streamfile().

00819 {
00820    int res = 0;
00821    ast_mutex_lock(&chan->lock);
00822    /* Stop if we're a zombie or need a soft hangup */
00823    if (chan->zombie || ast_check_hangup(chan)) {
00824       ast_mutex_unlock(&chan->lock);
00825       return -1;
00826    }
00827    switch(chan->_state) {
00828    case AST_STATE_RINGING:
00829    case AST_STATE_RING:
00830       if (chan->pvt->answer)
00831          res = chan->pvt->answer(chan);
00832       ast_setstate(chan, AST_STATE_UP);
00833       if (chan->cdr)
00834          ast_cdr_answer(chan->cdr);
00835       ast_mutex_unlock(&chan->lock);
00836       return res;
00837       break;
00838    case AST_STATE_UP:
00839       if (chan->cdr)
00840          ast_cdr_answer(chan->cdr);
00841       break;
00842    }
00843    ast_mutex_unlock(&chan->lock);
00844    return 0;
00845 }

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

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

00109 {
00110    struct ast_channel *c;
00111    shutting_down = 1;
00112    if (hangup) {
00113       ast_mutex_lock(&chlock);
00114       c = channels;
00115       while(c) {
00116          ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
00117          c = c->next;
00118       }
00119       ast_mutex_unlock(&chlock);
00120    }
00121 }

int ast_best_codec int  fmts  ) 
 

Pick the best codec.

Definition at line 236 of file channel.c.

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

Referenced by ast_codec_choose().

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

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

02006 {
02007    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
02008       If the remote end does not answer within the timeout, then do NOT hang up, but 
02009       return anyway.  */
02010    int res = -1;
02011    /* Stop if we're a zombie or need a soft hangup */
02012    ast_mutex_lock(&chan->lock);
02013    if (!chan->zombie && !ast_check_hangup(chan)) 
02014       if (chan->pvt->call)
02015          res = chan->pvt->call(chan, addr, timeout);
02016    ast_mutex_unlock(&chan->lock);
02017    return res;
02018 }

void ast_cancel_shutdown void   ) 
 

Cancels an existing shutdown and returns to normal operation

Definition at line 137 of file channel.c.

00138 {
00139    shutting_down = 0;
00140 }

void ast_change_name struct ast_channel chan,
char *  newname
 

Definition at line 2247 of file channel.c.

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

02248 {
02249    char tmp[256];
02250    strncpy(tmp, chan->name, sizeof(tmp) - 1);
02251    strncpy(chan->name, newname, sizeof(chan->name) - 1);
02252    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid);
02253 }

struct ast_channel* ast_channel_alloc int  needalertpipe  ) 
 

Create a channel structure.

Returns NULL on failure to allocate

Definition at line 288 of file channel.c.

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

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

00289 {
00290    struct ast_channel *tmp;
00291    struct ast_channel_pvt *pvt;
00292    int x;
00293    int flags;
00294    struct varshead *headp;
00295    char *tmpuniqueid;
00296            
00297    
00298    /* If shutting down, don't allocate any new channels */
00299    if (shutting_down)
00300       return NULL;
00301    ast_mutex_lock(&chlock);
00302    tmp = malloc(sizeof(struct ast_channel));
00303    if (tmp) {
00304       memset(tmp, 0, sizeof(struct ast_channel));
00305       pvt = malloc(sizeof(struct ast_channel_pvt));
00306       if (pvt) {
00307          memset(pvt, 0, sizeof(struct ast_channel_pvt));
00308          tmp->sched = sched_context_create();
00309          if (tmp->sched) {
00310             for (x=0;x<AST_MAX_FDS - 1;x++)
00311                tmp->fds[x] = -1;
00312 #ifdef ZAPTEL_OPTIMIZATIONS
00313             tmp->timingfd = open("/dev/zap/timer", O_RDWR);
00314             if (tmp->timingfd > -1) {
00315                /* Check if timing interface supports new
00316                   ping/pong scheme */
00317                flags = 1;
00318                if (!ioctl(tmp->timingfd, ZT_TIMERPONG, &flags))
00319                   needqueue = 0;
00320             }
00321 #else
00322             tmp->timingfd = -1;              
00323 #endif               
00324             if (needqueue &&  
00325                pipe(pvt->alertpipe)) {
00326                ast_log(LOG_WARNING, "Alert pipe creation failed!\n");
00327                free(pvt);
00328                free(tmp);
00329                tmp = NULL;
00330                pvt = NULL;
00331             } else {
00332                if (needqueue) {
00333                   flags = fcntl(pvt->alertpipe[0], F_GETFL);
00334                   fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK);
00335                   flags = fcntl(pvt->alertpipe[1], F_GETFL);
00336                   fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK);
00337                } else 
00338                /* Make sure we've got it done right if they don't */
00339                   pvt->alertpipe[0] = pvt->alertpipe[1] = -1;
00340                /* Always watch the alertpipe */
00341                tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0];
00342                /* And timing pipe */
00343                tmp->fds[AST_MAX_FDS-2] = tmp->timingfd;
00344                strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1);
00345                tmp->pvt = pvt;
00346                /* Initial state */
00347                tmp->_state = AST_STATE_DOWN;
00348                tmp->stack = -1;
00349                tmp->streamid = -1;
00350                tmp->appl = NULL;
00351                tmp->data = NULL;
00352                tmp->fin = 0;
00353                tmp->fout = 0;
00354                tmpuniqueid = ast_alloc_uniqueid();
00355                snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), tmpuniqueid);
00356                if (tmpuniqueid) { 
00357                    free(tmpuniqueid);
00358                    tmpuniqueid = NULL;
00359                }
00360                headp=&tmp->varshead;
00361                ast_mutex_init(&tmp->lock);
00362                     AST_LIST_HEAD_INIT(headp);
00363                tmp->vars=ast_var_assign("tempvar","tempval");
00364                AST_LIST_INSERT_HEAD(headp,tmp->vars,entries);
00365                strncpy(tmp->context, "default", sizeof(tmp->context)-1);
00366                strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1);
00367                strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
00368                tmp->priority=1;
00369                tmp->amaflags = ast_default_amaflags;
00370                strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1);
00371                tmp->next = channels;
00372                channels= tmp;
00373             }
00374          } else {
00375             ast_log(LOG_WARNING, "Unable to create schedule context\n");
00376             free(tmp);
00377             tmp = NULL;
00378          }
00379       } else {
00380          ast_log(LOG_WARNING, "Out of memory\n");
00381          free(tmp);
00382          tmp = NULL;
00383       }
00384    } else 
00385       ast_log(LOG_WARNING, "Out of memory\n");
00386    ast_mutex_unlock(&chlock);
00387    return tmp;
00388 }

int ast_channel_bridge struct ast_channel c0,
struct ast_channel c1,
struct ast_bridge_config config,
struct ast_frame **  fo,
struct ast_channel **  rc
 

Bridge two channels together.

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

Definition at line 2570 of file channel.c.

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

02571 {
02572    /* Copy voice back and forth between the two channels.   Give the peer
02573       the ability to transfer calls with '#<extension' syntax. */
02574    int flags;
02575    struct ast_channel *cs[3];
02576    int to = -1;
02577    struct ast_frame *f;
02578    struct ast_channel *who = NULL;
02579    int res=0;
02580    int nativefailed=0;
02581    int firstpass;
02582    int o0nativeformats;
02583    int o1nativeformats;
02584    struct timeval start_time,precise_now;
02585    long elapsed_ms=0, time_left_ms=0;
02586    int playit=0, playitagain=1, first_time=1;
02587 
02588    flags = (config->allowdisconnect_out||config->allowredirect_out ? AST_BRIDGE_DTMF_CHANNEL_0 : 0) + (config->allowdisconnect_in||config->allowredirect_in ? AST_BRIDGE_DTMF_CHANNEL_1 : 0);
02589 
02590    firstpass = config->firstpass;
02591    config->firstpass = 0;
02592 
02593    /* timestamp */
02594    gettimeofday(&start_time,NULL);
02595    time_left_ms = config->timelimit;
02596 
02597    if (config->play_to_caller && config->start_sound && firstpass)
02598       bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000);
02599    if (config->play_to_callee && config->start_sound && firstpass)
02600       bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000);
02601 
02602    /* Stop if we're a zombie or need a soft hangup */
02603    if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 
02604       return -1;
02605    if (c0->bridge) {
02606       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02607          c0->name, c0->bridge->name);
02608       return -1;
02609    }
02610    if (c1->bridge) {
02611       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02612          c1->name, c1->bridge->name);
02613       return -1;
02614    }
02615    
02616    /* Keep track of bridge */
02617    c0->bridge = c1;
02618    c1->bridge = c0;
02619    cs[0] = c0;
02620    cs[1] = c1;
02621    
02622    manager_event(EVENT_FLAG_CALL, "Link", 
02623          "Channel1: %s\r\n"
02624          "Channel2: %s\r\n"
02625          "Uniqueid1: %s\r\n"
02626          "Uniqueid2: %s\r\n",
02627          c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02628    o1nativeformats = c1->nativeformats;
02629    o0nativeformats = c0->nativeformats;
02630    for (/* ever */;;) {
02631       /* timestamp */
02632       if (config->timelimit) {
02633          gettimeofday(&precise_now,NULL);
02634          elapsed_ms = tvdiff(&precise_now,&start_time);
02635          time_left_ms = config->timelimit - elapsed_ms;
02636 
02637          if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) { 
02638             /* narrowing down to the end */
02639             if (config->warning_freq == 0) {
02640                playit = 1;
02641                first_time=0;
02642                playitagain=0;
02643             } else if (first_time) {
02644                playit = 1;
02645                first_time=0;
02646             } else {
02647                if ((time_left_ms % config->warning_freq) <= 50) {
02648                   playit = 1;
02649                }
02650             }
02651          }
02652          if (time_left_ms <= 0) {
02653             if (config->play_to_caller && config->end_sound)
02654                bridge_playfile(c0,c1,config->end_sound,0);
02655             if (config->play_to_callee && config->end_sound)
02656                bridge_playfile(c1,c0,config->end_sound,0);
02657             *fo = NULL;
02658             if (who) *rc = who;
02659             res = 0;
02660             break;
02661          }
02662          if (time_left_ms >= 5000 && playit) {
02663             if (config->play_to_caller && config->warning_sound && config->play_warning)
02664                bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000);
02665             if (config->play_to_callee && config->warning_sound && config->play_warning)
02666                bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000);
02667             playit = 0;
02668          }
02669          
02670       }
02671       /* Stop if we're a zombie or need a soft hangup */
02672       if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
02673          *fo = NULL;
02674          if (who) *rc = who;
02675          res = 0;
02676          ast_log(LOG_DEBUG, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",c0->name,c1->name,c0->zombie?"Yes":"No",ast_check_hangup(c0)?"Yes":"No",c1->zombie?"Yes":"No",ast_check_hangup(c1)?"Yes":"No");
02677          break;
02678       }
02679       if (c0->pvt->bridge && config->timelimit==0 &&
02680          (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
02681             /* Looks like they share a bridge code */
02682          if (option_verbose > 2) 
02683             ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
02684          if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
02685             c0->bridge = NULL;
02686             c1->bridge = NULL;
02687             manager_event(EVENT_FLAG_CALL, "Unlink", 
02688                "Channel1: %s\r\n"
02689                "Channel2: %s\r\n"
02690                "Uniqueid1: %s\r\n"
02691                "Uniqueid2: %s\r\n",
02692                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02693             ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
02694             return 0;
02695          }
02696          /* If they return non-zero then continue on normally.  Let "-2" mean don't worry about
02697             my not wanting to bridge */
02698          if ((res != -2) && (res != -3))
02699             ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
02700          if (res != -3) nativefailed++;
02701       }
02702    
02703       if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) &&
02704          !(c0->generator || c1->generator))  {
02705          if (ast_channel_make_compatible(c0, c1)) {
02706             ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
02707             manager_event(EVENT_FLAG_CALL, "Unlink", 
02708                "Channel1: %s\r\n"
02709                "Channel2: %s\r\n"
02710                "Uniqueid1: %s\r\n"
02711                "Uniqueid2: %s\r\n",
02712                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02713             return -1;
02714          }
02715          o0nativeformats = c0->nativeformats;
02716          o1nativeformats = c1->nativeformats;
02717       }
02718       who = ast_waitfor_n(cs, 2, &to);
02719       if (!who) {
02720          ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 
02721          continue;
02722       }
02723       f = ast_read(who);
02724       if (!f) {
02725          *fo = NULL;
02726          *rc = who;
02727          res = 0;
02728          ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
02729          break;
02730       }
02731 
02732       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02733          *fo = f;
02734          *rc = who;
02735          res =  0;
02736          ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
02737          break;
02738       }
02739       if ((f->frametype == AST_FRAME_VOICE) ||
02740          (f->frametype == AST_FRAME_TEXT) ||
02741          (f->frametype == AST_FRAME_VIDEO) || 
02742          (f->frametype == AST_FRAME_IMAGE) ||
02743          (f->frametype == AST_FRAME_DTMF)) {
02744          if ((f->frametype == AST_FRAME_DTMF) && 
02745             (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
02746             if ((who == c0)) {
02747                if  ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
02748                   *rc = c0;
02749                   *fo = f;
02750                   /* Take out of conference mode */
02751                   res = 0;
02752                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
02753                   break;
02754                } else 
02755                   goto tackygoto;
02756             } else
02757             if ((who == c1)) {
02758                if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
02759                   *rc = c1;
02760                   *fo = f;
02761                   res =  0;
02762                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
02763                   break;
02764                } else
02765                   goto tackygoto;
02766             }
02767          } else {
02768 #if 0
02769             ast_log(LOG_DEBUG, "Read from %s\n", who->name);
02770             if (who == last) 
02771                ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
02772             last = who;
02773 #endif
02774 tackygoto:
02775             /* Don't copy packets if there is a generator on either one, since they're
02776                not supposed to be listening anyway */
02777             if (who == c0) 
02778                ast_write(c1, f);
02779             else 
02780                ast_write(c0, f);
02781          }
02782          ast_frfree(f);
02783       } else
02784          ast_frfree(f);
02785       /* Swap who gets priority */
02786       cs[2] = cs[0];
02787       cs[0] = cs[1];
02788       cs[1] = cs[2];
02789    }
02790    c0->bridge = NULL;
02791    c1->bridge = NULL;
02792    manager_event(EVENT_FLAG_CALL, "Unlink", 
02793                "Channel1: %s\r\n"
02794                "Channel2: %s\r\n"
02795                "Uniqueid1: %s\r\n"
02796                "Uniqueid2: %s\r\n",
02797                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02798    ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name);
02799    return res;
02800 }

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

References ast_channel::deferdtmf.

00462 {
00463    int pre = 0;
00464    if (chan) {
00465       pre = chan->deferdtmf;
00466       chan->deferdtmf = 1;
00467    }
00468    return pre;
00469 }

void ast_channel_free struct ast_channel chan  ) 
 

Free a channel structure.

Definition at line 594 of file channel.c.

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

Referenced by ast_do_masquerade(), and ast_hangup().

00595 {
00596    struct ast_channel *last=NULL, *cur;
00597    int fd;
00598    struct ast_var_t *vardata;
00599    struct ast_frame *f, *fp;
00600    struct varshead *headp;
00601    char name[AST_CHANNEL_NAME];
00602    
00603    headp=&chan->varshead;
00604    
00605    ast_mutex_lock(&chlock);
00606    cur = channels;
00607    while(cur) {
00608       if (cur == chan) {
00609          if (last)
00610             last->next = cur->next;
00611          else
00612             channels = cur->next;
00613          break;
00614       }
00615       last = cur;
00616       cur = cur->next;
00617    }
00618    if (!cur)
00619       ast_log(LOG_WARNING, "Unable to find channel in list\n");
00620    else {
00621       /* Lock and unlock the channel just to be sure nobody
00622          has it locked still */
00623       ast_mutex_lock(&cur->lock);
00624       ast_mutex_unlock(&cur->lock);
00625    }
00626    if (chan->pvt->pvt)
00627       ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
00628 
00629    strncpy(name, chan->name, sizeof(name)-1);
00630    
00631    /* Stop monitoring */
00632    if (chan->monitor) {
00633       chan->monitor->stop( chan, 0 );
00634    }
00635 
00636    /* Free translatosr */
00637    if (chan->pvt->readtrans)
00638       ast_translator_free_path(chan->pvt->readtrans);
00639    if (chan->pvt->writetrans)
00640       ast_translator_free_path(chan->pvt->writetrans);
00641    if (chan->pbx) 
00642       ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
00643    if (chan->dnid)
00644       free(chan->dnid);
00645    if (chan->callerid)
00646       free(chan->callerid);   
00647    if (chan->ani)
00648       free(chan->ani);
00649    if (chan->rdnis)
00650       free(chan->rdnis);
00651    ast_mutex_destroy(&chan->lock);
00652    /* Close pipes if appropriate */
00653    if ((fd = chan->pvt->alertpipe[0]) > -1)
00654       close(fd);
00655    if ((fd = chan->pvt->alertpipe[1]) > -1)
00656       close(fd);
00657    if ((fd = chan->timingfd) > -1)
00658       close(fd);
00659    f = chan->pvt->readq;
00660    chan->pvt->readq = NULL;
00661    while(f) {
00662       fp = f;
00663       f = f->next;
00664       ast_frfree(fp);
00665    }
00666    
00667    /* loop over the variables list, freeing all data and deleting list items */
00668    /* no need to lock the list, as the channel is already locked */
00669    
00670    while (!AST_LIST_EMPTY(headp)) {           /* List Deletion. */
00671                vardata = AST_LIST_FIRST(headp);
00672                AST_LIST_REMOVE_HEAD(headp, entries);
00673 //             printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata));
00674                ast_var_delete(vardata);
00675    }
00676                                                     
00677 
00678    free(chan->pvt);
00679    chan->pvt = NULL;
00680    free(chan);
00681    ast_mutex_unlock(&chlock);
00682 
00683    ast_device_state_changed(name);
00684 }

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

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

Referenced by ast_channel_bridge().

02143 {
02144    int peerf;
02145    int chanf;
02146    int res;
02147    ast_mutex_lock(&peer->lock);
02148    peerf = peer->nativeformats;
02149    ast_mutex_unlock(&peer->lock);
02150    ast_mutex_lock(&chan->lock);
02151    chanf = chan->nativeformats;
02152    ast_mutex_unlock(&chan->lock);
02153    res = ast_translator_best_choice(&peerf, &chanf);
02154    if (res < 0) {
02155       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
02156       return -1;
02157    }
02158    /* Set read format on channel */
02159    res = ast_set_read_format(chan, peerf);
02160    if (res < 0) {
02161       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
02162       return -1;
02163    }
02164    /* Set write format on peer channel */
02165    res = ast_set_write_format(peer, peerf);
02166    if (res < 0) {
02167       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
02168       return -1;
02169    }
02170    /* Now we go the other way */
02171    peerf = peer->nativeformats;
02172    chanf = chan->nativeformats;
02173    res = ast_translator_best_choice(&chanf, &peerf);
02174    if (res < 0) {
02175       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
02176       return -1;
02177    }
02178    /* Set writeformat on channel */
02179    res = ast_set_write_format(chan, chanf);
02180    if (res < 0) {
02181       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
02182       return -1;
02183    }
02184    /* Set read format on peer channel */
02185    res = ast_set_read_format(peer, chanf);
02186    if (res < 0) {
02187       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
02188       return -1;
02189    }
02190    return 0;
02191 }

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

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

Referenced by ast_async_goto().

02194 {
02195    struct ast_frame null = { AST_FRAME_NULL, };
02196    int res = -1;
02197    ast_mutex_lock(&original->lock);
02198    while(ast_mutex_trylock(&clone->lock)) {
02199       ast_mutex_unlock(&original->lock);
02200       usleep(1);
02201       ast_mutex_lock(&original->lock);
02202    }
02203    ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
02204       clone->name, original->name);
02205    if (original->masq) {
02206       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02207          original->masq->name, original->name);
02208    } else if (clone->masqr) {
02209       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02210          clone->name, clone->masqr->name);
02211    } else {
02212       original->masq = clone;
02213       clone->masqr = original;
02214       ast_queue_frame(original, &null);
02215       ast_queue_frame(clone, &null);
02216       ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
02217       res = 0;
02218    }
02219    ast_mutex_unlock(&clone->lock);
02220    ast_mutex_unlock(&original->lock);
02221    return res;
02222 }

int ast_channel_masquerade_locked struct ast_channel original,
struct ast_channel clone
 

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

02225 {
02226    struct ast_frame null = { AST_FRAME_NULL, };
02227    int res = -1;
02228    ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
02229       clone->name, original->name);
02230    if (original->masq) {
02231       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02232          original->masq->name, original->name);
02233    } else if (clone->masqr) {
02234       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02235          clone->name, clone->masqr->name);
02236    } else {
02237       original->masq = clone;
02238       clone->masqr = original;
02239       ast_queue_frame(original, &null);
02240       ast_queue_frame(clone, &null);
02241       ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
02242       res = 0;
02243    }
02244    return res;
02245 }

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

Registers a channel.

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

Definition at line 159 of file channel.c.

References ast_channel_register_ex().

00161 {
00162    return ast_channel_register_ex(type, description, capabilities, requester, NULL);
00163 }

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

Definition at line 165 of file channel.c.

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

Referenced by ast_channel_register().

00168 {
00169    struct chanlist *chan, *last=NULL;
00170    if (ast_mutex_lock(&chlock)) {
00171       ast_log(LOG_WARNING, "Unable to lock channel list\n");
00172       return -1;
00173    }
00174    chan = backends;
00175    while (chan) {
00176       if (!strcasecmp(type, chan->type)) {
00177          ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
00178          ast_mutex_unlock(&chlock);
00179          return -1;
00180       }
00181       last = chan;
00182       chan = chan->next;
00183    }
00184    chan = malloc(sizeof(struct chanlist));
00185    if (!chan) {
00186       ast_log(LOG_WARNING, "Out of memory\n");
00187       ast_mutex_unlock(&chlock);
00188       return -1;
00189    }
00190    strncpy(chan->type, type, sizeof(chan->type)-1);
00191    strncpy(chan->description, description, sizeof(chan->description)-1);
00192    chan->capabilities = capabilities;
00193    chan->requester = requester;
00194    chan->devicestate = devicestate;
00195    chan->next = NULL;
00196    if (last)
00197       last->next = chan;
00198    else
00199       backends = chan;
00200    if (option_debug)
00201       ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
00202    else if (option_verbose > 1)
00203       ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
00204    ast_mutex_unlock(&chlock);
00205    return 0;
00206 }

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

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

02129 {
02130    if (chan->pvt->send_html)
02131       return chan->pvt->send_html(chan, subclass, data, datalen);
02132    return -1;
02133 }

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

References AST_HTML_URL.

02136 {
02137    if (chan->pvt->send_html)
02138       return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
02139    return -1;
02140 }

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

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

02803 {
02804    int res;
02805    if (chan->pvt->setoption) {
02806       res = chan->pvt->setoption(chan, option, data, datalen);
02807       if (res < 0)
02808          return res;
02809    } else {
02810       errno = ENOSYS;
02811       return -1;
02812    }
02813    if (block) {
02814       /* XXX Implement blocking -- just wait for our option frame reply, discarding
02815          intermediate packets. XXX */
02816       ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
02817       return -1;
02818    }
02819    return 0;
02820 }

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

References ast_channel::whentohangup.

00148 {
00149    time_t   myt;
00150 
00151    time(&myt);
00152    if (offset)
00153       chan->whentohangup = myt + offset;
00154    else
00155       chan->whentohangup = 0;
00156    return;
00157 }

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

02122 {
02123    if (chan->pvt->send_html)
02124       return 1;
02125    return 0;
02126 }

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

00472 {
00473    if (chan)
00474       chan->deferdtmf = 0;
00475 }

void ast_channel_unregister char *  type  ) 
 

Unregister a channel class.

Definition at line 789 of file channel.c.

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

00790 {
00791    struct chanlist *chan, *last=NULL;
00792    if (option_debug)
00793       ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type);
00794    if (ast_mutex_lock(&chlock)) {
00795       ast_log(LOG_WARNING, "Unable to lock channel list\n");
00796       return;
00797    }
00798    if (option_verbose > 1)
00799       ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type);
00800 
00801    chan = backends;
00802    while(chan) {
00803       if (!strcasecmp(chan->type, type)) {
00804          if (last)
00805             last->next = chan->next;
00806          else
00807             backends = backends->next;
00808          free(chan);
00809          ast_mutex_unlock(&chlock);
00810          return;
00811       }
00812       last = chan;
00813       chan = chan->next;
00814    }
00815    ast_mutex_unlock(&chlock);
00816 }

struct ast_channel* ast_channel_walk_locked struct ast_channel prev  ) 
 

Browse channels in use.

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

Definition at line 477 of file channel.c.

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

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

00478 {
00479    /* Returns next channel (locked) */
00480    struct ast_channel *l, *ret;
00481    int retries = 0;  
00482 retry:
00483    ret=NULL;
00484    ast_mutex_lock(&chlock);
00485    l = channels;
00486    if (!prev) {
00487       if (l) {
00488          if (ast_mutex_trylock(&l->lock)) {
00489             if (retries < 10)
00490                ast_log(LOG_DEBUG, "Avoiding initial deadlock for '%s'\n", l->name);
00491             else
00492                ast_log(LOG_WARNING, "Avoided initial deadlock for '%s', %d retries!\n", l->name, retries);
00493             ast_mutex_unlock(&chlock);
00494             if (retries < 10) {
00495                usleep(1);
00496                retries++;
00497                goto retry;
00498             } else
00499                return NULL;
00500          }
00501       }
00502       ast_mutex_unlock(&chlock);
00503       return l;
00504    }
00505    while(l) {
00506       if (l == prev)
00507          ret = l->next;
00508       l = l->next;
00509    }
00510    if (ret) {
00511       if (ast_mutex_trylock(&ret->lock)) {
00512          if (retries < 10)
00513             ast_log(LOG_DEBUG, "Avoiding deadlock for '%s'\n", ret->name);
00514          else
00515             ast_log(LOG_WARNING, "Avoided deadlock for '%s', %d retries!\n", ret->name, retries);
00516          ast_mutex_unlock(&chlock);
00517          if (retries < 10) {
00518             usleep(1);
00519             retries++;
00520             goto retry;
00521          } else
00522             return NULL;
00523       }
00524    }
00525    ast_mutex_unlock(&chlock);
00526    return ret;
00527    
00528 }

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

00083 {
00084 time_t   myt;
00085 
00086      /* if soft hangup flag, return true */
00087    if (chan->_softhangup) return 1;
00088      /* if no private structure, return true */
00089    if (!chan->pvt->pvt) return 1;
00090      /* if no hangup scheduled, just return here */
00091    if (!chan->whentohangup) return 0;
00092    time(&myt); /* get current time */
00093      /* return, if not yet */
00094    if (chan->whentohangup > myt) return 0;
00095    chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
00096    return 1;
00097 }

void ast_deactivate_generator struct ast_channel chan  ) 
 

Deactive an active generator

Definition at line 849 of file channel.c.

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

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

00850 {
00851    ast_mutex_lock(&chan->lock);
00852    if (chan->generatordata) {
00853       if (chan->generator && chan->generator->release) 
00854          chan->generator->release(chan, chan->generatordata);
00855       chan->generatordata = NULL;
00856       chan->generator = NULL;
00857       chan->writeinterrupt = 0;
00858       ast_settimeout(chan, 0, NULL, NULL);
00859    }
00860    ast_mutex_unlock(&chan->lock);
00861 }

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

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

01967 {
01968    char tech[AST_MAX_EXTENSION] = "";
01969    char *number;
01970    struct chanlist *chanls;
01971    int res = 0;
01972    
01973    strncpy(tech, device, sizeof(tech)-1);
01974    number = strchr(tech, '/');
01975    if (!number) {
01976        return AST_DEVICE_INVALID;
01977    }
01978    *number = 0;
01979    number++;
01980       
01981    if (ast_mutex_lock(&chlock)) {
01982       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01983       return -1;
01984    }
01985    chanls = backends;
01986    while(chanls) {
01987       if (!strcasecmp(tech, chanls->type)) {
01988          ast_mutex_unlock(&chlock);
01989          if (!chanls->devicestate) 
01990             return ast_parse_device_state(device);
01991          else {
01992             res = chanls->devicestate(number);
01993             if (res == AST_DEVICE_UNKNOWN)
01994                return ast_parse_device_state(device);
01995             else
01996                return res;
01997          }
01998       }
01999       chanls = chanls->next;
02000    }
02001    ast_mutex_unlock(&chlock);
02002    return AST_DEVICE_INVALID;
02003 }

int ast_do_masquerade struct ast_channel original  ) 
 

Definition at line 2255 of file channel.c.

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

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

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

struct ast_channel* ast_get_channel_by_name_locked char *  channame  ) 
 

Get channel by name (locks channel).

Definition at line 530 of file channel.c.

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

00531 {
00532    struct ast_channel *chan;
00533    chan = ast_channel_walk_locked(NULL);
00534    while(chan) {
00535       if (!strcasecmp(chan->name, channame))
00536          return chan;
00537       ast_mutex_unlock(&chan->lock);
00538       chan = ast_channel_walk_locked(chan);
00539    }
00540    return NULL;
00541 }

struct ast_channel* ast_get_channel_by_uniqueid_locked char *  uniqueid  ) 
 

Get channel by uniqueid (locks channel).

Definition at line 543 of file channel.c.

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

00544 {
00545    struct ast_channel *chan;
00546    chan = ast_channel_walk_locked(NULL);
00547    while(chan) {
00548       if (!strcasecmp(chan->uniqueid, uniqueid))
00549          return chan;
00550       ast_mutex_unlock(&chan->lock);
00551       chan = ast_channel_walk_locked(chan);
00552    }
00553    return NULL;
00554 }

unsigned int ast_get_group char *  s  ) 
 

Definition at line 2954 of file channel.c.

References ast_log(), LOG_ERROR, and LOG_WARNING.

02955 {
02956    char *copy;
02957    char *piece;
02958    char *c=NULL;
02959    int start=0, finish=0,x;
02960    unsigned int group = 0;
02961    copy = ast_strdupa(s);
02962    if (!copy) {
02963       ast_log(LOG_ERROR, "Out of memory\n");
02964       return 0;
02965    }
02966    c = copy;
02967    
02968    while((piece = strsep(&c, ","))) {
02969       if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
02970          /* Range */
02971       } else if (sscanf(piece, "%d", &start)) {
02972          /* Just one */
02973          finish = start;
02974       } else {
02975          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.\n", s, piece);
02976          continue;
02977       }
02978       for (x=start;x<=finish;x++) {
02979          if ((x > 31) || (x < 0)) {
02980             ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x);
02981          } else
02982             group |= (1 << x);
02983       }
02984    }
02985    return group;
02986 }

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

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

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

00723 {
00724    int res = 0;
00725    /* Don't actually hang up a channel that will masquerade as someone else, or
00726       if someone is going to masquerade as us */
00727    ast_mutex_lock(&chan->lock);
00728    if (chan->masq) {
00729       if (ast_do_masquerade(chan)) 
00730          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
00731    }
00732 
00733    if (chan->masq) {
00734       ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
00735       ast_mutex_unlock(&chan->lock);
00736       return 0;
00737    }
00738    /* If this channel is one which will be masqueraded into something, 
00739       mark it as a zombie already, so we know to free it later */
00740    if (chan->masqr) {
00741       chan->zombie=1;
00742       ast_mutex_unlock(&chan->lock);
00743       return 0;
00744    }
00745    free_translation(chan);
00746    if (chan->stream) 
00747       ast_closestream(chan->stream);
00748    if (chan->vstream)
00749       ast_closestream(chan->vstream);
00750    if (chan->sched)
00751       sched_context_destroy(chan->sched);
00752    /* Clear any tone stuff remaining */
00753    if (chan->generatordata)
00754       chan->generator->release(chan, chan->generatordata);
00755    chan->generatordata = NULL;
00756    chan->generator = NULL;
00757    if (chan->cdr) {
00758       /* End the CDR if it hasn't already */
00759       ast_cdr_end(chan->cdr);
00760       /* Post and Free the CDR */
00761       ast_cdr_post(chan->cdr);
00762       ast_cdr_free(chan->cdr);
00763    }
00764    if (chan->blocking) {
00765       ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
00766                "is blocked by thread %ld in procedure %s!  Expect a failure\n",
00767                (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc);
00768       CRASH;
00769    }
00770    if (!chan->zombie) {
00771       if (option_debug)
00772          ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
00773       if (chan->pvt->hangup)
00774          res = chan->pvt->hangup(chan);
00775    } else
00776       if (option_debug)
00777          ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
00778          
00779    ast_mutex_unlock(&chan->lock);
00780    manager_event(EVENT_FLAG_CALL, "Hangup", 
00781          "Channel: %s\r\n"
00782          "Uniqueid: %s\r\n"
00783          "Cause: %i\r\n",
00784          chan->name, chan->uniqueid, chan->hangupcause);
00785    ast_channel_free(chan);
00786    return res;
00787 }

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

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

01441 {
01442    int res = -1;
01443    /* Stop if we're a zombie or need a soft hangup */
01444    if (chan->zombie || ast_check_hangup(chan)) 
01445       return -1;
01446    ast_mutex_lock(&chan->lock);
01447    if (chan->pvt->indicate)
01448       res = chan->pvt->indicate(chan, condition);
01449    ast_mutex_unlock(&chan->lock);
01450    if (!chan->pvt->indicate || res) {
01451       /*
01452        * Device does not support (that) indication, lets fake
01453        * it by doing our own tone generation. (PM2002)
01454        */
01455       if (condition >= 0) {
01456          const struct tone_zone_sound *ts = NULL;
01457          switch (condition) {
01458           case AST_CONTROL_RINGING:
01459             ts = ast_get_indication_tone(chan->zone, "ring");
01460             break;
01461           case AST_CONTROL_BUSY:
01462             ts = ast_get_indication_tone(chan->zone, "busy");
01463             break;
01464           case AST_CONTROL_CONGESTION:
01465             ts = ast_get_indication_tone(chan->zone, "congestion");
01466             break;
01467          }
01468          if (ts && ts->data[0]) {
01469             ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
01470             ast_playtones_start(chan,0,ts->data, 1);
01471             res = 0;
01472          } else if (condition == AST_CONTROL_PROGRESS) {
01473             /* ast_playtones_stop(chan); */
01474          } else if (condition == AST_CONTROL_PROCEEDING) {
01475             /* Do nothing, really */
01476          } else {
01477             /* not handled */
01478             ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
01479             res = -1;
01480          }
01481       }
01482       else ast_playtones_stop(chan);
01483    }
01484    return res;
01485 }

AST_MUTEX_DEFINE_STATIC chlock   ) 
 

AST_MUTEX_DEFINE_STATIC uniquelock   ) 
 

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

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

Referenced by ast_device_state().

01943 {
01944    char name[AST_CHANNEL_NAME] = "";
01945    char *cut;
01946    struct ast_channel *chan;
01947 
01948    chan = ast_channel_walk_locked(NULL);
01949    while (chan) {
01950       strncpy(name, chan->name, sizeof(name)-1);
01951       ast_mutex_unlock(&chan->lock);
01952       cut = strchr(name,'-');
01953       if (cut)
01954               *cut = 0;
01955       if (!strcmp(name, device)) {
01956           if (chan->_state == AST_STATE_RINGING)
01957          return AST_DEVICE_RINGING;
01958           else          
01959               return AST_DEVICE_INUSE;
01960       }
01961       chan = ast_channel_walk_locked(chan);
01962    }
01963    return AST_DEVICE_UNKNOWN;
01964 }

int ast_prod struct ast_channel chan  ) 
 

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

01579 {
01580    struct ast_frame a = { AST_FRAME_VOICE };
01581    char nothing[128];
01582    /* Send an empty audio frame to get things moving */
01583    if (chan->_state != AST_STATE_UP) {
01584       ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
01585       a.subclass = chan->pvt->rawwriteformat;
01586       a.data = nothing + AST_FRIENDLY_OFFSET;
01587       if (ast_write(chan, &a))
01588          ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name);
01589    }
01590    return 0;
01591 }

int ast_queue_control struct ast_channel chan,
int  control
 

Definition at line 454 of file channel.c.

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

00455 {
00456    struct ast_frame f = { AST_FRAME_CONTROL, };
00457    f.subclass = control;
00458    return ast_queue_frame(chan, &f);
00459 }

int ast_queue_frame struct ast_channel chan,
struct ast_frame f
 

Queue an outgoing frame

Definition at line 390 of file channel.c.

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

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

00391 {
00392    struct ast_frame *f;
00393    struct ast_frame *prev, *cur;
00394    int blah = 1;
00395    int qlen = 0;
00396    /* Build us a copy and free the original one */
00397    f = ast_frdup(fin);
00398    if (!f) {
00399       ast_log(LOG_WARNING, "Unable to duplicate frame\n");
00400       return -1;
00401    }
00402    ast_mutex_lock(&chan->lock);
00403    prev = NULL;
00404    cur = chan->pvt->readq;
00405    while(cur) {
00406       if ((cur->frametype == AST_FRAME_CONTROL) && (cur->subclass == AST_CONTROL_HANGUP)) {
00407          /* Don't bother actually queueing anything after a hangup */
00408          ast_frfree(f);
00409          ast_mutex_unlock(&chan->lock);
00410          return 0;
00411       }
00412       prev = cur;
00413       cur = cur->next;
00414       qlen++;
00415    }
00416    /* Allow up to 96 voice frames outstanding, and up to 128 total frames */
00417    if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen  > 128)) {
00418       if (fin->frametype != AST_FRAME_VOICE) {
00419          ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
00420          CRASH;
00421       } else {
00422          ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name);
00423          ast_frfree(f);
00424          ast_mutex_unlock(&chan->lock);
00425          return 0;
00426       }
00427    }
00428    if (prev)
00429       prev->next = f;
00430    else
00431       chan->pvt->readq = f;
00432    if (chan->pvt->alertpipe[1] > -1) {
00433       if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah))
00434          ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
00435             chan->name, f->frametype, f->subclass, qlen, strerror(errno));
00436 #ifdef ZAPTEL_OPTIMIZATIONS
00437    } else if (chan->timingfd > -1) {
00438       ioctl(chan->timingfd, ZT_TIMERPING, &blah);
00439 #endif            
00440    } else if (chan->blocking) {
00441       pthread_kill(chan->blocker, SIGURG);
00442    }
00443    ast_mutex_unlock(&chan->lock);
00444    return 0;
00445 }

int ast_queue_hangup struct ast_channel chan  ) 
 

Definition at line 447 of file channel.c.

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

00448 {
00449    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
00450    chan->_softhangup |= AST_SOFTHANGUP_DEV;
00451    return ast_queue_frame(chan, &f);
00452 }

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

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

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

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

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

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

Referenced by ast_app_getdata().

02041 {
02042    int pos=0;
02043    int to = ftimeout;
02044    char d;
02045    /* XXX Merge with full version? XXX */
02046    /* Stop if we're a zombie or need a soft hangup */
02047    if (c->zombie || ast_check_hangup(c)) 
02048       return -1;
02049    if (!len)
02050       return -1;
02051    do {
02052       if (c->stream) {
02053          d = ast_waitstream(c, AST_DIGIT_ANY);
02054          ast_stopstream(c);
02055          usleep(1000);
02056          if (!d)
02057             d = ast_waitfordigit(c, to);
02058       } else {
02059          d = ast_waitfordigit(c, to);
02060       }
02061       if (d < 0)
02062          return -1;
02063       if (d == 0) {
02064          s[pos]='\0';
02065          return 1;
02066       }
02067       if (!strchr(enders, d))
02068          s[pos++] = d;
02069       if (strchr(enders, d) || (pos >= len)) {
02070          s[pos]='\0';
02071          return 0;
02072       }
02073       to = timeout;
02074    } while(1);
02075    /* Never reached */
02076    return 0;
02077 }

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

References ast_check_hangup(), AST_DIGIT_ANY, ast_stopstream(), ast_waitfordigit_full(), and ast_waitstream_full().

Referenced by ast_app_getdata_full().

02080 {
02081    int pos=0;
02082    int to = ftimeout;
02083    char d;
02084    /* Stop if we're a zombie or need a soft hangup */
02085    if (c->zombie || ast_check_hangup(c)) 
02086       return -1;
02087    if (!len)
02088       return -1;
02089    do {
02090       if (c->stream) {
02091          d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
02092          ast_stopstream(c);
02093          usleep(1000);
02094          if (!d)
02095             d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02096       } else {
02097          d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02098       }
02099       if (d < 0)
02100          return -1;
02101       if (d == 0) {
02102          s[pos]='\0';
02103          return 1;
02104       }
02105       if (d == 1) {
02106          s[pos]='\0';
02107          return 2;
02108       }
02109       if (!strchr(enders, d))
02110          s[pos++] = d;
02111       if (strchr(enders, d) || (pos >= len)) {
02112          s[pos]='\0';
02113          return 0;
02114       }
02115       to = timeout;
02116    } while(1);
02117    /* Never reached */
02118    return 0;
02119 }

int ast_recvchar struct ast_channel chan,
int  timeout
 

Definition at line 1487 of file channel.c.

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

01488 {
01489    int res,ourto,c;
01490    struct ast_frame *f;
01491    
01492    ourto = timeout;
01493    for(;;)
01494       {
01495       if (ast_check_hangup(chan)) return -1;
01496       res = ast_waitfor(chan,ourto);
01497       if (res <= 0) /* if timeout */
01498          {
01499          return 0;
01500          }
01501       ourto = res;
01502       f = ast_read(chan);
01503       if (f == NULL) return -1; /* if hangup */
01504       if ((f->frametype == AST_FRAME_CONTROL) &&
01505           (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
01506       if (f->frametype == AST_FRAME_TEXT)  /* if a text frame */
01507          {
01508          c = *((char *)f->data);  /* get the data */
01509          ast_frfree(f);
01510          return(c);
01511          }
01512       ast_frfree(f);
01513    }
01514 }

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

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

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

Referenced by __ast_request_and_dial().

01897 {
01898    struct chanlist *chan;
01899    struct ast_channel *c = NULL;
01900    int capabilities;
01901    int fmt;
01902    int res;
01903    if (ast_mutex_lock(&chlock)) {
01904       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01905       return NULL;
01906    }
01907    chan = backends;
01908    while(chan) {
01909       if (!strcasecmp(type, chan->type)) {
01910          capabilities = chan->capabilities;
01911          fmt = format;
01912          res = ast_translator_best_choice(&fmt, &capabilities);
01913          if (res < 0) {
01914             ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
01915             ast_mutex_unlock(&chlock);
01916             return NULL;
01917          }
01918          ast_mutex_unlock(&chlock);
01919          if (chan->requester)
01920             c = chan->requester(type, capabilities, data);
01921          if (c) {
01922             if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
01923             if (c->_state == AST_STATE_DOWN) {
01924                manager_event(EVENT_FLAG_CALL, "Newchannel",
01925                "Channel: %s\r\n"
01926                "State: %s\r\n"
01927                "CallerID: %s\r\n"
01928                "Uniqueid: %s\r\n",
01929                c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid);
01930             }
01931          }
01932          return c;
01933       }
01934       chan = chan->next;
01935    }
01936    if (!chan)
01937       ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
01938    ast_mutex_unlock(&chlock);
01939    return c;
01940 }

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

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

References __ast_request_and_dial().

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

01892 {
01893    return __ast_request_and_dial(type, format, data, timeout, outstate, 0, callerid, NULL, uniqueid);
01894 }

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

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

Referenced by ast_dtmf_stream().

00578 {
00579    struct ast_frame *f;
00580    while(ms > 0) {
00581       ms = ast_waitfor(chan, ms);
00582       if (ms <0)
00583          return -1;
00584       if (ms > 0) {
00585          f = ast_read(chan);
00586          if (!f)
00587             return -1;
00588          ast_frfree(f);
00589       }
00590    }
00591    return 0;
00592 }

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

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

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

Definition at line 556 of file channel.c.

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

00558 {
00559    struct ast_frame *f;
00560 
00561    while(ms > 0) {
00562       if( cond && ((*cond)(data) == 0 ) )
00563          return 0;
00564       ms = ast_waitfor(chan, ms);
00565       if (ms <0)
00566          return -1;
00567       if (ms > 0) {
00568          f = ast_read(chan);
00569          if (!f)
00570             return -1;
00571          ast_frfree(f);
00572       }
00573    }
00574    return 0;
00575 }

int ast_senddigit struct ast_channel chan,
char  digit
 

Receives a text character from a channel.

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

Definition at line 1573 of file channel.c.

01574 {
01575    return do_senddigit(chan, digit);
01576 }

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

References ast_check_hangup(), CHECK_BLOCKING, and ast_channel::zombie.

01517 {
01518    int res = 0;
01519    /* Stop if we're a zombie or need a soft hangup */
01520    if (chan->zombie || ast_check_hangup(chan)) 
01521       return -1;
01522    CHECK_BLOCKING(chan);
01523    if (chan->pvt->send_text)
01524       res = chan->pvt->send_text(chan, text);
01525    chan->blocking = 0;
01526    return res;
01527 }

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

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

02476 {
02477    if (chan->callerid)
02478       free(chan->callerid);
02479    if (anitoo && chan->ani)
02480       free(chan->ani);
02481    if (callerid) {
02482       chan->callerid = strdup(callerid);
02483       if (anitoo)
02484          chan->ani = strdup(callerid);
02485    } else {
02486       chan->callerid = NULL;
02487       if (anitoo)
02488          chan->ani = NULL;
02489    }
02490    if (chan->cdr)
02491       ast_cdr_setcid(chan->cdr, chan);
02492    manager_event(EVENT_FLAG_CALL, "Newcallerid", 
02493             "Channel: %s\r\n"
02494             "CallerID: %s\r\n"
02495             "Uniqueid: %s\r\n",
02496             chan->name, chan->callerid ? 
02497             chan->callerid : "<Unknown>",
02498             chan->uniqueid);
02499 }

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

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

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

01746 {
01747    int fmt;
01748    int native;
01749    int res;
01750    
01751    ast_mutex_lock(&chan->lock);
01752    native = chan->nativeformats;
01753    fmt = fmts;
01754    /* Find a translation path from the native read format to one of the user's read formats */
01755    res = ast_translator_best_choice(&fmt, &native);
01756    if (res < 0) {
01757       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01758          ast_getformatname(chan->nativeformats), ast_getformatname(fmts));
01759       ast_mutex_unlock(&chan->lock);
01760       return -1;
01761    }
01762    
01763    /* Now we have a good choice for both.  We'll write using our native format. */
01764    chan->pvt->rawreadformat = native;
01765    /* User perspective is fmt */
01766    chan->readformat = fmt;
01767    /* Free any read translation we have right now */
01768    if (chan->pvt->readtrans)
01769       ast_translator_free_path(chan->pvt->readtrans);
01770    /* Build a translation path from the raw read format to the user reading format */
01771    chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
01772    if (option_debug)
01773       ast_log(LOG_DEBUG, "Set channel %s to read format %s\n", 
01774          chan->name, ast_getformatname(chan->readformat));
01775    ast_mutex_unlock(&chan->lock);
01776    return 0;
01777 }

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

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

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

01713 {
01714    int fmt;
01715    int native;
01716    int res;
01717    
01718    ast_mutex_lock(&chan->lock);
01719    native = chan->nativeformats;
01720    fmt = fmts;
01721    
01722    res = ast_translator_best_choice(&native, &fmt);
01723    if (res < 0) {
01724       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01725          ast_getformatname(fmts), ast_getformatname(chan->nativeformats));
01726       ast_mutex_unlock(&chan->lock);
01727       return -1;
01728    }
01729    
01730    /* Now we have a good choice for both.  We'll write using our native format. */
01731    chan->pvt->rawwriteformat = native;
01732    /* User perspective is fmt */
01733    chan->writeformat = fmt;
01734    /* Free any write translation we have right now */
01735    if (chan->pvt->writetrans)
01736       ast_translator_free_path(chan->pvt->writetrans);
01737    /* Build a translation path from the user write format to the raw writing format */
01738    chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
01739    if (option_debug)
01740       ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat));
01741    ast_mutex_unlock(&chan->lock);
01742    return 0;
01743 }

int ast_setstate struct ast_channel chan,
int  state
 

Change the state of a channel

Definition at line 2501 of file channel.c.

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

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

02502 {
02503    if (chan->_state != state) {
02504       int oldstate = chan->_state;
02505       chan->_state = state;
02506       if (oldstate == AST_STATE_DOWN) {
02507          ast_device_state_changed(chan->name);
02508          manager_event(EVENT_FLAG_CALL, "Newchannel",
02509          "Channel: %s\r\n"
02510          "State: %s\r\n"
02511          "CallerID: %s\r\n"
02512          "Uniqueid: %s\r\n",
02513          chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02514       } else {
02515          ast_device_state_changed(chan->name);
02516          manager_event(EVENT_FLAG_CALL, "Newstate", 
02517             "Channel: %s\r\n"
02518             "State: %s\r\n"
02519             "CallerID: %s\r\n"
02520             "Uniqueid: %s\r\n",
02521             chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02522       }
02523    }
02524    return 0;
02525 }

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

Definition at line 1152 of file channel.c.

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

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

01153 {
01154    int res = -1;
01155 #ifdef ZAPTEL_OPTIMIZATIONS
01156    if (c->timingfd > -1) {
01157       if (!func) {
01158          samples = 0;
01159          data = 0;
01160       }
01161       ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples);
01162       res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples);
01163       c->timingfunc = func;
01164       c->timingdata = data;
01165    }
01166 #endif   
01167    return res;
01168 }

int ast_shutting_down void   ) 
 

Returns non-zero if Asterisk is being shut down

Definition at line 142 of file channel.c.

00143 {
00144    return shutting_down;
00145 }

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

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

Referenced by ast_begin_shutdown().

00702 {
00703    int res;
00704    ast_mutex_lock(&chan->lock);
00705    res = ast_softhangup_nolock(chan, cause);
00706    ast_mutex_unlock(&chan->lock);
00707    return res;
00708 }

int ast_softhangup_nolock struct ast_channel chan,
int  cause
 

Definition at line 686 of file channel.c.

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

Referenced by ast_async_goto(), and ast_softhangup().

00687 {
00688    int res = 0;
00689    struct ast_frame f = { AST_FRAME_NULL };
00690    if (option_debug)
00691       ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name);
00692    /* Inform channel driver that we need to be hung up, if it cares */
00693    chan->_softhangup |= cause;
00694    ast_queue_frame(chan, &f);
00695    /* Interrupt any poll call or such */
00696    if (chan->blocking)
00697       pthread_kill(chan->blocker, SIGURG);
00698    return res;
00699 }

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

00209 {
00210    /* XXX Not reentrant XXX */
00211    static char localtmp[256];
00212    switch(state) {
00213    case AST_STATE_DOWN:
00214       return "Down";
00215    case AST_STATE_RESERVED:
00216       return "Rsrvd";
00217    case AST_STATE_OFFHOOK:
00218       return "OffHook";
00219    case AST_STATE_DIALING:
00220       return "Dialing";
00221    case AST_STATE_RING:
00222       return "Ring";
00223    case AST_STATE_RINGING:
00224       return "Ringing";
00225    case AST_STATE_UP:
00226       return "Up";
00227    case AST_STATE_BUSY:
00228       return "Busy";
00229    default:
00230       snprintf(localtmp, sizeof(localtmp), "Unknown (%d)\n", state);
00231       return localtmp;
00232    }
00233 }

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

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

02937 {
02938    struct ast_frame *f;
02939    int res;
02940    if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
02941       return res;
02942 
02943    /* Give us some wiggle room */
02944    while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
02945       f = ast_read(chan);
02946       if (f)
02947          ast_frfree(f);
02948       else
02949          return -1;
02950    }
02951    return 0;
02952 }

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

Start a tone going

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

02917 {
02918    struct tonepair_def d = { 0, };
02919    d.freq1 = freq1;
02920    d.freq2 = freq2;
02921    d.duration = duration;
02922    if (vol < 1)
02923       d.vol = 8192;
02924    else
02925       d.vol = vol;
02926    if (ast_activate_generator(chan, &tonepair, &d))
02927       return -1;
02928    return 0;
02929 }

void ast_tonepair_stop struct ast_channel chan  ) 
 

Stop a tone from playing

Definition at line 2931 of file channel.c.

References ast_deactivate_generator().

02932 {
02933    ast_deactivate_generator(chan);
02934 }

int ast_transfer struct ast_channel chan,
char *  dest
 

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

02021 {
02022    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
02023       If the remote end does not answer within the timeout, then do NOT hang up, but 
02024       return anyway.  */
02025    int res = -1;
02026    /* Stop if we're a zombie or need a soft hangup */
02027    ast_mutex_lock(&chan->lock);
02028    if (!chan->zombie && !ast_check_hangup(chan)) {
02029       if (chan->pvt->transfer) {
02030          res = chan->pvt->transfer(chan, dest);
02031          if (!res)
02032             res = 1;
02033       } else
02034          res = 0;
02035    }
02036    ast_mutex_unlock(&chan->lock);
02037    return res;
02038 }

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

References ast_waitfor_n().

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

01112 {
01113    struct ast_channel *chan;
01114    int oldms = ms;
01115    chan = ast_waitfor_n(&c, 1, &ms);
01116    if (ms < 0) {
01117       if (oldms < 0)
01118          return 0;
01119       else
01120          return -1;
01121    }
01122    return ms;
01123 }

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

References ast_waitfor_nandfds().

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

01107 {
01108    return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
01109 }

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

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

00903 {
00904    /* Wait for x amount of time on a file descriptor to have input.  */
00905    struct timeval start, now;
00906    int res;
00907    int x, y;
00908    int winner = -1;
00909    int spoint;
00910    struct pollfd *pfds;
00911    
00912    pfds = alloca(sizeof(struct pollfd) * n);
00913    if (!pfds) {
00914       ast_log(LOG_WARNING, "alloca failed!  bad things will happen.\n");
00915       return -1;
00916    }
00917    if (*ms > 0)
00918       gettimeofday(&start, NULL);
00919    y = 0;
00920    for (x=0;x<n;x++) {
00921       if (fds[x] > -1) {
00922          pfds[y].fd = fds[x];
00923          pfds[y].events = POLLIN | POLLPRI;
00924          y++;
00925       }
00926    }
00927    res = poll(pfds, y, *ms);
00928    if (res < 0) {
00929       /* Simulate a timeout if we were interrupted */
00930       if (errno != EINTR)
00931          *ms = -1;
00932       else
00933          *ms = 0;
00934       return -1;
00935    }
00936    spoint = 0;
00937    for (x=0;x<n;x++) {
00938       if (fds[x] > -1) {
00939          if ((res = ast_fdisset(pfds, fds[x], y, &spoint))) {
00940             winner = fds[x];
00941             if (exception) {
00942                if (res & POLLPRI)
00943                   *exception = -1;
00944                else
00945                   *exception = 0;
00946             }
00947          }
00948       }
00949    }
00950    if (*ms > 0) {
00951       long passed;
00952       gettimeofday(&now, NULL);
00953       passed = (now.tv_sec - start.tv_sec) * 1000;
00954       passed += (now.tv_usec - start.tv_usec) / 1000;
00955       if (passed <= *ms)
00956          *ms -= passed;
00957       else
00958          *ms = 0;
00959    }
00960    return winner;
00961 }

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

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

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

00965 {
00966    /* Wait for x amount of time on a file descriptor to have input.  */
00967    struct timeval start, end;
00968    struct pollfd *pfds;
00969    int res;
00970    long rms;
00971    int x, y, max;
00972    int spoint;
00973    time_t now = 0;
00974    long whentohangup = 0, havewhen = 0, diff;
00975    struct ast_channel *winner = NULL;
00976 
00977    pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds));
00978    if (!pfds) {
00979       ast_log(LOG_WARNING, "alloca failed!  bad things will happen.\n");
00980       *outfd = -1;
00981       return NULL;
00982    }
00983 
00984    if (outfd)
00985       *outfd = -99999;
00986    if (exception)
00987       *exception = 0;
00988    
00989    /* Perform any pending masquerades */
00990    for (x=0;x<n;x++) {
00991       ast_mutex_lock(&c[x]->lock);
00992       if (c[x]->whentohangup) {
00993          if (!havewhen)
00994             time(&now);
00995          diff = c[x]->whentohangup - now;
00996          if (!havewhen || (diff < whentohangup)) {
00997             havewhen++;
00998             whentohangup = diff;
00999          }
01000       }
01001       if (c[x]->masq) {
01002          if (ast_do_masquerade(c[x])) {
01003             ast_log(LOG_WARNING, "Masquerade failed\n");
01004             *ms = -1;
01005             ast_mutex_unlock(&c[x]->lock);
01006             return NULL;
01007          }
01008       }
01009       ast_mutex_unlock(&c[x]->lock);
01010    }
01011 
01012    rms = *ms;
01013    
01014    if (havewhen) {
01015       if ((*ms < 0) || (whentohangup * 1000 < *ms)) {
01016          rms =  whentohangup * 1000;
01017       }
01018    }
01019    max = 0;
01020    for (x=0;x<n;x++) {
01021       for (y=0;y<AST_MAX_FDS;y++) {
01022          if (c[x]->fds[y] > -1) {
01023             pfds[max].fd = c[x]->fds[y];
01024             pfds[max].events = POLLIN | POLLPRI;
01025             max++;
01026          }
01027       }
01028       CHECK_BLOCKING(c[x]);
01029    }
01030    for (x=0;x<nfds; x++) {
01031       if (fds[x] > -1) {
01032          pfds[max].fd = fds[x];
01033          pfds[max].events = POLLIN | POLLPRI;
01034          max++;
01035       }
01036    }
01037    if (*ms > 0) 
01038       gettimeofday(&start, NULL);
01039    res = poll(pfds, max, rms);
01040    if (res < 0) {
01041       for (x=0;x<n;x++) 
01042          c[x]->blocking = 0;
01043       /* Simulate a timeout if we were interrupted */
01044       if (errno != EINTR)
01045          *ms = -1;
01046       else {
01047          /* Just an interrupt */
01048 #if 0
01049          *ms = 0;
01050 #endif         
01051       }
01052       return NULL;
01053    }
01054 
01055    if (havewhen)
01056       time(&now);
01057    spoint = 0;
01058    for (x=0;x<n;x++) {
01059       c[x]->blocking = 0;
01060       if (havewhen && c[x]->whentohangup && (now > c[x]->whentohangup)) {
01061          c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
01062          if (!winner)
01063             winner = c[x];
01064       }
01065       for (y=0;y<AST_MAX_FDS;y++) {
01066          if (c[x]->fds[y] > -1) {
01067             if ((res = ast_fdisset(pfds, c[x]->fds[y], max, &spoint))) {
01068                if (res & POLLPRI)
01069                   c[x]->exception = -1;
01070                else
01071                   c[x]->exception = 0;
01072                c[x]->fdno = y;
01073                winner = c[x];
01074             }
01075          }
01076       }
01077    }
01078    for (x=0;x<nfds;x++) {
01079       if (fds[x] > -1) {
01080          if ((res = ast_fdisset(pfds, fds[x], max, &spoint))) {
01081             if (outfd)
01082                *outfd = fds[x];
01083             if (exception) {  
01084                if (res & POLLPRI) 
01085                   *exception = -1;
01086                else
01087                   *exception = 0;
01088             }
01089             winner = NULL;
01090          }
01091       }  
01092    }
01093    if (*ms > 0) {
01094       long diff;
01095       gettimeofday(&end, NULL);
01096       diff = (end.tv_sec - start.tv_sec) * 1000;
01097       diff += (end.tv_usec - start.tv_usec) / 1000;
01098       if (diff < *ms)
01099          *ms -= diff;
01100       else
01101          *ms = 0;
01102    }
01103    return winner;
01104 }

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

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

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

01126 {
01127    /* XXX Should I be merged with waitfordigit_full XXX */
01128    struct ast_frame *f;
01129    char result = 0;
01130    /* Stop if we're a zombie or need a soft hangup */
01131    if (c->zombie || ast_check_hangup(c)) 
01132       return -1;
01133    /* Wait for a digit, no more than ms milliseconds total. */
01134    while(ms && !result) {
01135       ms = ast_waitfor(c, ms);
01136       if (ms < 0) /* Error */
01137          result = -1; 
01138       else if (ms > 0) {
01139          /* Read something */
01140          f = ast_read(c);
01141          if (f) {
01142             if (f->frametype == AST_FRAME_DTMF) 
01143                result = f->subclass;
01144             ast_frfree(f);
01145          } else
01146             result = -1;
01147       }
01148    }
01149    return result;
01150 }

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

Definition at line 1169 of file channel.c.

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

Referenced by ast_readstring_full().

01170 {
01171    struct ast_frame *f;
01172    struct ast_channel *rchan;
01173    int outfd;
01174    int res;
01175    /* Stop if we're a zombie or need a soft hangup */
01176    if (c->zombie || ast_check_hangup(c)) 
01177       return -1;
01178    /* Wait for a digit, no more than ms milliseconds total. */
01179    while(ms) {
01180       rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01181       if ((!rchan) && (outfd < 0) && (ms)) { 
01182          ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01183          return -1;
01184       } else if (outfd > -1) {
01185          /* The FD we were watching has something waiting */
01186          return 1;
01187       } else if (rchan) {
01188          f = ast_read(c);
01189          if(!f) {
01190             return -1;
01191          }
01192 
01193          switch(f->frametype) {
01194          case AST_FRAME_DTMF:
01195             res = f->subclass;
01196             ast_frfree(f);
01197             return res;
01198          case AST_FRAME_CONTROL:
01199             switch(f->subclass) {
01200             case AST_CONTROL_HANGUP:
01201                ast_frfree(f);
01202                return -1;
01203             case AST_CONTROL_RINGING:
01204             case AST_CONTROL_ANSWER:
01205                /* Unimportant */
01206                break;
01207             default:
01208                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass);
01209             }
01210          case AST_FRAME_VOICE:
01211             /* Write audio if appropriate */
01212             if (audiofd > -1)
01213                write(audiofd, f->data, f->datalen);
01214          }
01215          /* Ignore */
01216          ast_frfree(f);
01217       }
01218    }
01219    return 0; // Time is up
01220 }

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

References ast_check_hangup(), ast_deactivate_generator(), ast_do_masquerade(), 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(), CHECK_BLOCKING, ast_frame::data, ast_frame::frametype, LOG_WARNING, ast_frame::samples, SEEK_FORCECUR, and ast_frame::subclass.

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

01605 {
01606    int res = -1;
01607    struct ast_frame *f = NULL;
01608    /* Stop if we're a zombie or need a soft hangup */
01609    ast_mutex_lock(&chan->lock);
01610    if (chan->zombie || ast_check_hangup(chan))  {
01611       ast_mutex_unlock(&chan->lock);
01612       return -1;
01613    }
01614    /* Handle any pending masquerades */
01615    if (chan->masq) {
01616       if (ast_do_masquerade(chan)) {
01617          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01618          ast_mutex_unlock(&chan->lock);
01619          return -1;
01620       }
01621    }
01622    if (chan->masqr) {
01623       ast_mutex_unlock(&chan->lock);
01624       return 0;
01625    }
01626    if (chan->generatordata) {
01627       if (chan->writeinterrupt)
01628          ast_deactivate_generator(chan);
01629       else {
01630          ast_mutex_unlock(&chan->lock);
01631          return 0;
01632       }
01633    }
01634    if (chan->fout & 0x80000000)
01635       ast_frame_dump(chan->name, fr, ">>");
01636    CHECK_BLOCKING(chan);
01637    switch(fr->frametype) {
01638    case AST_FRAME_CONTROL:
01639       /* XXX Interpret control frames XXX */
01640       ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
01641       break;
01642    case AST_FRAME_DTMF:
01643       chan->blocking = 0;
01644       ast_mutex_unlock(&chan->lock);
01645       res = do_senddigit(chan,fr->subclass);
01646       ast_mutex_lock(&chan->lock);
01647       CHECK_BLOCKING(chan);
01648       break;
01649    case AST_FRAME_TEXT:
01650       if (chan->pvt->send_text)
01651          res = chan->pvt->send_text(chan, (char *) fr->data);
01652       break;
01653    case AST_FRAME_VIDEO:
01654       /* XXX Handle translation of video codecs one day XXX */
01655       if (chan->pvt->write_video)
01656          res = chan->pvt->write_video(chan, fr);
01657       else
01658          res = 0;
01659       break;
01660    default:
01661       if (chan->pvt->write) {
01662          if (chan->pvt->writetrans) {
01663             f = ast_translate(chan->pvt->writetrans, fr, 0);
01664          } else
01665             f = fr;
01666          if (f) {
01667             res = chan->pvt->write(chan, f);
01668             if( chan->monitor &&
01669                   chan->monitor->write_stream &&
01670                   f && ( f->frametype == AST_FRAME_VOICE ) ) {
01671 #ifndef MONITOR_CONSTANT_DELAY
01672                int jump = chan->insmpl - chan->outsmpl - 2 * f->samples;
01673                if (jump >= 0) {
01674                   if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01675                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01676                   chan->outsmpl += jump + 2 * f->samples;
01677                } else
01678                   chan->outsmpl += f->samples;
01679 #else
01680                int jump = chan->insmpl - chan->outsmpl;
01681                if (jump - MONITOR_DELAY >= 0) {
01682                   if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01683                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01684                   chan->outsmpl += jump;
01685                } else
01686                   chan->outsmpl += f->samples;
01687 #endif
01688             if (ast_writestream(chan->monitor->write_stream, f) < 0)
01689                   ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
01690             }
01691          } else
01692             res = 0;
01693       }
01694    }
01695    if (f && (f != fr))
01696       ast_frfree(f);
01697    chan->blocking = 0;
01698    /* Consider a write failure to force a soft hangup */
01699    if (res < 0)
01700       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01701    else {
01702       if ((chan->fout & 0x7fffffff) == 0x7fffffff)
01703          chan->fout &= 0x80000000;
01704       else
01705          chan->fout++;
01706       chan->fout++;
01707    }
01708    ast_mutex_unlock(&chan->lock);
01709    return res;
01710 }

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

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

01594 {
01595    int res;
01596    if (!chan->pvt->write_video)
01597       return 0;
01598    res = ast_write(chan, fr);
01599    if (!res)
01600       res = 1;
01601    return res;
01602 }


Variable Documentation

int ast_mainpid
 

Definition at line 87 of file asterisk.c.

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


Generated on Thu Nov 29 22:50:25 2007 for Asterisk by  doxygen 1.4.2