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

channel.c File Reference

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

Go to the source code of this file.

Data Structures

struct  chanlist
struct  tonepair_def
struct  tonepair_state

Functions

int ast_check_hangup (struct ast_channel *chan)
 Check to see if a channel is needing hang up.

void ast_begin_shutdown (int hangup)
int ast_active_channels (void)
void ast_cancel_shutdown (void)
int ast_shutting_down (void)
void ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset)
 Set when to hang a channel up.

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

int ast_channel_register_ex (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data), int(*devicestate)(void *data))
char * ast_state2str (int state)
 Gives the string form of a given state.

int ast_best_codec (int fmts)
 Pick the best codec.

ast_channelast_channel_alloc (int needqueue)
 Create a channel structure.

int ast_queue_frame (struct ast_channel *chan, struct ast_frame *fin, int lock)
int ast_queue_hangup (struct ast_channel *chan, int lock)
int ast_queue_control (struct ast_channel *chan, int control, int lock)
int ast_channel_defer_dtmf (struct ast_channel *chan)
 Defers DTMF.

void ast_channel_undefer_dtmf (struct ast_channel *chan)
 Undeos a defer.

ast_channelast_channel_walk (struct ast_channel *prev)
 Browse channels in use.

int ast_safe_sleep_conditional (struct ast_channel *chan, int ms, int(*cond)(void *), void *data)
 Wait for a specied amount of time, looking for hangups and a condition argument.

int ast_safe_sleep (struct ast_channel *chan, int ms)
 Wait for a specied amount of time, looking for hangups.

void ast_channel_free (struct ast_channel *chan)
 Free a channel structure.

int ast_softhangup_nolock (struct ast_channel *chan, int cause)
int ast_softhangup (struct ast_channel *chan, int cause)
 Softly hangup up a channel.

int ast_hangup (struct ast_channel *chan)
 Hang up a channel.

void ast_channel_unregister (char *type)
 Unregister a channel class.

int ast_answer (struct ast_channel *chan)
 Answer a ringing call.

void ast_deactivate_generator (struct ast_channel *chan)
int ast_activate_generator (struct ast_channel *chan, struct ast_generator *gen, void *params)
int ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception)
 Waits for input on an fd.

ast_channelast_waitfor_nandfds (struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
 Waits for activity on a group of channels.

ast_channelast_waitfor_n (struct ast_channel **c, int n, int *ms)
 Waits for input on a group of channels.

int ast_waitfor (struct ast_channel *c, int ms)
 Wait for input on a channel.

char ast_waitfordigit (struct ast_channel *c, int ms)
 Waits for a digit.

int ast_settimeout (struct ast_channel *c, int samples, int(*func)(void *data), void *data)
char ast_waitfordigit_full (struct ast_channel *c, int ms, int audio, int ctrl)
ast_frameast_read (struct ast_channel *chan)
 Reads a frame.

int ast_indicate (struct ast_channel *chan, int condition)
 Indicates condition of channel.

int ast_recvchar (struct ast_channel *chan, int timeout)
 Receives a text character from a channel.

int ast_sendtext (struct ast_channel *chan, char *text)
 Sends text to a channel.

int ast_prod (struct ast_channel *chan)
int ast_write_video (struct ast_channel *chan, struct ast_frame *fr)
 Write video frame to a channel.

int ast_write (struct ast_channel *chan, struct ast_frame *fr)
 Write a frame to a channel.

int ast_set_write_format (struct ast_channel *chan, int fmts)
 Sets write format on channel chan.

int ast_set_read_format (struct ast_channel *chan, int fmts)
 Sets read format on channel chan.

ast_channelast_request_and_dial (char *type, int format, void *data, int timeout, int *outstate, char *callerid)
ast_channelast_request (char *type, int format, void *data)
 Requests a channel.

int ast_parse_device_state (char *device)
 Search the Channels by Name.

int ast_device_state (char *device)
 Asks a channel for device state.

int ast_call (struct ast_channel *chan, char *addr, int timeout)
 Make a call.

int ast_transfer (struct ast_channel *chan, char *dest)
int ast_readstring (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
 Reads multiple digits.

int ast_readstring_full (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
int ast_channel_supports_html (struct ast_channel *chan)
 Checks for HTML support on a channel.

int ast_channel_sendhtml (struct ast_channel *chan, int subclass, char *data, int datalen)
 Sends HTML on given channel.

int ast_channel_sendurl (struct ast_channel *chan, char *url)
 Sends a URL on a given link.

int ast_channel_make_compatible (struct ast_channel *chan, struct ast_channel *peer)
 Makes two channel formats compatible.

int ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone)
 Weird function made for call transfers.

void ast_change_name (struct ast_channel *chan, char *newname)
void ast_set_callerid (struct ast_channel *chan, char *callerid, int anitoo)
int ast_setstate (struct ast_channel *chan, int state)
int ast_channel_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
 Bridge two channels together.

int ast_channel_setoption (struct ast_channel *chan, int option, void *data, int datalen, int block)
 Sets an option on a channel.

int ast_tonepair_start (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
void ast_tonepair_stop (struct ast_channel *chan)
int ast_tonepair (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)

Variables

chanlistbackends
ast_channelchannels = NULL


Function Documentation

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

Activate a given generator

Definition at line 739 of file channel.c.

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

Referenced by ast_playtones_start(), and ast_tonepair_start().

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

int ast_active_channels void   ) 
 

Returns number of active/allocated channels

Definition at line 109 of file channel.c.

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

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

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

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

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

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

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

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

int ast_best_codec int  fmts  ) 
 

Pick the best codec.

Definition at line 222 of file channel.c.

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

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

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

01658 {
01659    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
01660       If the remote end does not answer within the timeout, then do NOT hang up, but 
01661       return anyway.  */
01662    int res = -1;
01663    /* Stop if we're a zombie or need a soft hangup */
01664    ast_mutex_lock(&chan->lock);
01665    if (!chan->zombie && !ast_check_hangup(chan)) 
01666       if (chan->pvt->call)
01667          res = chan->pvt->call(chan, addr, timeout);
01668    ast_mutex_unlock(&chan->lock);
01669    return res;
01670 }

void ast_cancel_shutdown void   ) 
 

Cancels an existing shutdown and returns to normal operation

Definition at line 123 of file channel.c.

00124 {
00125    shutting_down = 0;
00126 }

void ast_change_name struct ast_channel chan,
char *  newname
 

Definition at line 1866 of file channel.c.

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

01867 {
01868    char tmp[256];
01869    strncpy(tmp, chan->name, 256);
01870    strncpy(chan->name, newname, sizeof(chan->name) - 1);
01871    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid);
01872 }

struct ast_channel* ast_channel_alloc int  needalertpipe  ) 
 

Create a channel structure.

Returns NULL on failure to allocate

Definition at line 263 of file channel.c.

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

Referenced by ast_async_goto().

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

int ast_channel_bridge struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc
 

Bridge two channels together.

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

Definition at line 2121 of file channel.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, ast_channel_make_compatible(), ast_check_hangup(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_verbose(), ast_waitfor_n(), ast_write(), ast_channel::bridge, EVENT_FLAG_CALL, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::name, option_verbose, VERBOSE_PREFIX_3, and ast_channel::zombie.

02122 {
02123    /* Copy voice back and forth between the two channels.  Give the peer
02124       the ability to transfer calls with '#<extension' syntax. */
02125    struct ast_channel *cs[3];
02126    int to = -1;
02127    struct ast_frame *f;
02128    struct ast_channel *who = NULL;
02129    int res;
02130    int nativefailed=0;
02131 
02132    /* Stop if we're a zombie or need a soft hangup */
02133    if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 
02134       return -1;
02135    if (c0->bridge) {
02136       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02137          c0->name, c0->bridge->name);
02138       return -1;
02139    }
02140    if (c1->bridge) {
02141       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02142          c1->name, c1->bridge->name);
02143       return -1;
02144    }
02145    
02146    /* Keep track of bridge */
02147    c0->bridge = c1;
02148    c1->bridge = c0;
02149    cs[0] = c0;
02150    cs[1] = c1;
02151    
02152    manager_event(EVENT_FLAG_CALL, "Link", 
02153          "Channel1: %s\r\n"
02154          "Channel2: %s\r\n",
02155          c0->name, c1->name);
02156 
02157    for (/* ever */;;) {
02158       /* Stop if we're a zombie or need a soft hangup */
02159       if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
02160          *fo = NULL;
02161          if (who) *rc = who;
02162          res = 0;
02163          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");
02164          break;
02165       }
02166       if (c0->pvt->bridge && 
02167          (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
02168             /* Looks like they share a bridge code */
02169          if (option_verbose > 2) 
02170             ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
02171          if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
02172             c0->bridge = NULL;
02173             c1->bridge = NULL;
02174             manager_event(EVENT_FLAG_CALL, "Unlink", 
02175                "Channel1: %s\r\n"
02176                "Channel2: %s\r\n",
02177                c0->name, c1->name);
02178             ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
02179             return 0;
02180          }
02181          /* If they return non-zero then continue on normally.  Let "-2" mean don't worry about
02182             my not wanting to bridge */
02183          if ((res != -2) && (res != -3))
02184             ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
02185          if (res != -3) nativefailed++;
02186       }
02187    
02188          
02189       if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat)) &&
02190          !(c0->generator || c1->generator))  {
02191          if (ast_channel_make_compatible(c0, c1)) {
02192             ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
02193             manager_event(EVENT_FLAG_CALL, "Unlink", 
02194                "Channel1: %s\r\n"
02195                "Channel2: %s\r\n",
02196                c0->name, c1->name);
02197             return -1;
02198          }
02199       }
02200       who = ast_waitfor_n(cs, 2, &to);
02201       if (!who) {
02202          ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 
02203          continue;
02204       }
02205       f = ast_read(who);
02206       if (!f) {
02207          *fo = NULL;
02208          *rc = who;
02209          res = 0;
02210          ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
02211          break;
02212       }
02213 
02214       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02215          *fo = f;
02216          *rc = who;
02217          res =  0;
02218          ast_log(LOG_DEBUG, "Got a FRAME_CONTROL frame on channel %s\n",who->name);
02219          break;
02220       }
02221       if ((f->frametype == AST_FRAME_VOICE) ||
02222          (f->frametype == AST_FRAME_TEXT) ||
02223          (f->frametype == AST_FRAME_VIDEO) || 
02224          (f->frametype == AST_FRAME_IMAGE) ||
02225          (f->frametype == AST_FRAME_DTMF)) {
02226          if ((f->frametype == AST_FRAME_DTMF) && 
02227             (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
02228             if ((who == c0)) {
02229                if  ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
02230                   *rc = c0;
02231                   *fo = f;
02232                   /* Take out of conference mode */
02233                   res = 0;
02234                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
02235                   break;
02236                } else 
02237                   goto tackygoto;
02238             } else
02239             if ((who == c1)) {
02240                if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
02241                   *rc = c1;
02242                   *fo = f;
02243                   res =  0;
02244                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
02245                   break;
02246                } else
02247                   goto tackygoto;
02248             }
02249          } else {
02250 #if 0
02251             ast_log(LOG_DEBUG, "Read from %s\n", who->name);
02252             if (who == last) 
02253                ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
02254             last = who;
02255 #endif
02256 tackygoto:
02257             /* Don't copy packets if there is a generator on either one, since they're
02258                not supposed to be listening anyway */
02259             if (who == c0) 
02260                ast_write(c1, f);
02261             else 
02262                ast_write(c0, f);
02263          }
02264          ast_frfree(f);
02265       } else
02266          ast_frfree(f);
02267       /* Swap who gets priority */
02268       cs[2] = cs[0];
02269       cs[0] = cs[1];
02270       cs[1] = cs[2];
02271    }
02272    c0->bridge = NULL;
02273    c1->bridge = NULL;
02274    manager_event(EVENT_FLAG_CALL, "Unlink", 
02275                "Channel1: %s\r\n"
02276                "Channel2: %s\r\n",
02277                c0->name, c1->name);
02278    ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name);
02279    return res;
02280 }

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

References ast_channel::deferdtmf.

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

void ast_channel_free struct ast_channel chan  ) 
 

Free a channel structure.

Definition at line 489 of file channel.c.

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

Referenced by ast_hangup().

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

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

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

Referenced by ast_channel_bridge().

01795 {
01796    int peerf;
01797    int chanf;
01798    int res;
01799    peerf = peer->nativeformats;
01800    chanf = chan->nativeformats;
01801    res = ast_translator_best_choice(&peerf, &chanf);
01802    if (res < 0) {
01803       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
01804       return -1;
01805    }
01806    /* Set read format on channel */
01807    res = ast_set_read_format(chan, peerf);
01808    if (res < 0) {
01809       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
01810       return -1;
01811    }
01812    /* Set write format on peer channel */
01813    res = ast_set_write_format(peer, peerf);
01814    if (res < 0) {
01815       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
01816       return -1;
01817    }
01818    /* Now we go the other way */
01819    peerf = peer->nativeformats;
01820    chanf = chan->nativeformats;
01821    res = ast_translator_best_choice(&chanf, &peerf);
01822    if (res < 0) {
01823       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
01824       return -1;
01825    }
01826    /* Set writeformat on channel */
01827    res = ast_set_write_format(chan, chanf);
01828    if (res < 0) {
01829       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
01830       return -1;
01831    }
01832    /* Set read format on peer channel */
01833    res = ast_set_read_format(peer, chanf);
01834    if (res < 0) {
01835       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
01836       return -1;
01837    }
01838    return 0;
01839 }

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

Referenced by ast_async_goto().

01842 {
01843    struct ast_frame null = { AST_FRAME_NULL, };
01844    ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
01845       clone->name, original->name);
01846    if (original->masq) {
01847       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
01848          original->masq->name, original->name);
01849       return -1;
01850    }
01851    if (clone->masqr) {
01852       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
01853          clone->name, clone->masqr->name);
01854       return -1;
01855    }
01856    original->masq = clone;
01857    clone->masqr = original;
01858    /* XXX can't really hold the lock here, but at the same time, it' s
01859       not really safe not to XXX */
01860    ast_queue_frame(original, &null, 0);
01861    ast_queue_frame(clone, &null, 0);
01862    ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
01863    return 0;
01864 }

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

Registers a channel.

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

Definition at line 145 of file channel.c.

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

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

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

Definition at line 151 of file channel.c.

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

Referenced by ast_channel_register().

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

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

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

01781 {
01782    if (chan->pvt->send_html)
01783       return chan->pvt->send_html(chan, subclass, data, datalen);
01784    return -1;
01785 }

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

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

01788 {
01789    if (chan->pvt->send_html)
01790       return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
01791    return -1;
01792 }

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

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

02283 {
02284    int res;
02285    if (chan->pvt->setoption) {
02286       res = chan->pvt->setoption(chan, option, data, datalen);
02287       if (res < 0)
02288          return res;
02289    } else {
02290       errno = ENOSYS;
02291       return -1;
02292    }
02293    if (block) {
02294       /* XXX Implement blocking -- just wait for our option frame reply, discarding
02295          intermediate packets. XXX */
02296       ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
02297       return -1;
02298    }
02299    return 0;
02300 }

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

References ast_channel::whentohangup.

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

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

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

01774 {
01775    if (chan->pvt->send_html)
01776       return 1;
01777    return 0;
01778 }

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

References ast_channel::deferdtmf.

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

void ast_channel_unregister char *  type  ) 
 

Unregister a channel class.

Definition at line 677 of file channel.c.

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

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

struct ast_channel* ast_channel_walk struct ast_channel prev  ) 
 

Browse channels in use.

Parameters:
prev where you want to start in the channel list Browse the channels currently in use Returns the next channel in the list, NULL on end.

Definition at line 432 of file channel.c.

References ast_mutex_lock, ast_mutex_unlock, and channels.

Referenced by ast_async_goto_by_name(), and ast_parse_device_state().

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

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 68 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_sendtext(), ast_transfer(), ast_waitfordigit(), ast_waitfordigit_full(), and ast_write().

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

void ast_deactivate_generator struct ast_channel chan  ) 
 

Deactive an active generator

Definition at line 729 of file channel.c.

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

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

00730 {
00731    if (chan->generatordata) {
00732       chan->generator->release(chan, chan->generatordata);
00733       chan->generatordata = NULL;
00734       chan->generator = NULL;
00735       chan->writeinterrupt = 0;
00736    }
00737 }

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

References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_log(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parse_device_state(), backends, and LOG_WARNING.

01619 {
01620    char tech[AST_MAX_EXTENSION] = "";
01621    char *number;
01622    struct chanlist *chanls;
01623    int res = 0;
01624    
01625    strncpy(tech, device, sizeof(tech)-1);
01626    number = strchr(tech, '/');
01627    if (!number) {
01628        return AST_DEVICE_INVALID;
01629    }
01630    *number = 0;
01631    number++;
01632       
01633    if (ast_mutex_lock(&chlock)) {
01634       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01635       return -1;
01636    }
01637    chanls = backends;
01638    while(chanls) {
01639       if (!strcasecmp(tech, chanls->type)) {
01640          ast_mutex_unlock(&chlock);
01641          if (!chanls->devicestate) 
01642             return ast_parse_device_state(device);
01643          else {
01644             res = chanls->devicestate(number);
01645             if (res == AST_DEVICE_UNKNOWN)
01646                return ast_parse_device_state(device);
01647             else
01648                return res;
01649          }
01650       }
01651       chanls = chanls->next;
01652    }
01653    ast_mutex_unlock(&chlock);
01654    return AST_DEVICE_INVALID;
01655 }

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

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

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

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

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

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

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

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

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

Referenced by ast_device_state().

01600 {
01601    char name[AST_CHANNEL_NAME] = "";
01602    char *cut;
01603    struct ast_channel *chan;
01604 
01605    chan = ast_channel_walk(NULL);
01606    while (chan) {
01607       strncpy(name, chan->name, sizeof(name)-1);
01608       cut = strchr(name,'-');
01609       if (cut)
01610               *cut = 0;
01611       if (!strcmp(name, device))
01612               return AST_DEVICE_INUSE;
01613       chan = ast_channel_walk(chan);
01614    }
01615    return AST_DEVICE_UNKNOWN;
01616 }

int ast_prod struct ast_channel chan  ) 
 

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

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

int ast_queue_control struct ast_channel chan,
int  control,
int  lock
 

Definition at line 409 of file channel.c.

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

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

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

Queue an outgoing frame, locking if necessary

Definition at line 352 of file channel.c.

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

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

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

int ast_queue_hangup struct ast_channel chan,
int  lock
 

Definition at line 402 of file channel.c.

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

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

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

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

Referenced by ast_app_getvoice(), ast_async_goto(), ast_channel_bridge(), ast_recvchar(), ast_request_and_dial(), 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().

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

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

01693 {
01694    int pos=0;
01695    int to = ftimeout;
01696    char d;
01697    /* XXX Merge with full version? XXX */
01698    /* Stop if we're a zombie or need a soft hangup */
01699    if (c->zombie || ast_check_hangup(c)) 
01700       return -1;
01701    if (!len)
01702       return -1;
01703    do {
01704       if (c->stream) {
01705          d = ast_waitstream(c, AST_DIGIT_ANY);
01706          ast_stopstream(c);
01707          usleep(1000);
01708          if (!d)
01709             d = ast_waitfordigit(c, to);
01710       } else {
01711          d = ast_waitfordigit(c, to);
01712       }
01713       if (d < 0)
01714          return -1;
01715       if (d == 0) {
01716          s[pos]='\0';
01717          return 1;
01718       }
01719       if (!strchr(enders, d))
01720          s[pos++] = d;
01721       if (strchr(enders, d) || (pos >= len)) {
01722          s[pos]='\0';
01723          return 0;
01724       }
01725       to = timeout;
01726    } while(1);
01727    /* Never reached */
01728    return 0;
01729 }

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

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

Referenced by ast_app_getdata_full().

01732 {
01733    int pos=0;
01734    int to = ftimeout;
01735    char d;
01736    /* Stop if we're a zombie or need a soft hangup */
01737    if (c->zombie || ast_check_hangup(c)) 
01738       return -1;
01739    if (!len)
01740       return -1;
01741    do {
01742       if (c->stream) {
01743          d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
01744          ast_stopstream(c);
01745          usleep(1000);
01746          if (!d)
01747             d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
01748       } else {
01749          d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
01750       }
01751       if (d < 0)
01752          return -1;
01753       if (d == 0) {
01754          s[pos]='\0';
01755          return 1;
01756       }
01757       if (d == 1) {
01758          s[pos]='\0';
01759          return 2;
01760       }
01761       if (!strchr(enders, d))
01762          s[pos++] = d;
01763       if (strchr(enders, d) || (pos >= len)) {
01764          s[pos]='\0';
01765          return 0;
01766       }
01767       to = timeout;
01768    } while(1);
01769    /* Never reached */
01770    return 0;
01771 }

int ast_recvchar struct ast_channel chan,
int  timeout
 

Receives a text character from a channel.

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

Definition at line 1213 of file channel.c.

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

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

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

Requests a channel.

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

Definition at line 1554 of file channel.c.

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

Referenced by ast_request_and_dial().

01555 {
01556    struct chanlist *chan;
01557    struct ast_channel *c = NULL;
01558    int capabilities;
01559    int fmt;
01560    int res;
01561    if (ast_mutex_lock(&chlock)) {
01562       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01563       return NULL;
01564    }
01565    chan = backends;
01566    while(chan) {
01567       if (!strcasecmp(type, chan->type)) {
01568          capabilities = chan->capabilities;
01569          fmt = format;
01570          res = ast_translator_best_choice(&fmt, &capabilities);
01571          if (res < 0) {
01572             ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
01573             ast_mutex_unlock(&chlock);
01574             return NULL;
01575          }
01576          ast_mutex_unlock(&chlock);
01577          if (chan->requester)
01578             c = chan->requester(type, capabilities, data);
01579          if (c) {
01580             if (c->_state == AST_STATE_DOWN) {
01581                manager_event(EVENT_FLAG_CALL, "Newchannel",
01582                "Channel: %s\r\n"
01583                "State: %s\r\n"
01584                "Callerid: %s\r\n"
01585                "Uniqueid: %s\r\n",
01586                c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid);
01587             }
01588          }
01589          return c;
01590       }
01591       chan = chan->next;
01592    }
01593    if (!chan)
01594       ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
01595    ast_mutex_unlock(&chlock);
01596    return c;
01597 }

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

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

Definition at line 1491 of file channel.c.

References ast_channel::_state, ast_call(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_frfree(), ast_hangup(), ast_log(), ast_read(), ast_request(), ast_set_callerid(), AST_STATE_UP, ast_waitfor(), LOG_NOTICE, and type.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

01492 {
01493    int state = 0;
01494    struct ast_channel *chan;
01495    struct ast_frame *f;
01496    int res;
01497    
01498    chan = ast_request(type, format, data);
01499    if (chan) {
01500       if (callerid)
01501          ast_set_callerid(chan, callerid, 1);
01502       if (!ast_call(chan, data, 0)) {
01503          while(timeout && (chan->_state != AST_STATE_UP)) {
01504             res = ast_waitfor(chan, timeout);
01505             if (res < 0) {
01506                /* Something not cool, or timed out */
01507                ast_hangup(chan);
01508                chan = NULL;
01509                break;
01510             }
01511             /* If done, break out */
01512             if (!res)
01513                break;
01514             if (timeout > -1)
01515                timeout = res;
01516             f = ast_read(chan);
01517             if (!f) {
01518                state = AST_CONTROL_HANGUP;
01519                ast_hangup(chan);
01520                chan = NULL;
01521                break;
01522             }
01523             if (f->frametype == AST_FRAME_CONTROL) {
01524                if (f->subclass == AST_CONTROL_RINGING)
01525                   state = AST_CONTROL_RINGING;
01526                else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01527                   state = f->subclass;
01528                   ast_frfree(f);
01529                   break;
01530                } else if (f->subclass == AST_CONTROL_ANSWER) {
01531                   state = f->subclass;
01532                   ast_frfree(f);
01533                   break;
01534                } else {
01535                   ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
01536                }
01537             }
01538             ast_frfree(f);
01539          }
01540       } else {
01541          ast_hangup(chan);
01542          chan = NULL;
01543          ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01544       }
01545    } else
01546       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01547    if (chan && (chan->_state == AST_STATE_UP))
01548       state = AST_CONTROL_ANSWER;
01549    if (outstate)
01550       *outstate = state;
01551    return chan;
01552 }

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

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

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

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

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

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

Definition at line 451 of file channel.c.

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

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

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

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

01243 {
01244    int res = 0;
01245    /* Stop if we're a zombie or need a soft hangup */
01246    if (chan->zombie || ast_check_hangup(chan)) 
01247       return -1;
01248    CHECK_BLOCKING(chan);
01249    if (chan->pvt->send_text)
01250       res = chan->pvt->send_text(chan, text);
01251    chan->blocking = 0;
01252    return res;
01253 }

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

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

02071 {
02072    if (chan->callerid)
02073       free(chan->callerid);
02074    if (anitoo && chan->ani)
02075       free(chan->ani);
02076    if (callerid) {
02077       chan->callerid = strdup(callerid);
02078       if (anitoo)
02079          chan->ani = strdup(callerid);
02080    } else {
02081       chan->callerid = NULL;
02082       if (anitoo)
02083          chan->ani = NULL;
02084    }
02085    if (chan->cdr)
02086       ast_cdr_setcid(chan->cdr, chan);
02087    manager_event(EVENT_FLAG_CALL, "Newcallerid", 
02088             "Channel: %s\r\n"
02089             "Callerid: %s\r\n"
02090             "Uniqueid: %s\r\n",
02091             chan->name, chan->callerid ? 
02092             chan->callerid : "<Unknown>",
02093             chan->uniqueid);
02094 }

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

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

Referenced by ast_app_getvoice(), and ast_channel_make_compatible().

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

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

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

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

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

int ast_setstate struct ast_channel chan,
int  state
 

Change the state of a channel

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

02097 {
02098    if (chan->_state != state) {
02099       int oldstate = chan->_state;
02100       chan->_state = state;
02101       if (oldstate == AST_STATE_DOWN) {
02102          ast_device_state_changed(chan->name);
02103          manager_event(EVENT_FLAG_CALL, "Newchannel",
02104          "Channel: %s\r\n"
02105          "State: %s\r\n"
02106          "Callerid: %s\r\n"
02107          "Uniqueid: %s\r\n",
02108          chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02109       } else {
02110          manager_event(EVENT_FLAG_CALL, "Newstate", 
02111             "Channel: %s\r\n"
02112             "State: %s\r\n"
02113             "Callerid: %s\r\n"
02114             "Uniqueid: %s\r\n",
02115             chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02116       }
02117    }
02118    return 0;
02119 }

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

Definition at line 943 of file channel.c.

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

Referenced by ast_closestream().

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

int ast_shutting_down void   ) 
 

Returns non-zero if Asterisk is being shut down

Definition at line 128 of file channel.c.

00129 {
00130    return shutting_down;
00131 }

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

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

Referenced by ast_begin_shutdown().

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

int ast_softhangup_nolock struct ast_channel chan,
int  cause
 

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

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

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

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

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

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

02417 {
02418    struct ast_frame *f;
02419    int res;
02420    if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
02421       return res;
02422 
02423    /* Give us some wiggle room */
02424    while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
02425       f = ast_read(chan);
02426       if (f)
02427          ast_frfree(f);
02428       else
02429          return -1;
02430    }
02431    return 0;
02432 }

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

Start a tone going

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

02397 {
02398    struct tonepair_def d = { 0, };
02399    d.freq1 = freq1;
02400    d.freq2 = freq2;
02401    d.duration = duration;
02402    if (vol < 1)
02403       d.vol = 8192;
02404    else
02405       d.vol = vol;
02406    if (ast_activate_generator(chan, &tonepair, &d))
02407       return -1;
02408    return 0;
02409 }

void ast_tonepair_stop struct ast_channel chan  ) 
 

Stop a tone from playing

Definition at line 2411 of file channel.c.

References ast_deactivate_generator().

02412 {
02413    ast_deactivate_generator(chan);
02414 }

int ast_transfer struct ast_channel chan,
char *  dest
 

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

01673 {
01674    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
01675       If the remote end does not answer within the timeout, then do NOT hang up, but 
01676       return anyway.  */
01677    int res = -1;
01678    /* Stop if we're a zombie or need a soft hangup */
01679    ast_mutex_lock(&chan->lock);
01680    if (!chan->zombie && !ast_check_hangup(chan)) {
01681       if (chan->pvt->transfer) {
01682          res = chan->pvt->transfer(chan, dest);
01683          if (!res)
01684             res = 1;
01685       } else
01686          res = 0;
01687    }
01688    ast_mutex_unlock(&chan->lock);
01689    return res;
01690 }

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

References ast_waitfor_n().

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

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

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

References ast_waitfor_nandfds().

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

00898 {
00899    return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
00900 }

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

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

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

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

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

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

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

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

Referenced by ast_pbx_run(), and ast_readstring().

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

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

Definition at line 960 of file channel.c.

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

Referenced by ast_readstring_full().

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

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

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

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

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

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

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

01316 {
01317    int res;
01318    if (!chan->pvt->write_video)
01319       return 0;
01320    res = ast_write(chan, fr);
01321    if (!res)
01322       res = 1;
01323    return res;
01324 }


Variable Documentation

struct chanlist * backends
 

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

struct ast_channel* channels = NULL
 

Definition at line 61 of file channel.c.

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


Generated on Fri Oct 31 07:05:10 2003 for Asterisk by doxygen 1.3.4