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

channel.c File Reference

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

Go to the source code of this file.

Data Structures

struct  chanlist
struct  tonepair_def
struct  tonepair_state

Functions

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

Variables

chanlistbackends
ast_channelchannels = NULL


Function Documentation

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

Definition at line 1705 of file channel.c.

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

Referenced by ast_pbx_outgoing_exten(), and ast_request_and_dial().

01706 { 01707 int state = 0; 01708 struct ast_channel *chan; 01709 struct ast_frame *f; 01710 int res = 0; 01711 char *variable; 01712 chan = ast_request(type, format, data); 01713 if (chan) { 01714 if (oh) { 01715 char *tmp, *var; 01716 /* JDG chanvar */ 01717 if (oh->variable) 01718 variable = ast_strdupa(oh->variable); 01719 else 01720 variable = NULL; 01721 tmp = variable; 01722 /* FIXME replace this call with strsep NOT*/ 01723 while( (var = strtok_r(NULL, "|", &tmp)) ) { 01724 pbx_builtin_setvar( chan, var ); 01725 } /* /JDG */ 01726 if (oh->callerid && *oh->callerid) 01727 ast_set_callerid(chan, oh->callerid, 1); 01728 if (oh->account && *oh->account) 01729 ast_cdr_setaccount(chan, oh->account); 01730 } 01731 if (callerid && !ast_strlen_zero(callerid)) 01732 ast_set_callerid(chan, callerid, 1); 01733 01734 if (!ast_call(chan, data, 0)) { 01735 while(timeout && (chan->_state != AST_STATE_UP)) { 01736 res = ast_waitfor(chan, timeout); 01737 if (res < 0) { 01738 /* Something not cool, or timed out */ 01739 break; 01740 } 01741 /* If done, break out */ 01742 if (!res) 01743 break; 01744 if (timeout > -1) 01745 timeout = res; 01746 f = ast_read(chan); 01747 if (!f) { 01748 state = AST_CONTROL_HANGUP; 01749 res = 0; 01750 break; 01751 } 01752 if (f->frametype == AST_FRAME_CONTROL) { 01753 if (f->subclass == AST_CONTROL_RINGING) 01754 state = AST_CONTROL_RINGING; 01755 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) { 01756 state = f->subclass; 01757 ast_frfree(f); 01758 break; 01759 } else if (f->subclass == AST_CONTROL_ANSWER) { 01760 state = f->subclass; 01761 ast_frfree(f); 01762 break; 01763 } else if (f->subclass == AST_CONTROL_PROGRESS) { 01764 /* Ignore */ 01765 } else if (f->subclass == -1) { 01766 /* Ignore -- just stopping indications */ 01767 } else { 01768 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass); 01769 } 01770 } 01771 ast_frfree(f); 01772 } 01773 } else 01774 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 01775 } else 01776 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 01777 if (chan) { 01778 /* Final fixups */ 01779 if (oh) { 01780 if (oh->context && *oh->context) 01781 strncpy(chan->context, oh->context, sizeof(chan->context) - 1); 01782 if (oh->exten && *oh->exten) 01783 strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1); 01784 chan->priority = oh->priority; 01785 } 01786 if (chan->_state == AST_STATE_UP) 01787 state = AST_CONTROL_ANSWER; 01788 } 01789 if (outstate) 01790 *outstate = state; 01791 if (chan && res <= 0) { 01792 if (!chan->cdr) { 01793 chan->cdr = ast_cdr_alloc(); 01794 if (chan->cdr) 01795 ast_cdr_init(chan->cdr, chan); 01796 } 01797 if (chan->cdr) { 01798 char tmp[256]; 01799 snprintf(tmp, 256, "%s/%s", type, (char *)data); 01800 ast_cdr_setapp(chan->cdr,"Dial",tmp); 01801 ast_cdr_update(chan); 01802 ast_cdr_start(chan->cdr); 01803 ast_cdr_end(chan->cdr); 01804 /* If the cause wasn't handled properly */ 01805 if (ast_cdr_disposition(chan->cdr,chan->hangupcause)) 01806 ast_cdr_failed(chan->cdr); 01807 } else 01808 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 01809 ast_hangup(chan); 01810 chan = NULL; 01811 } 01812 return chan; 01813 }

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

Activate a given generator Definition at line 823 of file channel.c.

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

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

00824 { 00825 int res = 0; 00826 ast_mutex_lock(&chan->lock); 00827 if (chan->generatordata) { 00828 if (chan->generator && chan->generator->release) 00829 chan->generator->release(chan, chan->generatordata); 00830 chan->generatordata = NULL; 00831 } 00832 ast_prod(chan); 00833 if ((chan->generatordata = gen->alloc(chan, params))) { 00834 chan->generator = gen; 00835 } else { 00836 res = -1; 00837 } 00838 ast_mutex_unlock(&chan->lock); 00839 return res; 00840 }

int ast_active_channels void   ) 
 

Returns number of active/allocated channels Definition at line 120 of file channel.c.

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

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

int ast_answer struct ast_channel chan  ) 
 

Answer a ringing call.

Parameters:
chan channel to answer This function answers a channel and handles all necessary call setup functions. Returns 0 on success, -1 on failure
Definition at line 779 of file channel.c.

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

Referenced by ast_control_streamfile().

00780 { 00781 int res = 0; 00782 ast_mutex_lock(&chan->lock); 00783 /* Stop if we're a zombie or need a soft hangup */ 00784 if (chan->zombie || ast_check_hangup(chan)) { 00785 ast_mutex_unlock(&chan->lock); 00786 return -1; 00787 } 00788 switch(chan->_state) { 00789 case AST_STATE_RINGING: 00790 case AST_STATE_RING: 00791 if (chan->pvt->answer) 00792 res = chan->pvt->answer(chan); 00793 ast_setstate(chan, AST_STATE_UP); 00794 if (chan->cdr) 00795 ast_cdr_answer(chan->cdr); 00796 ast_mutex_unlock(&chan->lock); 00797 return res; 00798 break; 00799 case AST_STATE_UP: 00800 if (chan->cdr) 00801 ast_cdr_answer(chan->cdr); 00802 break; 00803 } 00804 ast_mutex_unlock(&chan->lock); 00805 return 0; 00806 }

void ast_begin_shutdown int  hangup  ) 
 

Initiate system shutdown -- prevents new channels from being allocated. If "hangup" is non-zero, all existing channels will receive soft hangups Definition at line 105 of file channel.c.

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

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

int ast_best_codec int  fmts  ) 
 

Pick the best codec.

Definition at line 233 of file channel.c.

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

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

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

Make a call.

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

01925 { 01926 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 01927 If the remote end does not answer within the timeout, then do NOT hang up, but 01928 return anyway. */ 01929 int res = -1; 01930 /* Stop if we're a zombie or need a soft hangup */ 01931 ast_mutex_lock(&chan->lock); 01932 if (!chan->zombie && !ast_check_hangup(chan)) 01933 if (chan->pvt->call) 01934 res = chan->pvt->call(chan, addr, timeout); 01935 ast_mutex_unlock(&chan->lock); 01936 return res; 01937 }

void ast_cancel_shutdown void   ) 
 

Cancels an existing shutdown and returns to normal operation Definition at line 134 of file channel.c.

00135 { 00136 shutting_down = 0; 00137 }

void ast_change_name struct ast_channel chan,
char *  newname
 

Definition at line 2143 of file channel.c.

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

02144 { 02145 char tmp[256]; 02146 strncpy(tmp, chan->name, sizeof(tmp) - 1); 02147 strncpy(chan->name, newname, sizeof(chan->name) - 1); 02148 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid); 02149 }

struct ast_channel* ast_channel_alloc int  needalertpipe  ) 
 

Create a channel structure.

Returns NULL on failure to allocate Definition at line 274 of file channel.c.

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

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

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

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

Bridge two channels together.

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

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

02457 { 02458 /* Copy voice back and forth between the two channels. Give the peer 02459 the ability to transfer calls with '#<extension' syntax. */ 02460 int flags; 02461 struct ast_channel *cs[3]; 02462 int to = -1; 02463 struct ast_frame *f; 02464 struct ast_channel *who = NULL; 02465 int res=0; 02466 int nativefailed=0; 02467 struct timeval start_time,precise_now; 02468 long elapsed_ms=0, time_left_ms=0; 02469 int playit=0, playitagain=1, first_time=1; 02470 02471 flags = (config->allowdisconnect||config->allowredirect_out ? AST_BRIDGE_DTMF_CHANNEL_0 : 0) + (config->allowredirect_in ? AST_BRIDGE_DTMF_CHANNEL_1 : 0); 02472 02473 /* timestamp */ 02474 gettimeofday(&start_time,NULL); 02475 time_left_ms = config->timelimit; 02476 02477 if (config->play_to_caller && config->start_sound) 02478 bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000); 02479 if (config->play_to_callee && config->start_sound) 02480 bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000); 02481 02482 /* Stop if we're a zombie or need a soft hangup */ 02483 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 02484 return -1; 02485 if (c0->bridge) { 02486 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 02487 c0->name, c0->bridge->name); 02488 return -1; 02489 } 02490 if (c1->bridge) { 02491 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 02492 c1->name, c1->bridge->name); 02493 return -1; 02494 } 02495 02496 /* Keep track of bridge */ 02497 c0->bridge = c1; 02498 c1->bridge = c0; 02499 cs[0] = c0; 02500 cs[1] = c1; 02501 02502 manager_event(EVENT_FLAG_CALL, "Link", 02503 "Channel1: %s\r\n" 02504 "Channel2: %s\r\n" 02505 "Uniqueid1: %s\r\n" 02506 "Uniqueid2: %s\r\n", 02507 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02508 02509 for (/* ever */;;) { 02510 /* timestamp */ 02511 if (config->timelimit) { 02512 gettimeofday(&precise_now,NULL); 02513 elapsed_ms = tvdiff(&precise_now,&start_time); 02514 time_left_ms = config->timelimit - elapsed_ms; 02515 02516 if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) { 02517 /* narrowing down to the end */ 02518 if (config->warning_freq == 0) { 02519 playit = 1; 02520 first_time=0; 02521 playitagain=0; 02522 } else if (first_time) { 02523 playit = 1; 02524 first_time=0; 02525 } else { 02526 if ((time_left_ms % config->warning_freq) <= 50) { 02527 playit = 1; 02528 } 02529 } 02530 } 02531 if (time_left_ms <= 0) { 02532 if (config->play_to_caller && config->end_sound) 02533 bridge_playfile(c0,c1,config->end_sound,0); 02534 if (config->play_to_callee && config->end_sound) 02535 bridge_playfile(c1,c0,config->end_sound,0); 02536 *fo = NULL; 02537 if (who) *rc = who; 02538 res = 0; 02539 break; 02540 } 02541 if (time_left_ms >= 5000 && playit) { 02542 if (config->play_to_caller && config->warning_sound && config->play_warning) 02543 bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000); 02544 if (config->play_to_callee && config->warning_sound && config->play_warning) 02545 bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000); 02546 playit = 0; 02547 } 02548 02549 } 02550 /* Stop if we're a zombie or need a soft hangup */ 02551 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) { 02552 *fo = NULL; 02553 if (who) *rc = who; 02554 res = 0; 02555 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"); 02556 break; 02557 } 02558 if (c0->pvt->bridge && config->timelimit==0 && 02559 (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) { 02560 /* Looks like they share a bridge code */ 02561 if (option_verbose > 2) 02562 ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name); 02563 if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) { 02564 c0->bridge = NULL; 02565 c1->bridge = NULL; 02566 manager_event(EVENT_FLAG_CALL, "Unlink", 02567 "Channel1: %s\r\n" 02568 "Channel2: %s\r\n" 02569 "Uniqueid1: %s\r\n" 02570 "Uniqueid2: %s\r\n", 02571 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02572 ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name); 02573 return 0; 02574 } 02575 /* If they return non-zero then continue on normally. Let "-2" mean don't worry about 02576 my not wanting to bridge */ 02577 if ((res != -2) && (res != -3)) 02578 ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name); 02579 if (res != -3) nativefailed++; 02580 } 02581 02582 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat)) && 02583 !(c0->generator || c1->generator)) { 02584 if (ast_channel_make_compatible(c0, c1)) { 02585 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); 02586 manager_event(EVENT_FLAG_CALL, "Unlink", 02587 "Channel1: %s\r\n" 02588 "Channel2: %s\r\n" 02589 "Uniqueid1: %s\r\n" 02590 "Uniqueid2: %s\r\n", 02591 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02592 return -1; 02593 } 02594 } 02595 who = ast_waitfor_n(cs, 2, &to); 02596 if (!who) { 02597 ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 02598 continue; 02599 } 02600 f = ast_read(who); 02601 if (!f) { 02602 *fo = NULL; 02603 *rc = who; 02604 res = 0; 02605 ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name); 02606 break; 02607 } 02608 02609 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02610 *fo = f; 02611 *rc = who; 02612 res = 0; 02613 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name); 02614 break; 02615 } 02616 if ((f->frametype == AST_FRAME_VOICE) || 02617 (f->frametype == AST_FRAME_TEXT) || 02618 (f->frametype == AST_FRAME_VIDEO) || 02619 (f->frametype == AST_FRAME_IMAGE) || 02620 (f->frametype == AST_FRAME_DTMF)) { 02621 if ((f->frametype == AST_FRAME_DTMF) && 02622 (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) { 02623 if ((who == c0)) { 02624 if ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 02625 *rc = c0; 02626 *fo = f; 02627 /* Take out of conference mode */ 02628 res = 0; 02629 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name); 02630 break; 02631 } else 02632 goto tackygoto; 02633 } else 02634 if ((who == c1)) { 02635 if (flags & AST_BRIDGE_DTMF_CHANNEL_1) { 02636 *rc = c1; 02637 *fo = f; 02638 res = 0; 02639 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name); 02640 break; 02641 } else 02642 goto tackygoto; 02643 } 02644 } else { 02645 #if 0 02646 ast_log(LOG_DEBUG, "Read from %s\n", who->name); 02647 if (who == last) 02648 ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name); 02649 last = who; 02650 #endif 02651 tackygoto: 02652 /* Don't copy packets if there is a generator on either one, since they're 02653 not supposed to be listening anyway */ 02654 if (who == c0) 02655 ast_write(c1, f); 02656 else 02657 ast_write(c0, f); 02658 } 02659 ast_frfree(f); 02660 } else 02661 ast_frfree(f); 02662 /* Swap who gets priority */ 02663 cs[2] = cs[0]; 02664 cs[0] = cs[1]; 02665 cs[1] = cs[2]; 02666 } 02667 c0->bridge = NULL; 02668 c1->bridge = NULL; 02669 manager_event(EVENT_FLAG_CALL, "Unlink", 02670 "Channel1: %s\r\n" 02671 "Channel2: %s\r\n" 02672 "Uniqueid1: %s\r\n" 02673 "Uniqueid2: %s\r\n", 02674 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02675 ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name); 02676 return res; 02677 }

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

References ast_channel::deferdtmf.

00436 { 00437 int pre = 0; 00438 if (chan) { 00439 pre = chan->deferdtmf; 00440 chan->deferdtmf = 1; 00441 } 00442 return pre; 00443 }

void ast_channel_free struct ast_channel chan  ) 
 

Free a channel structure.

Definition at line 555 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_do_masquerade(), and ast_hangup().

00556 { 00557 struct ast_channel *last=NULL, *cur; 00558 int fd; 00559 struct ast_var_t *vardata; 00560 struct ast_frame *f, *fp; 00561 struct varshead *headp; 00562 char name[AST_CHANNEL_NAME]; 00563 00564 headp=&chan->varshead; 00565 00566 ast_mutex_lock(&chlock); 00567 cur = channels; 00568 while(cur) { 00569 if (cur == chan) { 00570 if (last) 00571 last->next = cur->next; 00572 else 00573 channels = cur->next; 00574 break; 00575 } 00576 last = cur; 00577 cur = cur->next; 00578 } 00579 if (!cur) 00580 ast_log(LOG_WARNING, "Unable to find channel in list\n"); 00581 else { 00582 /* Lock and unlock the channel just to be sure nobody 00583 has it locked still */ 00584 ast_mutex_lock(&cur->lock); 00585 ast_mutex_unlock(&cur->lock); 00586 } 00587 if (chan->pvt->pvt) 00588 ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name); 00589 00590 strncpy(name, chan->name, sizeof(name)-1); 00591 00592 /* Stop monitoring */ 00593 if (chan->monitor) { 00594 chan->monitor->stop( chan, 0 ); 00595 } 00596 00597 /* Free translatosr */ 00598 if (chan->pvt->readtrans) 00599 ast_translator_free_path(chan->pvt->readtrans); 00600 if (chan->pvt->writetrans) 00601 ast_translator_free_path(chan->pvt->writetrans); 00602 if (chan->pbx) 00603 ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name); 00604 if (chan->dnid) 00605 free(chan->dnid); 00606 if (chan->callerid) 00607 free(chan->callerid); 00608 if (chan->ani) 00609 free(chan->ani); 00610 if (chan->rdnis) 00611 free(chan->rdnis); 00612 ast_mutex_destroy(&chan->lock); 00613 /* Close pipes if appropriate */ 00614 if ((fd = chan->pvt->alertpipe[0]) > -1) 00615 close(fd); 00616 if ((fd = chan->pvt->alertpipe[1]) > -1) 00617 close(fd); 00618 if ((fd = chan->timingfd) > -1) 00619 close(fd); 00620 f = chan->pvt->readq; 00621 chan->pvt->readq = NULL; 00622 while(f) { 00623 fp = f; 00624 f = f->next; 00625 ast_frfree(fp); 00626 } 00627 00628 /* loop over the variables list, freeing all data and deleting list items */ 00629 /* no need to lock the list, as the channel is already locked */ 00630 00631 while (!AST_LIST_EMPTY(headp)) { /* List Deletion. */ 00632 vardata = AST_LIST_FIRST(headp); 00633 AST_LIST_REMOVE_HEAD(headp, entries); 00634 // printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata)); 00635 ast_var_delete(vardata); 00636 } 00637 00638 00639 free(chan->pvt); 00640 chan->pvt = NULL; 00641 free(chan); 00642 ast_mutex_unlock(&chlock); 00643 00644 ast_device_state_changed(name); 00645 }

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

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

Referenced by ast_channel_bridge().

02062 { 02063 int peerf; 02064 int chanf; 02065 int res; 02066 ast_mutex_lock(&peer->lock); 02067 peerf = peer->nativeformats; 02068 ast_mutex_unlock(&peer->lock); 02069 ast_mutex_lock(&chan->lock); 02070 chanf = chan->nativeformats; 02071 ast_mutex_unlock(&chan->lock); 02072 res = ast_translator_best_choice(&peerf, &chanf); 02073 if (res < 0) { 02074 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats); 02075 return -1; 02076 } 02077 /* Set read format on channel */ 02078 res = ast_set_read_format(chan, peerf); 02079 if (res < 0) { 02080 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf); 02081 return -1; 02082 } 02083 /* Set write format on peer channel */ 02084 res = ast_set_write_format(peer, peerf); 02085 if (res < 0) { 02086 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf); 02087 return -1; 02088 } 02089 /* Now we go the other way */ 02090 peerf = peer->nativeformats; 02091 chanf = chan->nativeformats; 02092 res = ast_translator_best_choice(&chanf, &peerf); 02093 if (res < 0) { 02094 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats); 02095 return -1; 02096 } 02097 /* Set writeformat on channel */ 02098 res = ast_set_write_format(chan, chanf); 02099 if (res < 0) { 02100 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf); 02101 return -1; 02102 } 02103 /* Set read format on peer channel */ 02104 res = ast_set_read_format(peer, chanf); 02105 if (res < 0) { 02106 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf); 02107 return -1; 02108 } 02109 return 0; 02110 }

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

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

Referenced by ast_async_goto().

02113 { 02114 struct ast_frame null = { AST_FRAME_NULL, }; 02115 int res = -1; 02116 ast_mutex_lock(&original->lock); 02117 while(ast_mutex_trylock(&clone->lock)) { 02118 ast_mutex_unlock(&original->lock); 02119 usleep(1); 02120 ast_mutex_lock(&original->lock); 02121 } 02122 ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n", 02123 clone->name, original->name); 02124 if (original->masq) { 02125 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02126 original->masq->name, original->name); 02127 } else if (clone->masqr) { 02128 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02129 clone->name, clone->masqr->name); 02130 } else { 02131 original->masq = clone; 02132 clone->masqr = original; 02133 ast_queue_frame(original, &null); 02134 ast_queue_frame(clone, &null); 02135 ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name); 02136 res = 0; 02137 } 02138 ast_mutex_unlock(&clone->lock); 02139 ast_mutex_unlock(&original->lock); 02140 return res; 02141 }

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

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

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

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

Definition at line 162 of file channel.c.

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

Referenced by ast_channel_register().

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

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

Sends HTML on given channel.

Send HTML or URL on link. Returns 0 on success or -1 on failure Definition at line 2047 of file channel.c.

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

02048 { 02049 if (chan->pvt->send_html) 02050 return chan->pvt->send_html(chan, subclass, data, datalen); 02051 return -1; 02052 }

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

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

02055 { 02056 if (chan->pvt->send_html) 02057 return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1); 02058 return -1; 02059 }

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

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

02680 { 02681 int res; 02682 if (chan->pvt->setoption) { 02683 res = chan->pvt->setoption(chan, option, data, datalen); 02684 if (res < 0) 02685 return res; 02686 } else { 02687 errno = ENOSYS; 02688 return -1; 02689 } 02690 if (block) { 02691 /* XXX Implement blocking -- just wait for our option frame reply, discarding 02692 intermediate packets. XXX */ 02693 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 02694 return -1; 02695 } 02696 return 0; 02697 }

void ast_channel_setwhentohangup struct ast_channel chan,
time_t  offset
 

Set when to hang a channel up.

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

References ast_channel::whentohangup.

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

int ast_channel_supports_html struct ast_channel channel  ) 
 

Checks for HTML support on a channel.

Returns 0 if channel does not support HTML or non-zero if it does Definition at line 2040 of file channel.c.

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

02041 { 02042 if (chan->pvt->send_html) 02043 return 1; 02044 return 0; 02045 }

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

References ast_channel::deferdtmf.

00446 { 00447 if (chan) 00448 chan->deferdtmf = 0; 00449 }

void ast_channel_unregister char *  type  ) 
 

Unregister a channel class.

Definition at line 750 of file channel.c.

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

00751 { 00752 struct chanlist *chan, *last=NULL; 00753 if (option_debug) 00754 ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type); 00755 if (ast_mutex_lock(&chlock)) { 00756 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 00757 return; 00758 } 00759 if (option_verbose > 1) 00760 ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type); 00761 00762 chan = backends; 00763 while(chan) { 00764 if (!strcasecmp(chan->type, type)) { 00765 if (last) 00766 last->next = chan->next; 00767 else 00768 backends = backends->next; 00769 free(chan); 00770 ast_mutex_unlock(&chlock); 00771 return; 00772 } 00773 last = chan; 00774 chan = chan->next; 00775 } 00776 ast_mutex_unlock(&chlock); 00777 }

struct ast_channel* ast_channel_walk_locked struct ast_channel prev  ) 
 

Browse channels in use.

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

References ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, channels, LOG_DEBUG, and LOG_WARNING.

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

00452 { 00453 /* Returns next channel (locked) */ 00454 struct ast_channel *l, *ret; 00455 int retries = 0; 00456 retry: 00457 ret=NULL; 00458 ast_mutex_lock(&chlock); 00459 l = channels; 00460 if (!prev) { 00461 if (l) { 00462 if (ast_mutex_trylock(&l->lock)) { 00463 if (retries < 10) 00464 ast_log(LOG_DEBUG, "Avoiding initial deadlock for '%s'\n", l->name); 00465 else 00466 ast_log(LOG_WARNING, "Avoided initial deadlock for '%s', %d retries!\n", l->name, retries); 00467 ast_mutex_unlock(&chlock); 00468 if (retries < 10) { 00469 usleep(1); 00470 retries++; 00471 goto retry; 00472 } else 00473 return NULL; 00474 } 00475 } 00476 ast_mutex_unlock(&chlock); 00477 return l; 00478 } 00479 while(l) { 00480 if (l == prev) 00481 ret = l->next; 00482 l = l->next; 00483 } 00484 if (ret) { 00485 if (ast_mutex_trylock(&ret->lock)) { 00486 if (retries < 10) 00487 ast_log(LOG_DEBUG, "Avoiding deadlock for '%s'\n", ret->name); 00488 else 00489 ast_log(LOG_WARNING, "Avoided deadlock for '%s', %d retries!\n", ret->name, retries); 00490 ast_mutex_unlock(&chlock); 00491 if (retries < 10) { 00492 usleep(1); 00493 retries++; 00494 goto retry; 00495 } else 00496 return NULL; 00497 } 00498 } 00499 ast_mutex_unlock(&chlock); 00500 return ret; 00501 00502 }

int ast_check_hangup struct ast_channel chan  ) 
 

Check to see if a channel is needing hang up.

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

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

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

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

void ast_deactivate_generator struct ast_channel chan  ) 
 

Deactive an active generator Definition at line 810 of file channel.c.

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

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

00811 { 00812 ast_mutex_lock(&chan->lock); 00813 if (chan->generatordata) { 00814 if (chan->generator && chan->generator->release) 00815 chan->generator->release(chan, chan->generatordata); 00816 chan->generatordata = NULL; 00817 chan->generator = NULL; 00818 chan->writeinterrupt = 0; 00819 } 00820 ast_mutex_unlock(&chan->lock); 00821 }

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

01886 { 01887 char tech[AST_MAX_EXTENSION] = ""; 01888 char *number; 01889 struct chanlist *chanls; 01890 int res = 0; 01891 01892 strncpy(tech, device, sizeof(tech)-1); 01893 number = strchr(tech, '/'); 01894 if (!number) { 01895 return AST_DEVICE_INVALID; 01896 } 01897 *number = 0; 01898 number++; 01899 01900 if (ast_mutex_lock(&chlock)) { 01901 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 01902 return -1; 01903 } 01904 chanls = backends; 01905 while(chanls) { 01906 if (!strcasecmp(tech, chanls->type)) { 01907 ast_mutex_unlock(&chlock); 01908 if (!chanls->devicestate) 01909 return ast_parse_device_state(device); 01910 else { 01911 res = chanls->devicestate(number); 01912 if (res == AST_DEVICE_UNKNOWN) 01913 return ast_parse_device_state(device); 01914 else 01915 return res; 01916 } 01917 } 01918 chanls = chanls->next; 01919 } 01920 ast_mutex_unlock(&chlock); 01921 return AST_DEVICE_INVALID; 01922 }

int ast_do_masquerade struct ast_channel original  ) 
 

Definition at line 2151 of file channel.c.

References ast_channel::_state, ast_channel::adsicpe, ast_channel_pvt::alertpipe, ast_channel_free(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_set_read_format(), ast_set_write_format(), AST_SOFTHANGUP_DEV, ast_channel::blocker, ast_channel::blocking, ast_channel::callerid, ast_channel::dnid, EVENT_FLAG_CALL, ast_channel::exception, ast_channel::fdno, ast_channel::fds, ast_channel_pvt::fixup, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_channel::nativeformats, ast_channel::next, ast_channel::pvt, ast_channel_pvt::pvt, ast_channel::readformat, ast_channel_pvt::readq, ast_channel::timingfd, ast_channel::type, and ast_channel::writeformat.

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

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

struct ast_channel* ast_get_channel_by_name_locked char *  channame  ) 
 

Get channel by name (locks channel).

Definition at line 504 of file channel.c.

References ast_channel_walk_locked(), and ast_mutex_unlock.

00505 { 00506 struct ast_channel *chan; 00507 chan = ast_channel_walk_locked(NULL); 00508 while(chan) { 00509 if (!strcasecmp(chan->name, channame)) 00510 return chan; 00511 ast_mutex_unlock(&chan->lock); 00512 chan = ast_channel_walk_locked(chan); 00513 } 00514 return NULL; 00515 }

unsigned int ast_get_group char *  s  ) 
 

Definition at line 2831 of file channel.c.

References ast_log(), LOG_ERROR, LOG_WARNING, and s.

02832 { 02833 char *copy; 02834 char *piece; 02835 char *c=NULL; 02836 int start=0, finish=0,x; 02837 unsigned int group = 0; 02838 copy = ast_strdupa(s); 02839 if (!copy) { 02840 ast_log(LOG_ERROR, "Out of memory\n"); 02841 return 0; 02842 } 02843 c = copy; 02844 02845 while((piece = strsep(&c, ","))) { 02846 if (sscanf(piece, "%d-%d", &start, &finish) == 2) { 02847 /* Range */ 02848 } else if (sscanf(piece, "%d", &start)) { 02849 /* Just one */ 02850 finish = start; 02851 } else { 02852 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'. Using '0'\n", s,piece); 02853 return 0; 02854 } 02855 for (x=start;x<=finish;x++) { 02856 if ((x > 31) || (x < 0)) { 02857 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x); 02858 } else 02859 group |= (1 << x); 02860 } 02861 } 02862 return group; 02863 }

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

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

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

00684 { 00685 int res = 0; 00686 /* Don't actually hang up a channel that will masquerade as someone else, or 00687 if someone is going to masquerade as us */ 00688 ast_mutex_lock(&chan->lock); 00689 if (chan->masq) { 00690 if (ast_do_masquerade(chan)) 00691 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 00692 } 00693 00694 if (chan->masq) { 00695 ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name); 00696 ast_mutex_unlock(&chan->lock); 00697 return 0; 00698 } 00699 /* If this channel is one which will be masqueraded into something, 00700 mark it as a zombie already, so we know to free it later */ 00701 if (chan->masqr) { 00702 chan->zombie=1; 00703 ast_mutex_unlock(&chan->lock); 00704 return 0; 00705 } 00706 free_translation(chan); 00707 if (chan->stream) 00708 ast_closestream(chan->stream); 00709 if (chan->vstream) 00710 ast_closestream(chan->vstream); 00711 if (chan->sched) 00712 sched_context_destroy(chan->sched); 00713 /* Clear any tone stuff remaining */ 00714 if (chan->generatordata) 00715 chan->generator->release(chan, chan->generatordata); 00716 chan->generatordata = NULL; 00717 chan->generator = NULL; 00718 if (chan->cdr) { 00719 /* End the CDR if it hasn't already */ 00720 ast_cdr_end(chan->cdr); 00721 /* Post and Free the CDR */ 00722 ast_cdr_post(chan->cdr); 00723 ast_cdr_free(chan->cdr); 00724 } 00725 if (chan->blocking) { 00726 ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd " 00727 "is blocked by thread %ld in procedure %s! Expect a failure\n", 00728 (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc); 00729 CRASH; 00730 } 00731 if (!chan->zombie) { 00732 if (option_debug) 00733 ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name); 00734 if (chan->pvt->hangup) 00735 res = chan->pvt->hangup(chan); 00736 } else 00737 if (option_debug) 00738 ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name); 00739 00740 ast_mutex_unlock(&chan->lock); 00741 manager_event(EVENT_FLAG_CALL, "Hangup", 00742 "Channel: %s\r\n" 00743 "Uniqueid: %s\r\n" 00744 "Cause: %i\r\n", 00745 chan->name, chan->uniqueid, chan->hangupcause); 00746 ast_channel_free(chan); 00747 return res; 00748 }

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

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

01367 { 01368 int res = -1; 01369 /* Stop if we're a zombie or need a soft hangup */ 01370 if (chan->zombie || ast_check_hangup(chan)) 01371 return -1; 01372 ast_mutex_lock(&chan->lock); 01373 if (chan->pvt->indicate) 01374 res = chan->pvt->indicate(chan, condition); 01375 ast_mutex_unlock(&chan->lock); 01376 if (!chan->pvt->indicate || res) { 01377 /* 01378 * Device does not support (that) indication, lets fake 01379 * it by doing our own tone generation. (PM2002) 01380 */ 01381 if (condition >= 0) { 01382 const struct tone_zone_sound *ts = NULL; 01383 switch (condition) { 01384 case AST_CONTROL_RINGING: 01385 ts = ast_get_indication_tone(chan->zone, "ring"); 01386 break; 01387 case AST_CONTROL_BUSY: 01388 ts = ast_get_indication_tone(chan->zone, "busy"); 01389 break; 01390 case AST_CONTROL_CONGESTION: 01391 ts = ast_get_indication_tone(chan->zone, "congestion"); 01392 break; 01393 } 01394 if (ts && ts->data[0]) { 01395 ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition); 01396 ast_playtones_start(chan,0,ts->data, 1); 01397 res = 0; 01398 } else if (condition == AST_CONTROL_PROGRESS) { 01399 /* ast_playtones_stop(chan); */ 01400 } else if (condition == AST_CONTROL_PROCEEDING) { 01401 /* Do nothing, really */ 01402 } else { 01403 /* not handled */ 01404 ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name); 01405 res = -1; 01406 } 01407 } 01408 else ast_playtones_stop(chan); 01409 } 01410 return res; 01411 }

AST_MUTEX_DEFINE_STATIC chlock   ) 
 

int ast_parse_device_state char *  device  ) 
 

Search the Channels by Name.

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

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

Referenced by ast_device_state().

01866 { 01867 char name[AST_CHANNEL_NAME] = ""; 01868 char *cut; 01869 struct ast_channel *chan; 01870 01871 chan = ast_channel_walk_locked(NULL); 01872 while (chan) { 01873 strncpy(name, chan->name, sizeof(name)-1); 01874 ast_mutex_unlock(&chan->lock); 01875 cut = strchr(name,'-'); 01876 if (cut) 01877 *cut = 0; 01878 if (!strcmp(name, device)) 01879 return AST_DEVICE_INUSE; 01880 chan = ast_channel_walk_locked(chan); 01881 } 01882 return AST_DEVICE_UNKNOWN; 01883 }

int ast_prod struct ast_channel chan  ) 
 

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

01505 { 01506 struct ast_frame a = { AST_FRAME_VOICE }; 01507 char nothing[128]; 01508 /* Send an empty audio frame to get things moving */ 01509 if (chan->_state != AST_STATE_UP) { 01510 ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name); 01511 a.subclass = chan->pvt->rawwriteformat; 01512 a.data = nothing + AST_FRIENDLY_OFFSET; 01513 if (ast_write(chan, &a)) 01514 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name); 01515 } 01516 return 0; 01517 }

int ast_queue_control struct ast_channel chan,
int  control
 

Definition at line 428 of file channel.c.

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

00429 { 00430 struct ast_frame f = { AST_FRAME_CONTROL, }; 00431 f.subclass = control; 00432 return ast_queue_frame(chan, &f); 00433 }

int ast_queue_frame struct ast_channel chan,
struct ast_frame f
 

Queue an outgoing frame Definition at line 370 of file channel.c.

References ast_channel_pvt::alertpipe, AST_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, ast_channel_pvt::readq, and ast_channel::timingfd.

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

00371 { 00372 struct ast_frame *f; 00373 struct ast_frame *prev, *cur; 00374 int blah = 1; 00375 int qlen = 0; 00376 /* Build us a copy and free the original one */ 00377 f = ast_frdup(fin); 00378 if (!f) { 00379 ast_log(LOG_WARNING, "Unable to duplicate frame\n"); 00380 return -1; 00381 } 00382 ast_mutex_lock(&chan->lock); 00383 prev = NULL; 00384 cur = chan->pvt->readq; 00385 while(cur) { 00386 prev = cur; 00387 cur = cur->next; 00388 qlen++; 00389 } 00390 /* Allow up to 96 voice frames outstanding, and up to 128 total frames */ 00391 if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen > 128)) { 00392 if (fin->frametype != AST_FRAME_VOICE) { 00393 ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name); 00394 CRASH; 00395 } else { 00396 ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name); 00397 ast_frfree(f); 00398 ast_mutex_unlock(&chan->lock); 00399 return 0; 00400 } 00401 } 00402 if (prev) 00403 prev->next = f; 00404 else 00405 chan->pvt->readq = f; 00406 if (chan->pvt->alertpipe[1] > -1) { 00407 if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) 00408 ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n", 00409 chan->name, f->frametype, f->subclass, qlen, strerror(errno)); 00410 #ifdef ZAPTEL_OPTIMIZATIONS 00411 } else if (chan->timingfd > -1) { 00412 ioctl(chan->timingfd, ZT_TIMERPING, &blah); 00413 #endif 00414 } else if (chan->blocking) { 00415 pthread_kill(chan->blocker, SIGURG); 00416 } 00417 ast_mutex_unlock(&chan->lock); 00418 return 0; 00419 }

int ast_queue_hangup struct ast_channel chan  ) 
 

Definition at line 421 of file channel.c.

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

00422 { 00423 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP }; 00424 chan->_softhangup |= AST_SOFTHANGUP_DEV; 00425 return ast_queue_frame(chan, &f); 00426 }

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 1162 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_do_masquerade(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dump(), AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_seekstream(), ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_translate(), ast_writestream(), ast_channel::blocker, ast_channel::cdr, ast_channel::deferdtmf, ast_channel::dtmff, ast_channel::dtmfq, ast_channel::exception, ast_channel_pvt::exception, ast_channel::fdno, ast_channel::fin, ast_frame::frametype, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, ast_channel::insmpl, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::masq, ast_channel::monitor, ast_channel::name, ast_channel::nativeformats, ast_frame::next, ast_channel::outsmpl, ast_channel::pvt, ast_channel_pvt::read, ast_channel_monitor::read_stream, ast_channel_pvt::readq, ast_channel_pvt::readtrans, SEEK_FORCECUR, ast_frame::subclass, ast_channel::timingdata, ast_channel::timingfd, ast_channel::timingfunc, and ast_channel::zombie.

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

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

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

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

Referenced by ast_app_getdata().

01960 { 01961 int pos=0; 01962 int to = ftimeout; 01963 char d; 01964 /* XXX Merge with full version? XXX */ 01965 /* Stop if we're a zombie or need a soft hangup */ 01966 if (c->zombie || ast_check_hangup(c)) 01967 return -1; 01968 if (!len) 01969 return -1; 01970 do { 01971 if (c->stream) { 01972 d = ast_waitstream(c, AST_DIGIT_ANY); 01973 ast_stopstream(c); 01974 usleep(1000); 01975 if (!d) 01976 d = ast_waitfordigit(c, to); 01977 } else { 01978 d = ast_waitfordigit(c, to); 01979 } 01980 if (d < 0) 01981 return -1; 01982 if (d == 0) { 01983 s[pos]='\0'; 01984 return 1; 01985 } 01986 if (!strchr(enders, d)) 01987 s[pos++] = d; 01988 if (strchr(enders, d) || (pos >= len)) { 01989 s[pos]='\0'; 01990 return 0; 01991 } 01992 to = timeout; 01993 } while(1); 01994 /* Never reached */ 01995 return 0; 01996 }

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

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

Referenced by ast_app_getdata_full().

01999 { 02000 int pos=0; 02001 int to = ftimeout; 02002 char d; 02003 /* Stop if we're a zombie or need a soft hangup */ 02004 if (c->zombie || ast_check_hangup(c)) 02005 return -1; 02006 if (!len) 02007 return -1; 02008 do { 02009 if (c->stream) { 02010 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd); 02011 ast_stopstream(c); 02012 usleep(1000); 02013 if (!d) 02014 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 02015 } else { 02016 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 02017 } 02018 if (d < 0) 02019 return -1; 02020 if (d == 0) { 02021 s[pos]='\0'; 02022 return 1; 02023 } 02024 if (d == 1) { 02025 s[pos]='\0'; 02026 return 2; 02027 } 02028 if (!strchr(enders, d)) 02029 s[pos++] = d; 02030 if (strchr(enders, d) || (pos >= len)) { 02031 s[pos]='\0'; 02032 return 0; 02033 } 02034 to = timeout; 02035 } while(1); 02036 /* Never reached */ 02037 return 0; 02038 }

int ast_recvchar struct ast_channel chan,
int  timeout
 

Definition at line 1413 of file channel.c.

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

01414 { 01415 int res,ourto,c; 01416 struct ast_frame *f; 01417 01418 ourto = timeout; 01419 for(;;) 01420 { 01421 if (ast_check_hangup(chan)) return -1; 01422 res = ast_waitfor(chan,ourto); 01423 if (res <= 0) /* if timeout */ 01424 { 01425 return 0; 01426 } 01427 ourto = res; 01428 f = ast_read(chan); 01429 if (f == NULL) return -1; /* if hangup */ 01430 if ((f->frametype == AST_FRAME_CONTROL) && 01431 (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */ 01432 if (f->frametype == AST_FRAME_TEXT) /* if a text frame */ 01433 { 01434 c = *((char *)f->data); /* get the data */ 01435 ast_frfree(f); 01436 return(c); 01437 } 01438 ast_frfree(f); 01439 } 01440 }

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

01821 { 01822 struct chanlist *chan; 01823 struct ast_channel *c = NULL; 01824 int capabilities; 01825 int fmt; 01826 int res; 01827 if (ast_mutex_lock(&chlock)) { 01828 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 01829 return NULL; 01830 } 01831 chan = backends; 01832 while(chan) { 01833 if (!strcasecmp(type, chan->type)) { 01834 capabilities = chan->capabilities; 01835 fmt = format; 01836 res = ast_translator_best_choice(&fmt, &capabilities); 01837 if (res < 0) { 01838 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format); 01839 ast_mutex_unlock(&chlock); 01840 return NULL; 01841 } 01842 ast_mutex_unlock(&chlock); 01843 if (chan->requester) 01844 c = chan->requester(type, capabilities, data); 01845 if (c) { 01846 if (c->_state == AST_STATE_DOWN) { 01847 manager_event(EVENT_FLAG_CALL, "Newchannel", 01848 "Channel: %s\r\n" 01849 "State: %s\r\n" 01850 "Callerid: %s\r\n" 01851 "Uniqueid: %s\r\n", 01852 c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid); 01853 } 01854 } 01855 return c; 01856 } 01857 chan = chan->next; 01858 } 01859 if (!chan) 01860 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type); 01861 ast_mutex_unlock(&chlock); 01862 return c; 01863 }

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

References __ast_request_and_dial(), and type.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

01816 { 01817 return __ast_request_and_dial(type, format, data, timeout, outstate, callerid, NULL); 01818 }

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

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

Referenced by ast_dtmf_stream().

00539 { 00540 struct ast_frame *f; 00541 while(ms > 0) { 00542 ms = ast_waitfor(chan, ms); 00543 if (ms <0) 00544 return -1; 00545 if (ms > 0) { 00546 f = ast_read(chan); 00547 if (!f) 00548 return -1; 00549 ast_frfree(f); 00550 } 00551 } 00552 return 0; 00553 }

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

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

00519 { 00520 struct ast_frame *f; 00521 00522 while(ms > 0) { 00523 if( cond && ((*cond)(data) == 0 ) ) 00524 return 0; 00525 ms = ast_waitfor(chan, ms); 00526 if (ms <0) 00527 return -1; 00528 if (ms > 0) { 00529 f = ast_read(chan); 00530 if (!f) 00531 return -1; 00532 ast_frfree(f); 00533 } 00534 } 00535 return 0; 00536 }

int ast_senddigit struct ast_channel chan,
char  digit
 

Receives a text character from a channel.

Parameters:
chan channel to act upon
timeout timeout in milliseconds (0 for infinite wait) Read a char of text from a channel Returns 0 on success, -1 on failure
Definition at line 1499 of file channel.c.
01500 { 01501 return do_senddigit(chan, digit); 01502 }

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

01443 { 01444 int res = 0; 01445 /* Stop if we're a zombie or need a soft hangup */ 01446 if (chan->zombie || ast_check_hangup(chan)) 01447 return -1; 01448 CHECK_BLOCKING(chan); 01449 if (chan->pvt->send_text) 01450 res = chan->pvt->send_text(chan, text); 01451 chan->blocking = 0; 01452 return res; 01453 }

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

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

02363 { 02364 if (chan->callerid) 02365 free(chan->callerid); 02366 if (anitoo && chan->ani) 02367 free(chan->ani); 02368 if (callerid) { 02369 chan->callerid = strdup(callerid); 02370 if (anitoo) 02371 chan->ani = strdup(callerid); 02372 } else { 02373 chan->callerid = NULL; 02374 if (anitoo) 02375 chan->ani = NULL; 02376 } 02377 if (chan->cdr) 02378 ast_cdr_setcid(chan->cdr, chan); 02379 manager_event(EVENT_FLAG_CALL, "Newcallerid", 02380 "Channel: %s\r\n" 02381 "Callerid: %s\r\n" 02382 "Uniqueid: %s\r\n", 02383 chan->name, chan->callerid ? 02384 chan->callerid : "<Unknown>", 02385 chan->uniqueid); 02386 }

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

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

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

01672 { 01673 int fmt; 01674 int native; 01675 int res; 01676 01677 ast_mutex_lock(&chan->lock); 01678 native = chan->nativeformats; 01679 fmt = fmts; 01680 /* Find a translation path from the native read format to one of the user's read formats */ 01681 res = ast_translator_best_choice(&fmt, &native); 01682 if (res < 0) { 01683 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n", 01684 ast_getformatname(chan->nativeformats), ast_getformatname(fmts)); 01685 ast_mutex_unlock(&chan->lock); 01686 return -1; 01687 } 01688 01689 /* Now we have a good choice for both. We'll write using our native format. */ 01690 chan->pvt->rawreadformat = native; 01691 /* User perspective is fmt */ 01692 chan->readformat = fmt; 01693 /* Free any read translation we have right now */ 01694 if (chan->pvt->readtrans) 01695 ast_translator_free_path(chan->pvt->readtrans); 01696 /* Build a translation path from the raw read format to the user reading format */ 01697 chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat); 01698 if (option_debug) 01699 ast_log(LOG_DEBUG, "Set channel %s to read format %s\n", 01700 chan->name, ast_getformatname(chan->readformat)); 01701 ast_mutex_unlock(&chan->lock); 01702 return 0; 01703 }

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

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

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

01639 { 01640 int fmt; 01641 int native; 01642 int res; 01643 01644 ast_mutex_lock(&chan->lock); 01645 native = chan->nativeformats; 01646 fmt = fmts; 01647 01648 res = ast_translator_best_choice(&native, &fmt); 01649 if (res < 0) { 01650 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n", 01651 ast_getformatname(fmts), ast_getformatname(chan->nativeformats)); 01652 ast_mutex_unlock(&chan->lock); 01653 return -1; 01654 } 01655 01656 /* Now we have a good choice for both. We'll write using our native format. */ 01657 chan->pvt->rawwriteformat = native; 01658 /* User perspective is fmt */ 01659 chan->writeformat = fmt; 01660 /* Free any write translation we have right now */ 01661 if (chan->pvt->writetrans) 01662 ast_translator_free_path(chan->pvt->writetrans); 01663 /* Build a translation path from the user write format to the raw writing format */ 01664 chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat); 01665 if (option_debug) 01666 ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat)); 01667 ast_mutex_unlock(&chan->lock); 01668 return 0; 01669 }

int ast_setstate struct ast_channel chan,
int  state
 

Change the state of a channel Definition at line 2388 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().

02389 { 02390 if (chan->_state != state) { 02391 int oldstate = chan->_state; 02392 chan->_state = state; 02393 if (oldstate == AST_STATE_DOWN) { 02394 ast_device_state_changed(chan->name); 02395 manager_event(EVENT_FLAG_CALL, "Newchannel", 02396 "Channel: %s\r\n" 02397 "State: %s\r\n" 02398 "Callerid: %s\r\n" 02399 "Uniqueid: %s\r\n", 02400 chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid); 02401 } else { 02402 manager_event(EVENT_FLAG_CALL, "Newstate", 02403 "Channel: %s\r\n" 02404 "State: %s\r\n" 02405 "Callerid: %s\r\n" 02406 "Uniqueid: %s\r\n", 02407 chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid); 02408 } 02409 } 02410 return 0; 02411 }

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

Definition at line 1092 of file channel.c.

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

Referenced by ast_closestream().

01093 { 01094 int res = -1; 01095 #ifdef ZAPTEL_OPTIMIZATIONS 01096 if (c->timingfd > -1) { 01097 if (!func) { 01098 samples = 0; 01099 data = 0; 01100 } 01101 ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples); 01102 res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples); 01103 c->timingfunc = func; 01104 c->timingdata = data; 01105 } 01106 #endif 01107 return res; 01108 }

int ast_shutting_down void   ) 
 

Returns non-zero if Asterisk is being shut down Definition at line 139 of file channel.c.

00140 { 00141 return shutting_down; 00142 }

int ast_softhangup struct ast_channel chan,
int  cause
 

Softly hangup up a channel.

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

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

Referenced by ast_begin_shutdown().

00663 { 00664 int res; 00665 ast_mutex_lock(&chan->lock); 00666 res = ast_softhangup_nolock(chan, cause); 00667 ast_mutex_unlock(&chan->lock); 00668 return res; 00669 }

int ast_softhangup_nolock struct ast_channel chan,
int  cause
 

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

00648 { 00649 int res = 0; 00650 struct ast_frame f = { AST_FRAME_NULL }; 00651 if (option_debug) 00652 ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name); 00653 /* Inform channel driver that we need to be hung up, if it cares */ 00654 chan->_softhangup |= cause; 00655 ast_queue_frame(chan, &f); 00656 /* Interrupt any poll call or such */ 00657 if (chan->blocking) 00658 pthread_kill(chan->blocker, SIGURG); 00659 return res; 00660 }

char* ast_state2str int  state  ) 
 

Gives the string form of a given state.

Parameters:
state state to get the name of Give a name to a state Pretty self explanatory. Returns the text form of the binary state given
Definition at line 205 of file channel.c.

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

Referenced by ast_request(), and ast_setstate().

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

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

Play a tone pair for a given amount of time Definition at line 2813 of file channel.c.

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

02814 { 02815 struct ast_frame *f; 02816 int res; 02817 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol))) 02818 return res; 02819 02820 /* Give us some wiggle room */ 02821 while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) { 02822 f = ast_read(chan); 02823 if (f) 02824 ast_frfree(f); 02825 else 02826 return -1; 02827 } 02828 return 0; 02829 }

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

Start a tone going Definition at line 2793 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().

02794 { 02795 struct tonepair_def d = { 0, }; 02796 d.freq1 = freq1; 02797 d.freq2 = freq2; 02798 d.duration = duration; 02799 if (vol < 1) 02800 d.vol = 8192; 02801 else 02802 d.vol = vol; 02803 if (ast_activate_generator(chan, &tonepair, &d)) 02804 return -1; 02805 return 0; 02806 }

void ast_tonepair_stop struct ast_channel chan  ) 
 

Stop a tone from playing Definition at line 2808 of file channel.c.

References ast_deactivate_generator().

02809 { 02810 ast_deactivate_generator(chan); 02811 }

int ast_transfer struct ast_channel chan,
char *  dest
 

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

01940 { 01941 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 01942 If the remote end does not answer within the timeout, then do NOT hang up, but 01943 return anyway. */ 01944 int res = -1; 01945 /* Stop if we're a zombie or need a soft hangup */ 01946 ast_mutex_lock(&chan->lock); 01947 if (!chan->zombie && !ast_check_hangup(chan)) { 01948 if (chan->pvt->transfer) { 01949 res = chan->pvt->transfer(chan, dest); 01950 if (!res) 01951 res = 1; 01952 } else 01953 res = 0; 01954 } 01955 ast_mutex_unlock(&chan->lock); 01956 return res; 01957 }

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

References ast_waitfor_n().

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

01052 { 01053 struct ast_channel *chan; 01054 int oldms = ms; 01055 chan = ast_waitfor_n(&c, 1, &ms); 01056 if (ms < 0) { 01057 if (oldms < 0) 01058 return 0; 01059 else 01060 return -1; 01061 } 01062 return ms; 01063 }

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

References ast_waitfor_nandfds().

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

01047 { 01048 return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms); 01049 }

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

References ast_log(), LOG_WARNING, poll(), POLLIN, and POLLPRI.

00843 { 00844 /* Wait for x amount of time on a file descriptor to have input. */ 00845 struct timeval start, now; 00846 int res; 00847 int x, y; 00848 int winner = -1; 00849 int spoint; 00850 struct pollfd *pfds; 00851 00852 pfds = alloca(sizeof(struct pollfd) * n); 00853 if (!pfds) { 00854 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n"); 00855 return -1; 00856 } 00857 if (*ms > 0) 00858 gettimeofday(&start, NULL); 00859 y = 0; 00860 for (x=0;x<n;x++) { 00861 if (fds[x] > -1) { 00862 pfds[y].fd = fds[x]; 00863 pfds[y].events = POLLIN | POLLPRI; 00864 y++; 00865 } 00866 } 00867 res = poll(pfds, y, *ms); 00868 if (res < 0) { 00869 /* Simulate a timeout if we were interrupted */ 00870 if (errno != EINTR) 00871 *ms = -1; 00872 else 00873 *ms = 0; 00874 return -1; 00875 } 00876 spoint = 0; 00877 for (x=0;x<n;x++) { 00878 if (fds[x] > -1) { 00879 if ((res = ast_fdisset(pfds, fds[x], y, &spoint))) { 00880 winner = fds[x]; 00881 if (exception) { 00882 if (res & POLLPRI) 00883 *exception = -1; 00884 else 00885 *exception = 0; 00886 } 00887 } 00888 } 00889 } 00890 if (*ms > 0) { 00891 long passed; 00892 gettimeofday(&now, NULL); 00893 passed = (now.tv_sec - start.tv_sec) * 1000; 00894 passed += (now.tv_usec - start.tv_usec) / 1000; 00895 if (passed <= *ms) 00896 *ms -= passed; 00897 else 00898 *ms = 0; 00899 } 00900 return winner; 00901 }

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

References ast_do_masquerade(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_TIMEOUT, ast_channel::blocking, CHECK_BLOCKING, ast_channel::fds, LOG_WARNING, ast_channel::masq, poll(), POLLIN, POLLPRI, and ast_channel::whentohangup.

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

00905 { 00906 /* Wait for x amount of time on a file descriptor to have input. */ 00907 struct timeval start, end; 00908 struct pollfd *pfds; 00909 int res; 00910 long rms; 00911 int x, y, max; 00912 int spoint; 00913 time_t now = 0; 00914 long whentohangup = 0, havewhen = 0, diff; 00915 struct ast_channel *winner = NULL; 00916 00917 pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds)); 00918 if (!pfds) { 00919 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n"); 00920 *outfd = -1; 00921 return NULL; 00922 } 00923 00924 if (outfd) 00925 *outfd = -99999; 00926 if (exception) 00927 *exception = 0; 00928 00929 /* Perform any pending masquerades */ 00930 for (x=0;x<n;x++) { 00931 ast_mutex_lock(&c[x]->lock); 00932 if (c[x]->whentohangup) { 00933 if (!havewhen) 00934 time(&now); 00935 diff = c[x]->whentohangup - now; 00936 if (!havewhen || (diff < whentohangup)) { 00937 havewhen++; 00938 whentohangup = diff; 00939 } 00940 } 00941 if (c[x]->masq) { 00942 if (ast_do_masquerade(c[x])) { 00943 ast_log(LOG_WARNING, "Masquerade failed\n"); 00944 *ms = -1; 00945 ast_mutex_unlock(&c[x]->lock); 00946 return NULL; 00947 } 00948 } 00949 ast_mutex_unlock(&c[x]->lock); 00950 } 00951 00952 rms = *ms; 00953 00954 if (havewhen) { 00955 if ((*ms < 0) || (whentohangup * 1000 < *ms)) { 00956 rms = whentohangup * 1000; 00957 } 00958 } 00959 max = 0; 00960 for (x=0;x<n;x++) { 00961 for (y=0;y<AST_MAX_FDS;y++) { 00962 if (c[x]->fds[y] > -1) { 00963 pfds[max].fd = c[x]->fds[y]; 00964 pfds[max].events = POLLIN | POLLPRI; 00965 max++; 00966 } 00967 } 00968 CHECK_BLOCKING(c[x]); 00969 } 00970 for (x=0;x<nfds; x++) { 00971 if (fds[x] > -1) { 00972 pfds[max].fd = fds[x]; 00973 pfds[max].events = POLLIN | POLLPRI; 00974 max++; 00975 } 00976 } 00977 if (*ms > 0) 00978 gettimeofday(&start, NULL); 00979 res = poll(pfds, max, rms); 00980 if (res < 0) { 00981 for (x=0;x<n;x++) 00982 c[x]->blocking = 0; 00983 /* Simulate a timeout if we were interrupted */ 00984 if (errno != EINTR) 00985 *ms = -1; 00986 else { 00987 /* Just an interrupt */ 00988 #if 0 00989 *ms = 0; 00990 #endif 00991 } 00992 return NULL; 00993 } 00994 00995 if (havewhen) 00996 time(&now); 00997 spoint = 0; 00998 for (x=0;x<n;x++) { 00999 c[x]->blocking = 0; 01000 if (havewhen && c[x]->whentohangup && (now > c[x]->whentohangup)) { 01001 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 01002 if (!winner) 01003 winner = c[x]; 01004 } 01005 for (y=0;y<AST_MAX_FDS;y++) { 01006 if (c[x]->fds[y] > -1) { 01007 if ((res = ast_fdisset(pfds, c[x]->fds[y], max, &spoint))) { 01008 if (res & POLLPRI) 01009 c[x]->exception = -1; 01010 else 01011 c[x]->exception = 0; 01012 c[x]->fdno = y; 01013 winner = c[x]; 01014 } 01015 } 01016 } 01017 } 01018 for (x=0;x<nfds;x++) { 01019 if (fds[x] > -1) { 01020 if ((res = ast_fdisset(pfds, fds[x], max, &spoint))) { 01021 if (outfd) 01022 *outfd = fds[x]; 01023 if (exception) { 01024 if (res & POLLPRI) 01025 *exception = -1; 01026 else 01027 *exception = 0; 01028 } 01029 winner = NULL; 01030 } 01031 } 01032 } 01033 if (*ms > 0) { 01034 long diff; 01035 gettimeofday(&end, NULL); 01036 diff = (end.tv_sec - start.tv_sec) * 1000; 01037 diff += (end.tv_usec - start.tv_usec) / 1000; 01038 if (diff < *ms) 01039 *ms -= diff; 01040 else 01041 *ms = 0; 01042 } 01043 return winner; 01044 }

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

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

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

01066 { 01067 /* XXX Should I be merged with waitfordigit_full XXX */ 01068 struct ast_frame *f; 01069 char result = 0; 01070 /* Stop if we're a zombie or need a soft hangup */ 01071 if (c->zombie || ast_check_hangup(c)) 01072 return -1; 01073 /* Wait for a digit, no more than ms milliseconds total. */ 01074 while(ms && !result) { 01075 ms = ast_waitfor(c, ms); 01076 if (ms < 0) /* Error */ 01077 result = -1; 01078 else if (ms > 0) { 01079 /* Read something */ 01080 f = ast_read(c); 01081 if (f) { 01082 if (f->frametype == AST_FRAME_DTMF) 01083 result = f->subclass; 01084 ast_frfree(f); 01085 } else 01086 result = -1; 01087 } 01088 } 01089 return result; 01090 }

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

Definition at line 1109 of file channel.c.

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

Referenced by ast_readstring_full().

01110 { 01111 struct ast_frame *f; 01112 struct ast_channel *rchan; 01113 int outfd; 01114 int res; 01115 /* Stop if we're a zombie or need a soft hangup */ 01116 if (c->zombie || ast_check_hangup(c)) 01117 return -1; 01118 /* Wait for a digit, no more than ms milliseconds total. */ 01119 while(ms) { 01120 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 01121 if ((!rchan) && (outfd < 0) && (ms)) { 01122 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 01123 return -1; 01124 } else if (outfd > -1) { 01125 /* The FD we were watching has something waiting */ 01126 return 1; 01127 } else if (rchan) { 01128 f = ast_read(c); 01129 if(!f) { 01130 return -1; 01131 } 01132 01133 switch(f->frametype) { 01134 case AST_FRAME_DTMF: 01135 res = f->subclass; 01136 ast_frfree(f); 01137 return res; 01138 case AST_FRAME_CONTROL: 01139 switch(f->subclass) { 01140 case AST_CONTROL_HANGUP: 01141 ast_frfree(f); 01142 return -1; 01143 case AST_CONTROL_RINGING: 01144 case AST_CONTROL_ANSWER: 01145 /* Unimportant */ 01146 break; 01147 default: 01148 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass); 01149 } 01150 case AST_FRAME_VOICE: 01151 /* Write audio if appropriate */ 01152 if (audiofd > -1) 01153 write(audiofd, f->data, f->datalen); 01154 } 01155 /* Ignore */ 01156 ast_frfree(f); 01157 } 01158 } 01159 return 0; // Time is up 01160 }

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

References ast_channel::_softhangup, ast_check_hangup(), ast_deactivate_generator(), ast_do_masquerade(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dump(), AST_FRAME_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_dtmf_stream(), ast_prod(), ast_rtp_bridge(), and ast_write_video().

01531 { 01532 int res = -1; 01533 struct ast_frame *f = NULL; 01534 /* Stop if we're a zombie or need a soft hangup */ 01535 ast_mutex_lock(&chan->lock); 01536 if (chan->zombie || ast_check_hangup(chan)) { 01537 ast_mutex_unlock(&chan->lock); 01538 return -1; 01539 } 01540 /* Handle any pending masquerades */ 01541 if (chan->masq) { 01542 if (ast_do_masquerade(chan)) { 01543 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 01544 ast_mutex_unlock(&chan->lock); 01545 return -1; 01546 } 01547 } 01548 if (chan->masqr) { 01549 ast_mutex_unlock(&chan->lock); 01550 return 0; 01551 } 01552 if (chan->generatordata) { 01553 if (chan->writeinterrupt) 01554 ast_deactivate_generator(chan); 01555 else { 01556 ast_mutex_unlock(&chan->lock); 01557 return 0; 01558 } 01559 } 01560 if (chan->fout & 0x80000000) 01561 ast_frame_dump(chan->name, fr, ">>"); 01562 CHECK_BLOCKING(chan); 01563 switch(fr->frametype) { 01564 case AST_FRAME_CONTROL: 01565 /* XXX Interpret control frames XXX */ 01566 ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n"); 01567 break; 01568 case AST_FRAME_DTMF: 01569 chan->blocking = 0; 01570 ast_mutex_unlock(&chan->lock); 01571 res = do_senddigit(chan,fr->subclass); 01572 ast_mutex_lock(&chan->lock); 01573 CHECK_BLOCKING(chan); 01574 break; 01575 case AST_FRAME_TEXT: 01576 if (chan->pvt->send_text) 01577 res = chan->pvt->send_text(chan, (char *) fr->data); 01578 break; 01579 case AST_FRAME_VIDEO: 01580 /* XXX Handle translation of video codecs one day XXX */ 01581 if (chan->pvt->write_video) 01582 res = chan->pvt->write_video(chan, fr); 01583 else 01584 res = 0; 01585 break; 01586 default: 01587 if (chan->pvt->write) { 01588 if (chan->pvt->writetrans) { 01589 f = ast_translate(chan->pvt->writetrans, fr, 0); 01590 } else 01591 f = fr; 01592 if (f) { 01593 res = chan->pvt->write(chan, f); 01594 if( chan->monitor && 01595 chan->monitor->write_stream && 01596 f && ( f->frametype == AST_FRAME_VOICE ) ) { 01597 #ifndef MONITOR_CONSTANT_DELAY 01598 int jump = chan->insmpl - chan->outsmpl - 2 * f->samples; 01599 if (jump >= 0) { 01600 if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1) 01601 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 01602 chan->outsmpl += jump + 2 * f->samples; 01603 } else 01604 chan->outsmpl += f->samples; 01605 #else 01606 int jump = chan->insmpl - chan->outsmpl; 01607 if (jump - MONITOR_DELAY >= 0) { 01608 if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1) 01609 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 01610 chan->outsmpl += jump; 01611 } else 01612 chan->outsmpl += f->samples; 01613 #endif 01614 if (ast_writestream(chan->monitor->write_stream, f) < 0) 01615 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n"); 01616 } 01617 } else 01618 res = 0; 01619 } 01620 } 01621 if (f && (f != fr)) 01622 ast_frfree(f); 01623 chan->blocking = 0; 01624 /* Consider a write failure to force a soft hangup */ 01625 if (res < 0) 01626 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01627 else { 01628 if ((chan->fout & 0x7fffffff) == 0x7fffffff) 01629 chan->fout &= 0x80000000; 01630 else 01631 chan->fout++; 01632 chan->fout++; 01633 } 01634 ast_mutex_unlock(&chan->lock); 01635 return res; 01636 }

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

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

01520 { 01521 int res; 01522 if (!chan->pvt->write_video) 01523 return 0; 01524 res = ast_write(chan, fr); 01525 if (!res) 01526 res = 1; 01527 return res; 01528 }


Variable Documentation

struct chanlist * backends
 

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

struct ast_channel* channels = NULL
 

Definition at line 72 of file channel.c.

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


Generated on Tue Aug 17 16:13:54 2004 for Asterisk by doxygen 1.3.8