#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <math.h>
#include <sys/poll.h>
#include <asterisk/pbx.h>
#include <asterisk/frame.h>
#include <asterisk/sched.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/logger.h>
#include <asterisk/say.h>
#include <asterisk/file.h>
#include <asterisk/translate.h>
#include <asterisk/manager.h>
#include <asterisk/chanvars.h>
#include <asterisk/linkedlists.h>
#include <asterisk/indications.h>
#include <asterisk/monitor.h>
#include <asterisk/causes.h>
#include <asterisk/utils.h>
#include <asterisk/lock.h>
#include "astconf.h"
Go to the source code of this file.
Functions | |
AST_MUTEX_DEFINE_STATIC (uniquelock) | |
AST_MUTEX_DEFINE_STATIC (chlock) | |
int | ast_check_hangup (struct ast_channel *chan) |
Check to see if a channel is needing hang up. | |
void | ast_begin_shutdown (int hangup) |
int | ast_active_channels (void) |
void | ast_cancel_shutdown (void) |
int | ast_shutting_down (void) |
void | ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset) |
Set when to hang a channel up. | |
int | ast_channel_register (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data)) |
Registers a channel. | |
int | ast_channel_register_ex (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data), int(*devicestate)(void *data)) |
char * | ast_state2str (int state) |
Gives the string form of a given state. | |
int | ast_best_codec (int fmts) |
Pick the best codec. | |
char * | ast_alloc_uniqueid (void) |
ast_channel * | ast_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_channel * | ast_channel_walk_locked (struct ast_channel *prev) |
Browse channels in use. | |
ast_channel * | ast_get_channel_by_name_locked (char *channame) |
Get channel by name (locks channel). | |
ast_channel * | ast_get_channel_by_uniqueid_locked (char *uniqueid) |
Get channel by uniqueid (locks channel). | |
int | ast_safe_sleep_conditional (struct ast_channel *chan, int ms, int(*cond)(void *), void *data) |
Wait for a specied amount of time, looking for hangups and a condition argument. | |
int | ast_safe_sleep (struct ast_channel *chan, int ms) |
Wait for a specied amount of time, looking for hangups. | |
void | ast_channel_free (struct ast_channel *chan) |
Free a channel structure. | |
int | ast_softhangup_nolock (struct ast_channel *chan, int cause) |
int | ast_softhangup (struct ast_channel *chan, int cause) |
Softly hangup up a channel. | |
int | ast_hangup (struct ast_channel *chan) |
Hang up a channel. | |
void | ast_channel_unregister (char *type) |
Unregister a channel class. | |
int | ast_answer (struct ast_channel *chan) |
Answer a ringing call. | |
void | ast_deactivate_generator (struct ast_channel *chan) |
int | ast_activate_generator (struct ast_channel *chan, struct ast_generator *gen, void *params) |
int | ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception) |
Waits for input on an fd. | |
ast_channel * | ast_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_channel * | ast_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_frame * | ast_read (struct ast_channel *chan) |
Reads a frame. | |
int | ast_indicate (struct ast_channel *chan, int condition) |
Indicates condition of channel. | |
int | ast_recvchar (struct ast_channel *chan, int timeout) |
int | ast_sendtext (struct ast_channel *chan, char *text) |
Sends text to a channel. | |
int | ast_senddigit (struct ast_channel *chan, char digit) |
Receives a text character from a channel. | |
int | ast_prod (struct ast_channel *chan) |
int | ast_write_video (struct ast_channel *chan, struct ast_frame *fr) |
Write video frame to a channel. | |
int | ast_write (struct ast_channel *chan, struct ast_frame *fr) |
Write a frame to a channel. | |
int | ast_set_write_format (struct ast_channel *chan, int fmts) |
Sets write format on channel chan. | |
int | ast_set_read_format (struct ast_channel *chan, int fmts) |
Sets read format on channel chan. | |
ast_channel * | __ast_request_and_dial (char *type, int format, void *data, int timeout, int *outstate, int callingpres, char *callerid, struct outgoing_helper *oh, char *uniqueid) |
ast_channel * | ast_request_and_dial (char *type, int format, void *data, int timeout, int *outstate, int callingpres, char *callerid, char *uniqueid) |
ast_channel * | ast_request (char *type, int format, void *data, char *uniqueid) |
Requests a channel. | |
int | ast_parse_device_state (char *device) |
Search the Channels by Name. | |
int | ast_device_state (char *device) |
Asks a channel for device state. | |
int | ast_call (struct ast_channel *chan, char *addr, int timeout) |
Make a call. | |
int | ast_transfer (struct ast_channel *chan, char *dest) |
int | ast_readstring (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders) |
Reads multiple digits. | |
int | ast_readstring_full (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd) |
int | ast_channel_supports_html (struct ast_channel *chan) |
Checks for HTML support on a channel. | |
int | ast_channel_sendhtml (struct ast_channel *chan, int subclass, char *data, int datalen) |
Sends HTML on given channel. | |
int | ast_channel_sendurl (struct ast_channel *chan, char *url) |
Sends a URL on a given link. | |
int | ast_channel_make_compatible (struct ast_channel *chan, struct ast_channel *peer) |
Makes two channel formats compatible. | |
int | ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone) |
Weird function made for call transfers. | |
int | ast_channel_masquerade_locked (struct ast_channel *original, struct ast_channel *clone) |
void | ast_change_name (struct ast_channel *chan, char *newname) |
int | ast_do_masquerade (struct ast_channel *original) |
void | ast_set_callerid (struct ast_channel *chan, char *callerid, int anitoo) |
int | ast_setstate (struct ast_channel *chan, int state) |
int | ast_channel_bridge (struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc) |
Bridge two channels together. | |
int | ast_channel_setoption (struct ast_channel *chan, int option, void *data, int datalen, int block) |
Sets an option on a channel. | |
int | ast_tonepair_start (struct ast_channel *chan, int freq1, int freq2, int duration, int vol) |
void | ast_tonepair_stop (struct ast_channel *chan) |
int | ast_tonepair (struct ast_channel *chan, int freq1, int freq2, int duration, int vol) |
unsigned int | ast_get_group (char *s) |
Variables | |
int | ast_mainpid |
chanlist * | backends |
ast_channel * | channels = NULL |
|
Definition at line 1779 of file channel.c. References ast_channel::_state, ast_call(), ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_setapp(), ast_cdr_start(), ast_cdr_update(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_frfree(), ast_hangup(), ast_log(), ast_read(), ast_request(), ast_set_callerid(), AST_STATE_UP, ast_waitfor(), ast_channel::callerid, ast_channel::callingpres, ast_channel::cdr, ast_channel::context, ast_channel::exten, ast_frame::frametype, ast_channel::hangupcause, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar(), ast_channel::priority, ast_frame::subclass, and type. Referenced by ast_pbx_outgoing_exten(), and ast_request_and_dial(). 01780 { 01781 int state = 0; 01782 struct ast_channel *chan; 01783 struct ast_frame *f; 01784 int res = 0; 01785 char *variable; 01786 chan = ast_request(type, format, data, uniqueid); 01787 if (chan) { 01788 if (oh) { 01789 char *tmp, *var; 01790 /* JDG chanvar */ 01791 if (oh->variable) 01792 variable = ast_strdupa(oh->variable); 01793 else 01794 variable = NULL; 01795 tmp = variable; 01796 /* FIXME replace this call with strsep NOT*/ 01797 while( (var = strtok_r(NULL, "|", &tmp)) ) { 01798 pbx_builtin_setvar( chan, var ); 01799 } /* /JDG */ 01800 if (oh->callerid && *oh->callerid) 01801 ast_set_callerid(chan, oh->callerid, 1); 01802 if (oh->account && *oh->account) 01803 ast_cdr_setaccount(chan, oh->account); 01804 } 01805 if (callerid && !ast_strlen_zero(callerid)) 01806 ast_set_callerid(chan, callerid, 1); 01807 01808 chan->callingpres = callingpres; 01809 if (!ast_call(chan, data, 0)) { 01810 while(timeout && (chan->_state != AST_STATE_UP)) { 01811 res = ast_waitfor(chan, timeout); 01812 if (res < 0) { 01813 /* Something not cool, or timed out */ 01814 break; 01815 } 01816 /* If done, break out */ 01817 if (!res) 01818 break; 01819 if (timeout > -1) 01820 timeout = res; 01821 f = ast_read(chan); 01822 if (!f) { 01823 state = AST_CONTROL_HANGUP; 01824 res = 0; 01825 break; 01826 } 01827 if (f->frametype == AST_FRAME_CONTROL) { 01828 if (f->subclass == AST_CONTROL_RINGING) 01829 state = AST_CONTROL_RINGING; 01830 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) { 01831 res = 0; 01832 state = f->subclass; 01833 ast_frfree(f); 01834 break; 01835 } else if (f->subclass == AST_CONTROL_ANSWER) { 01836 state = f->subclass; 01837 ast_frfree(f); 01838 break; 01839 } else if (f->subclass == AST_CONTROL_PROGRESS) { 01840 /* Ignore */ 01841 } else if (f->subclass == -1) { 01842 /* Ignore -- just stopping indications */ 01843 } else { 01844 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass); 01845 } 01846 } 01847 ast_frfree(f); 01848 } 01849 } else 01850 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 01851 } else 01852 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 01853 if (chan) { 01854 /* Final fixups */ 01855 if (oh) { 01856 if (oh->context && *oh->context) 01857 strncpy(chan->context, oh->context, sizeof(chan->context) - 1); 01858 if (oh->exten && *oh->exten) 01859 strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1); 01860 chan->priority = oh->priority; 01861 } 01862 if (chan->_state == AST_STATE_UP) 01863 state = AST_CONTROL_ANSWER; 01864 } 01865 if (outstate) 01866 *outstate = state; 01867 if (chan && res <= 0) { 01868 if (!chan->cdr) { 01869 chan->cdr = ast_cdr_alloc(); 01870 if (chan->cdr) 01871 ast_cdr_init(chan->cdr, chan); 01872 } 01873 if (chan->cdr) { 01874 char tmp[256]; 01875 snprintf(tmp, 256, "%s/%s", type, (char *)data); 01876 ast_cdr_setapp(chan->cdr,"Dial",tmp); 01877 ast_cdr_update(chan); 01878 ast_cdr_start(chan->cdr); 01879 ast_cdr_end(chan->cdr); 01880 /* If the cause wasn't handled properly */ 01881 if (ast_cdr_disposition(chan->cdr,chan->hangupcause)) 01882 ast_cdr_failed(chan->cdr); 01883 } else 01884 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 01885 ast_hangup(chan); 01886 chan = NULL; 01887 } 01888 return chan; 01889 }
|
|
Activate a given generator Definition at line 882 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, ast_prod(), ast_settimeout(), ast_channel::generator, and ast_generator::release. Referenced by ast_linear_stream(), ast_playtones_start(), and ast_tonepair_start(). 00883 { 00884 int res = 0; 00885 ast_mutex_lock(&chan->lock); 00886 if (chan->generatordata) { 00887 if (chan->generator && chan->generator->release) 00888 chan->generator->release(chan, chan->generatordata); 00889 chan->generatordata = NULL; 00890 } 00891 ast_prod(chan); 00892 if ((chan->generatordata = gen->alloc(chan, params))) { 00893 ast_settimeout(chan, 160, generator_force, chan); 00894 chan->generator = gen; 00895 } else { 00896 res = -1; 00897 } 00898 ast_mutex_unlock(&chan->lock); 00899 return res; 00900 }
|
|
Returns number of active/allocated channels Definition at line 123 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, channels, and ast_channel::next. 00124 { 00125 struct ast_channel *c; 00126 int cnt = 0; 00127 ast_mutex_lock(&chlock); 00128 c = channels; 00129 while(c) { 00130 cnt++; 00131 c = c->next; 00132 } 00133 ast_mutex_unlock(&chlock); 00134 return cnt; 00135 }
|
|
Definition at line 277 of file channel.c. References ast_config_AST_SYMBOLIC_NAME, ast_mainpid, ast_mutex_lock, ast_mutex_unlock, malloc, and uniquelock. Referenced by ast_channel_alloc(). 00277 { 00278 char *uniqueid; 00279 uniqueid = malloc(64); 00280 if (!uniqueid) return NULL; 00281 ast_mutex_lock(&uniquelock); 00282 snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYMBOLIC_NAME, ast_mainpid, (long)time(NULL), uniqueint++); 00283 ast_mutex_unlock(&uniquelock); 00284 // ast_log(LOG_NOTICE,"uid = %s\n",uniqueid); 00285 return uniqueid; 00286 }
|
|
Answer a ringing call.
Definition at line 818 of file channel.c. References ast_cdr_answer(), ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_RING, AST_STATE_RINGING, and AST_STATE_UP. Referenced by ast_control_streamfile(). 00819 { 00820 int res = 0; 00821 ast_mutex_lock(&chan->lock); 00822 /* Stop if we're a zombie or need a soft hangup */ 00823 if (chan->zombie || ast_check_hangup(chan)) { 00824 ast_mutex_unlock(&chan->lock); 00825 return -1; 00826 } 00827 switch(chan->_state) { 00828 case AST_STATE_RINGING: 00829 case AST_STATE_RING: 00830 if (chan->pvt->answer) 00831 res = chan->pvt->answer(chan); 00832 ast_setstate(chan, AST_STATE_UP); 00833 if (chan->cdr) 00834 ast_cdr_answer(chan->cdr); 00835 ast_mutex_unlock(&chan->lock); 00836 return res; 00837 break; 00838 case AST_STATE_UP: 00839 if (chan->cdr) 00840 ast_cdr_answer(chan->cdr); 00841 break; 00842 } 00843 ast_mutex_unlock(&chan->lock); 00844 return 0; 00845 }
|
|
Initiate system shutdown -- prevents new channels from being allocated. If "hangup" is non-zero, all existing channels will receive soft hangups Definition at line 108 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), AST_SOFTHANGUP_SHUTDOWN, channels, and ast_channel::next. 00109 { 00110 struct ast_channel *c; 00111 shutting_down = 1; 00112 if (hangup) { 00113 ast_mutex_lock(&chlock); 00114 c = channels; 00115 while(c) { 00116 ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN); 00117 c = c->next; 00118 } 00119 ast_mutex_unlock(&chlock); 00120 } 00121 }
|
|
Pick the best codec.
Definition at line 236 of file channel.c. References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_ILBC, AST_FORMAT_LPC10, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, ast_log(), and LOG_WARNING. Referenced by ast_codec_choose(). 00237 { 00238 /* This just our opinion, expressed in code. We are asked to choose 00239 the best codec to use, given no information */ 00240 int x; 00241 static int prefs[] = 00242 { 00243 /* Okay, ulaw is used by all telephony equipment, so start with it */ 00244 AST_FORMAT_ULAW, 00245 /* Unless of course, you're a silly European, so then prefer ALAW */ 00246 AST_FORMAT_ALAW, 00247 /* Okay, well, signed linear is easy to translate into other stuff */ 00248 AST_FORMAT_SLINEAR, 00249 /* G.726 is standard ADPCM */ 00250 AST_FORMAT_G726, 00251 /* ADPCM has great sound quality and is still pretty easy to translate */ 00252 AST_FORMAT_ADPCM, 00253 /* Okay, we're down to vocoders now, so pick GSM because it's small and easier to 00254 translate and sounds pretty good */ 00255 AST_FORMAT_GSM, 00256 /* iLBC is not too bad */ 00257 AST_FORMAT_ILBC, 00258 /* Speex is free, but computationally more expensive than GSM */ 00259 AST_FORMAT_SPEEX, 00260 /* Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough 00261 to use it */ 00262 AST_FORMAT_LPC10, 00263 /* G.729a is faster than 723 and slightly less expensive */ 00264 AST_FORMAT_G729A, 00265 /* Down to G.723.1 which is proprietary but at least designed for voice */ 00266 AST_FORMAT_G723_1, 00267 }; 00268 00269 00270 for (x=0;x<sizeof(prefs) / sizeof(prefs[0]); x++) 00271 if (fmts & prefs[x]) 00272 return prefs[x]; 00273 ast_log(LOG_WARNING, "Don't know any of 0x%x formats\n", fmts); 00274 return 0; 00275 }
|
|
Make a call.
Definition at line 2005 of file channel.c. References ast_check_hangup(), ast_mutex_lock, and ast_mutex_unlock. Referenced by __ast_request_and_dial(). 02006 { 02007 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 02008 If the remote end does not answer within the timeout, then do NOT hang up, but 02009 return anyway. */ 02010 int res = -1; 02011 /* Stop if we're a zombie or need a soft hangup */ 02012 ast_mutex_lock(&chan->lock); 02013 if (!chan->zombie && !ast_check_hangup(chan)) 02014 if (chan->pvt->call) 02015 res = chan->pvt->call(chan, addr, timeout); 02016 ast_mutex_unlock(&chan->lock); 02017 return res; 02018 }
|
|
Cancels an existing shutdown and returns to normal operation Definition at line 137 of file channel.c. 00138 { 00139 shutting_down = 0; 00140 }
|
|
Definition at line 2247 of file channel.c. References EVENT_FLAG_CALL, and manager_event(). 02248 { 02249 char tmp[256]; 02250 strncpy(tmp, chan->name, sizeof(tmp) - 1); 02251 strncpy(chan->name, newname, sizeof(chan->name) - 1); 02252 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid); 02253 }
|
|
Create a channel structure. Returns NULL on failure to allocate Definition at line 288 of file channel.c. References ast_channel::_state, ast_channel::accountcode, ast_channel_pvt::alertpipe, ast_channel::amaflags, ast_channel::appl, ast_alloc_uniqueid(), ast_default_accountcode, ast_default_amaflags, AST_LIST_HEAD_INIT, AST_LIST_INSERT_HEAD, ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, AST_STATE_DOWN, ast_var_assign(), channels, ast_channel::context, ast_channel::data, defaultlanguage, ast_channel::exten, ast_channel::fds, ast_channel::fin, ast_channel::fout, free, ast_channel::language, ast_channel::lock, LOG_WARNING, malloc, ast_channel::name, ast_channel::next, ast_channel::priority, ast_channel::pvt, ast_channel::sched, sched_context_create(), ast_channel::stack, ast_channel::streamid, ast_channel::timingfd, ast_channel::uniqueid, and ast_channel::vars. Referenced by ast_async_goto(), and ast_pbx_outgoing_exten(). 00289 { 00290 struct ast_channel *tmp; 00291 struct ast_channel_pvt *pvt; 00292 int x; 00293 int flags; 00294 struct varshead *headp; 00295 char *tmpuniqueid; 00296 00297 00298 /* If shutting down, don't allocate any new channels */ 00299 if (shutting_down) 00300 return NULL; 00301 ast_mutex_lock(&chlock); 00302 tmp = malloc(sizeof(struct ast_channel)); 00303 if (tmp) { 00304 memset(tmp, 0, sizeof(struct ast_channel)); 00305 pvt = malloc(sizeof(struct ast_channel_pvt)); 00306 if (pvt) { 00307 memset(pvt, 0, sizeof(struct ast_channel_pvt)); 00308 tmp->sched = sched_context_create(); 00309 if (tmp->sched) { 00310 for (x=0;x<AST_MAX_FDS - 1;x++) 00311 tmp->fds[x] = -1; 00312 #ifdef ZAPTEL_OPTIMIZATIONS 00313 tmp->timingfd = open("/dev/zap/timer", O_RDWR); 00314 if (tmp->timingfd > -1) { 00315 /* Check if timing interface supports new 00316 ping/pong scheme */ 00317 flags = 1; 00318 if (!ioctl(tmp->timingfd, ZT_TIMERPONG, &flags)) 00319 needqueue = 0; 00320 } 00321 #else 00322 tmp->timingfd = -1; 00323 #endif 00324 if (needqueue && 00325 pipe(pvt->alertpipe)) { 00326 ast_log(LOG_WARNING, "Alert pipe creation failed!\n"); 00327 free(pvt); 00328 free(tmp); 00329 tmp = NULL; 00330 pvt = NULL; 00331 } else { 00332 if (needqueue) { 00333 flags = fcntl(pvt->alertpipe[0], F_GETFL); 00334 fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK); 00335 flags = fcntl(pvt->alertpipe[1], F_GETFL); 00336 fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK); 00337 } else 00338 /* Make sure we've got it done right if they don't */ 00339 pvt->alertpipe[0] = pvt->alertpipe[1] = -1; 00340 /* Always watch the alertpipe */ 00341 tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0]; 00342 /* And timing pipe */ 00343 tmp->fds[AST_MAX_FDS-2] = tmp->timingfd; 00344 strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1); 00345 tmp->pvt = pvt; 00346 /* Initial state */ 00347 tmp->_state = AST_STATE_DOWN; 00348 tmp->stack = -1; 00349 tmp->streamid = -1; 00350 tmp->appl = NULL; 00351 tmp->data = NULL; 00352 tmp->fin = 0; 00353 tmp->fout = 0; 00354 tmpuniqueid = ast_alloc_uniqueid(); 00355 snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), tmpuniqueid); 00356 if (tmpuniqueid) { 00357 free(tmpuniqueid); 00358 tmpuniqueid = NULL; 00359 } 00360 headp=&tmp->varshead; 00361 ast_mutex_init(&tmp->lock); 00362 AST_LIST_HEAD_INIT(headp); 00363 tmp->vars=ast_var_assign("tempvar","tempval"); 00364 AST_LIST_INSERT_HEAD(headp,tmp->vars,entries); 00365 strncpy(tmp->context, "default", sizeof(tmp->context)-1); 00366 strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1); 00367 strncpy(tmp->exten, "s", sizeof(tmp->exten)-1); 00368 tmp->priority=1; 00369 tmp->amaflags = ast_default_amaflags; 00370 strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1); 00371 tmp->next = channels; 00372 channels= tmp; 00373 } 00374 } else { 00375 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 00376 free(tmp); 00377 tmp = NULL; 00378 } 00379 } else { 00380 ast_log(LOG_WARNING, "Out of memory\n"); 00381 free(tmp); 00382 tmp = NULL; 00383 } 00384 } else 00385 ast_log(LOG_WARNING, "Out of memory\n"); 00386 ast_mutex_unlock(&chlock); 00387 return tmp; 00388 }
|
|
Bridge two channels together.
Definition at line 2570 of file channel.c. References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, ast_channel_make_compatible(), ast_check_hangup(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_verbose(), ast_waitfor_n(), ast_write(), ast_channel::bridge, EVENT_FLAG_CALL, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::name, ast_channel::nativeformats, option_verbose, ast_frame::subclass, and VERBOSE_PREFIX_3. 02571 { 02572 /* Copy voice back and forth between the two channels. Give the peer 02573 the ability to transfer calls with '#<extension' syntax. */ 02574 int flags; 02575 struct ast_channel *cs[3]; 02576 int to = -1; 02577 struct ast_frame *f; 02578 struct ast_channel *who = NULL; 02579 int res=0; 02580 int nativefailed=0; 02581 int firstpass; 02582 int o0nativeformats; 02583 int o1nativeformats; 02584 struct timeval start_time,precise_now; 02585 long elapsed_ms=0, time_left_ms=0; 02586 int playit=0, playitagain=1, first_time=1; 02587 02588 flags = (config->allowdisconnect_out||config->allowredirect_out ? AST_BRIDGE_DTMF_CHANNEL_0 : 0) + (config->allowdisconnect_in||config->allowredirect_in ? AST_BRIDGE_DTMF_CHANNEL_1 : 0); 02589 02590 firstpass = config->firstpass; 02591 config->firstpass = 0; 02592 02593 /* timestamp */ 02594 gettimeofday(&start_time,NULL); 02595 time_left_ms = config->timelimit; 02596 02597 if (config->play_to_caller && config->start_sound && firstpass) 02598 bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000); 02599 if (config->play_to_callee && config->start_sound && firstpass) 02600 bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000); 02601 02602 /* Stop if we're a zombie or need a soft hangup */ 02603 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 02604 return -1; 02605 if (c0->bridge) { 02606 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 02607 c0->name, c0->bridge->name); 02608 return -1; 02609 } 02610 if (c1->bridge) { 02611 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 02612 c1->name, c1->bridge->name); 02613 return -1; 02614 } 02615 02616 /* Keep track of bridge */ 02617 c0->bridge = c1; 02618 c1->bridge = c0; 02619 cs[0] = c0; 02620 cs[1] = c1; 02621 02622 manager_event(EVENT_FLAG_CALL, "Link", 02623 "Channel1: %s\r\n" 02624 "Channel2: %s\r\n" 02625 "Uniqueid1: %s\r\n" 02626 "Uniqueid2: %s\r\n", 02627 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02628 o1nativeformats = c1->nativeformats; 02629 o0nativeformats = c0->nativeformats; 02630 for (/* ever */;;) { 02631 /* timestamp */ 02632 if (config->timelimit) { 02633 gettimeofday(&precise_now,NULL); 02634 elapsed_ms = tvdiff(&precise_now,&start_time); 02635 time_left_ms = config->timelimit - elapsed_ms; 02636 02637 if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) { 02638 /* narrowing down to the end */ 02639 if (config->warning_freq == 0) { 02640 playit = 1; 02641 first_time=0; 02642 playitagain=0; 02643 } else if (first_time) { 02644 playit = 1; 02645 first_time=0; 02646 } else { 02647 if ((time_left_ms % config->warning_freq) <= 50) { 02648 playit = 1; 02649 } 02650 } 02651 } 02652 if (time_left_ms <= 0) { 02653 if (config->play_to_caller && config->end_sound) 02654 bridge_playfile(c0,c1,config->end_sound,0); 02655 if (config->play_to_callee && config->end_sound) 02656 bridge_playfile(c1,c0,config->end_sound,0); 02657 *fo = NULL; 02658 if (who) *rc = who; 02659 res = 0; 02660 break; 02661 } 02662 if (time_left_ms >= 5000 && playit) { 02663 if (config->play_to_caller && config->warning_sound && config->play_warning) 02664 bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000); 02665 if (config->play_to_callee && config->warning_sound && config->play_warning) 02666 bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000); 02667 playit = 0; 02668 } 02669 02670 } 02671 /* Stop if we're a zombie or need a soft hangup */ 02672 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) { 02673 *fo = NULL; 02674 if (who) *rc = who; 02675 res = 0; 02676 ast_log(LOG_DEBUG, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",c0->name,c1->name,c0->zombie?"Yes":"No",ast_check_hangup(c0)?"Yes":"No",c1->zombie?"Yes":"No",ast_check_hangup(c1)?"Yes":"No"); 02677 break; 02678 } 02679 if (c0->pvt->bridge && config->timelimit==0 && 02680 (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) { 02681 /* Looks like they share a bridge code */ 02682 if (option_verbose > 2) 02683 ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name); 02684 if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) { 02685 c0->bridge = NULL; 02686 c1->bridge = NULL; 02687 manager_event(EVENT_FLAG_CALL, "Unlink", 02688 "Channel1: %s\r\n" 02689 "Channel2: %s\r\n" 02690 "Uniqueid1: %s\r\n" 02691 "Uniqueid2: %s\r\n", 02692 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02693 ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name); 02694 return 0; 02695 } 02696 /* If they return non-zero then continue on normally. Let "-2" mean don't worry about 02697 my not wanting to bridge */ 02698 if ((res != -2) && (res != -3)) 02699 ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name); 02700 if (res != -3) nativefailed++; 02701 } 02702 02703 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) && 02704 !(c0->generator || c1->generator)) { 02705 if (ast_channel_make_compatible(c0, c1)) { 02706 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); 02707 manager_event(EVENT_FLAG_CALL, "Unlink", 02708 "Channel1: %s\r\n" 02709 "Channel2: %s\r\n" 02710 "Uniqueid1: %s\r\n" 02711 "Uniqueid2: %s\r\n", 02712 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02713 return -1; 02714 } 02715 o0nativeformats = c0->nativeformats; 02716 o1nativeformats = c1->nativeformats; 02717 } 02718 who = ast_waitfor_n(cs, 2, &to); 02719 if (!who) { 02720 ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 02721 continue; 02722 } 02723 f = ast_read(who); 02724 if (!f) { 02725 *fo = NULL; 02726 *rc = who; 02727 res = 0; 02728 ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name); 02729 break; 02730 } 02731 02732 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02733 *fo = f; 02734 *rc = who; 02735 res = 0; 02736 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name); 02737 break; 02738 } 02739 if ((f->frametype == AST_FRAME_VOICE) || 02740 (f->frametype == AST_FRAME_TEXT) || 02741 (f->frametype == AST_FRAME_VIDEO) || 02742 (f->frametype == AST_FRAME_IMAGE) || 02743 (f->frametype == AST_FRAME_DTMF)) { 02744 if ((f->frametype == AST_FRAME_DTMF) && 02745 (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) { 02746 if ((who == c0)) { 02747 if ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 02748 *rc = c0; 02749 *fo = f; 02750 /* Take out of conference mode */ 02751 res = 0; 02752 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name); 02753 break; 02754 } else 02755 goto tackygoto; 02756 } else 02757 if ((who == c1)) { 02758 if (flags & AST_BRIDGE_DTMF_CHANNEL_1) { 02759 *rc = c1; 02760 *fo = f; 02761 res = 0; 02762 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name); 02763 break; 02764 } else 02765 goto tackygoto; 02766 } 02767 } else { 02768 #if 0 02769 ast_log(LOG_DEBUG, "Read from %s\n", who->name); 02770 if (who == last) 02771 ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name); 02772 last = who; 02773 #endif 02774 tackygoto: 02775 /* Don't copy packets if there is a generator on either one, since they're 02776 not supposed to be listening anyway */ 02777 if (who == c0) 02778 ast_write(c1, f); 02779 else 02780 ast_write(c0, f); 02781 } 02782 ast_frfree(f); 02783 } else 02784 ast_frfree(f); 02785 /* Swap who gets priority */ 02786 cs[2] = cs[0]; 02787 cs[0] = cs[1]; 02788 cs[1] = cs[2]; 02789 } 02790 c0->bridge = NULL; 02791 c1->bridge = NULL; 02792 manager_event(EVENT_FLAG_CALL, "Unlink", 02793 "Channel1: %s\r\n" 02794 "Channel2: %s\r\n" 02795 "Uniqueid1: %s\r\n" 02796 "Uniqueid2: %s\r\n", 02797 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02798 ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name); 02799 return res; 02800 }
|
|
Defers DTMF. Defer DTMF so that you only read things like hangups and audio. Returns non-zero if channel was already DTMF-deferred or 0 if channel is just now being DTMF-deferred Definition at line 461 of file channel.c. 00462 { 00463 int pre = 0; 00464 if (chan) { 00465 pre = chan->deferdtmf; 00466 chan->deferdtmf = 1; 00467 } 00468 return pre; 00469 }
|
|
Free a channel structure.
Definition at line 594 of file channel.c. References 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(), channels, free, LOG_WARNING, ast_channel::monitor, ast_channel::next, ast_frame::next, and ast_channel_monitor::stop. Referenced by ast_do_masquerade(), and ast_hangup(). 00595 { 00596 struct ast_channel *last=NULL, *cur; 00597 int fd; 00598 struct ast_var_t *vardata; 00599 struct ast_frame *f, *fp; 00600 struct varshead *headp; 00601 char name[AST_CHANNEL_NAME]; 00602 00603 headp=&chan->varshead; 00604 00605 ast_mutex_lock(&chlock); 00606 cur = channels; 00607 while(cur) { 00608 if (cur == chan) { 00609 if (last) 00610 last->next = cur->next; 00611 else 00612 channels = cur->next; 00613 break; 00614 } 00615 last = cur; 00616 cur = cur->next; 00617 } 00618 if (!cur) 00619 ast_log(LOG_WARNING, "Unable to find channel in list\n"); 00620 else { 00621 /* Lock and unlock the channel just to be sure nobody 00622 has it locked still */ 00623 ast_mutex_lock(&cur->lock); 00624 ast_mutex_unlock(&cur->lock); 00625 } 00626 if (chan->pvt->pvt) 00627 ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name); 00628 00629 strncpy(name, chan->name, sizeof(name)-1); 00630 00631 /* Stop monitoring */ 00632 if (chan->monitor) { 00633 chan->monitor->stop( chan, 0 ); 00634 } 00635 00636 /* Free translatosr */ 00637 if (chan->pvt->readtrans) 00638 ast_translator_free_path(chan->pvt->readtrans); 00639 if (chan->pvt->writetrans) 00640 ast_translator_free_path(chan->pvt->writetrans); 00641 if (chan->pbx) 00642 ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name); 00643 if (chan->dnid) 00644 free(chan->dnid); 00645 if (chan->callerid) 00646 free(chan->callerid); 00647 if (chan->ani) 00648 free(chan->ani); 00649 if (chan->rdnis) 00650 free(chan->rdnis); 00651 ast_mutex_destroy(&chan->lock); 00652 /* Close pipes if appropriate */ 00653 if ((fd = chan->pvt->alertpipe[0]) > -1) 00654 close(fd); 00655 if ((fd = chan->pvt->alertpipe[1]) > -1) 00656 close(fd); 00657 if ((fd = chan->timingfd) > -1) 00658 close(fd); 00659 f = chan->pvt->readq; 00660 chan->pvt->readq = NULL; 00661 while(f) { 00662 fp = f; 00663 f = f->next; 00664 ast_frfree(fp); 00665 } 00666 00667 /* loop over the variables list, freeing all data and deleting list items */ 00668 /* no need to lock the list, as the channel is already locked */ 00669 00670 while (!AST_LIST_EMPTY(headp)) { /* List Deletion. */ 00671 vardata = AST_LIST_FIRST(headp); 00672 AST_LIST_REMOVE_HEAD(headp, entries); 00673 // printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata)); 00674 ast_var_delete(vardata); 00675 } 00676 00677 00678 free(chan->pvt); 00679 chan->pvt = NULL; 00680 free(chan); 00681 ast_mutex_unlock(&chlock); 00682 00683 ast_device_state_changed(name); 00684 }
|
|
Makes two channel formats compatible.
Definition at line 2142 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_set_read_format(), ast_set_write_format(), ast_translator_best_choice(), and LOG_WARNING. Referenced by ast_channel_bridge(). 02143 { 02144 int peerf; 02145 int chanf; 02146 int res; 02147 ast_mutex_lock(&peer->lock); 02148 peerf = peer->nativeformats; 02149 ast_mutex_unlock(&peer->lock); 02150 ast_mutex_lock(&chan->lock); 02151 chanf = chan->nativeformats; 02152 ast_mutex_unlock(&chan->lock); 02153 res = ast_translator_best_choice(&peerf, &chanf); 02154 if (res < 0) { 02155 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats); 02156 return -1; 02157 } 02158 /* Set read format on channel */ 02159 res = ast_set_read_format(chan, peerf); 02160 if (res < 0) { 02161 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf); 02162 return -1; 02163 } 02164 /* Set write format on peer channel */ 02165 res = ast_set_write_format(peer, peerf); 02166 if (res < 0) { 02167 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf); 02168 return -1; 02169 } 02170 /* Now we go the other way */ 02171 peerf = peer->nativeformats; 02172 chanf = chan->nativeformats; 02173 res = ast_translator_best_choice(&chanf, &peerf); 02174 if (res < 0) { 02175 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats); 02176 return -1; 02177 } 02178 /* Set writeformat on channel */ 02179 res = ast_set_write_format(chan, chanf); 02180 if (res < 0) { 02181 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf); 02182 return -1; 02183 } 02184 /* Set read format on peer channel */ 02185 res = ast_set_read_format(peer, chanf); 02186 if (res < 0) { 02187 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf); 02188 return -1; 02189 } 02190 return 0; 02191 }
|
|
Weird function made for call transfers.
Definition at line 2193 of file channel.c. References AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_queue_frame(), LOG_DEBUG, and LOG_WARNING. Referenced by ast_async_goto(). 02194 { 02195 struct ast_frame null = { AST_FRAME_NULL, }; 02196 int res = -1; 02197 ast_mutex_lock(&original->lock); 02198 while(ast_mutex_trylock(&clone->lock)) { 02199 ast_mutex_unlock(&original->lock); 02200 usleep(1); 02201 ast_mutex_lock(&original->lock); 02202 } 02203 ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n", 02204 clone->name, original->name); 02205 if (original->masq) { 02206 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02207 original->masq->name, original->name); 02208 } else if (clone->masqr) { 02209 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02210 clone->name, clone->masqr->name); 02211 } else { 02212 original->masq = clone; 02213 clone->masqr = original; 02214 ast_queue_frame(original, &null); 02215 ast_queue_frame(clone, &null); 02216 ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name); 02217 res = 0; 02218 } 02219 ast_mutex_unlock(&clone->lock); 02220 ast_mutex_unlock(&original->lock); 02221 return res; 02222 }
|
|
Definition at line 2224 of file channel.c. References AST_FRAME_NULL, ast_log(), ast_queue_frame(), LOG_DEBUG, and LOG_WARNING. 02225 { 02226 struct ast_frame null = { AST_FRAME_NULL, }; 02227 int res = -1; 02228 ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n", 02229 clone->name, original->name); 02230 if (original->masq) { 02231 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02232 original->masq->name, original->name); 02233 } else if (clone->masqr) { 02234 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02235 clone->name, clone->masqr->name); 02236 } else { 02237 original->masq = clone; 02238 clone->masqr = original; 02239 ast_queue_frame(original, &null); 02240 ast_queue_frame(clone, &null); 02241 ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name); 02242 res = 0; 02243 } 02244 return res; 02245 }
|
|
Registers a channel.
Definition at line 159 of file channel.c. References ast_channel_register_ex(), description(), and type. 00161 { 00162 return ast_channel_register_ex(type, description, capabilities, requester, NULL); 00163 }
|
|
Definition at line 165 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), backends, chanlist::capabilities, chanlist::description, description(), chanlist::devicestate, LOG_DEBUG, LOG_WARNING, malloc, chanlist::next, option_debug, option_verbose, chanlist::requester, type, chanlist::type, and VERBOSE_PREFIX_2. Referenced by ast_channel_register(). 00168 { 00169 struct chanlist *chan, *last=NULL; 00170 if (ast_mutex_lock(&chlock)) { 00171 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 00172 return -1; 00173 } 00174 chan = backends; 00175 while (chan) { 00176 if (!strcasecmp(type, chan->type)) { 00177 ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type); 00178 ast_mutex_unlock(&chlock); 00179 return -1; 00180 } 00181 last = chan; 00182 chan = chan->next; 00183 } 00184 chan = malloc(sizeof(struct chanlist)); 00185 if (!chan) { 00186 ast_log(LOG_WARNING, "Out of memory\n"); 00187 ast_mutex_unlock(&chlock); 00188 return -1; 00189 } 00190 strncpy(chan->type, type, sizeof(chan->type)-1); 00191 strncpy(chan->description, description, sizeof(chan->description)-1); 00192 chan->capabilities = capabilities; 00193 chan->requester = requester; 00194 chan->devicestate = devicestate; 00195 chan->next = NULL; 00196 if (last) 00197 last->next = chan; 00198 else 00199 backends = chan; 00200 if (option_debug) 00201 ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description); 00202 else if (option_verbose > 1) 00203 ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description); 00204 ast_mutex_unlock(&chlock); 00205 return 0; 00206 }
|
|
Sends HTML on given channel. Send HTML or URL on link. Returns 0 on success or -1 on failure Definition at line 2128 of file channel.c. 02129 { 02130 if (chan->pvt->send_html) 02131 return chan->pvt->send_html(chan, subclass, data, datalen); 02132 return -1; 02133 }
|
|
Sends a URL on a given link. Send URL on link. Returns 0 on success or -1 on failure Definition at line 2135 of file channel.c. References AST_HTML_URL. 02136 { 02137 if (chan->pvt->send_html) 02138 return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1); 02139 return -1; 02140 }
|
|
Sets an option on a channel.
Definition at line 2802 of file channel.c. References ast_log(), LOG_ERROR, ast_channel::pvt, and ast_channel_pvt::setoption. 02803 { 02804 int res; 02805 if (chan->pvt->setoption) { 02806 res = chan->pvt->setoption(chan, option, data, datalen); 02807 if (res < 0) 02808 return res; 02809 } else { 02810 errno = ENOSYS; 02811 return -1; 02812 } 02813 if (block) { 02814 /* XXX Implement blocking -- just wait for our option frame reply, discarding 02815 intermediate packets. XXX */ 02816 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 02817 return -1; 02818 } 02819 return 0; 02820 }
|
|
Set when to hang a channel up.
Definition at line 147 of file channel.c. References ast_channel::whentohangup. 00148 {
00149 time_t myt;
00150
00151 time(&myt);
00152 if (offset)
00153 chan->whentohangup = myt + offset;
00154 else
00155 chan->whentohangup = 0;
00156 return;
00157 }
|
|
Checks for HTML support on a channel. Returns 0 if channel does not support HTML or non-zero if it does Definition at line 2121 of file channel.c.
|
|
Undeos a defer. Undo defer. ast_read will return any dtmf characters that were queued Definition at line 471 of file channel.c. 00472 {
00473 if (chan)
00474 chan->deferdtmf = 0;
00475 }
|
|
Unregister a channel class.
Definition at line 789 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), backends, free, LOG_DEBUG, LOG_WARNING, chanlist::next, option_debug, option_verbose, type, chanlist::type, and VERBOSE_PREFIX_2. 00790 { 00791 struct chanlist *chan, *last=NULL; 00792 if (option_debug) 00793 ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type); 00794 if (ast_mutex_lock(&chlock)) { 00795 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 00796 return; 00797 } 00798 if (option_verbose > 1) 00799 ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type); 00800 00801 chan = backends; 00802 while(chan) { 00803 if (!strcasecmp(chan->type, type)) { 00804 if (last) 00805 last->next = chan->next; 00806 else 00807 backends = backends->next; 00808 free(chan); 00809 ast_mutex_unlock(&chlock); 00810 return; 00811 } 00812 last = chan; 00813 chan = chan->next; 00814 } 00815 ast_mutex_unlock(&chlock); 00816 }
|
|
Browse channels in use.
Definition at line 477 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, channels, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, and ast_channel::next. Referenced by ast_async_goto_by_name(), ast_get_channel_by_name_locked(), ast_get_channel_by_uniqueid_locked(), and ast_parse_device_state(). 00478 { 00479 /* Returns next channel (locked) */ 00480 struct ast_channel *l, *ret; 00481 int retries = 0; 00482 retry: 00483 ret=NULL; 00484 ast_mutex_lock(&chlock); 00485 l = channels; 00486 if (!prev) { 00487 if (l) { 00488 if (ast_mutex_trylock(&l->lock)) { 00489 if (retries < 10) 00490 ast_log(LOG_DEBUG, "Avoiding initial deadlock for '%s'\n", l->name); 00491 else 00492 ast_log(LOG_WARNING, "Avoided initial deadlock for '%s', %d retries!\n", l->name, retries); 00493 ast_mutex_unlock(&chlock); 00494 if (retries < 10) { 00495 usleep(1); 00496 retries++; 00497 goto retry; 00498 } else 00499 return NULL; 00500 } 00501 } 00502 ast_mutex_unlock(&chlock); 00503 return l; 00504 } 00505 while(l) { 00506 if (l == prev) 00507 ret = l->next; 00508 l = l->next; 00509 } 00510 if (ret) { 00511 if (ast_mutex_trylock(&ret->lock)) { 00512 if (retries < 10) 00513 ast_log(LOG_DEBUG, "Avoiding deadlock for '%s'\n", ret->name); 00514 else 00515 ast_log(LOG_WARNING, "Avoided deadlock for '%s', %d retries!\n", ret->name, retries); 00516 ast_mutex_unlock(&chlock); 00517 if (retries < 10) { 00518 usleep(1); 00519 retries++; 00520 goto retry; 00521 } else 00522 return NULL; 00523 } 00524 } 00525 ast_mutex_unlock(&chlock); 00526 return ret; 00527 00528 }
|
|
Check to see if a channel is needing hang up.
Definition at line 82 of file channel.c. References ast_channel::_softhangup, and AST_SOFTHANGUP_TIMEOUT. Referenced by ast_answer(), ast_call(), ast_channel_bridge(), ast_indicate(), ast_read(), ast_readstring(), ast_readstring_full(), ast_recvchar(), ast_rtp_bridge(), ast_sendtext(), ast_transfer(), ast_waitfordigit(), ast_waitfordigit_full(), and ast_write(). 00083 { 00084 time_t myt; 00085 00086 /* if soft hangup flag, return true */ 00087 if (chan->_softhangup) return 1; 00088 /* if no private structure, return true */ 00089 if (!chan->pvt->pvt) return 1; 00090 /* if no hangup scheduled, just return here */ 00091 if (!chan->whentohangup) return 0; 00092 time(&myt); /* get current time */ 00093 /* return, if not yet */ 00094 if (chan->whentohangup > myt) return 0; 00095 chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 00096 return 1; 00097 }
|
|
Deactive an active generator Definition at line 849 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, and ast_settimeout(). Referenced by ast_openstream(), ast_playtones_stop(), ast_read(), ast_tonepair_stop(), and ast_write(). 00850 { 00851 ast_mutex_lock(&chan->lock); 00852 if (chan->generatordata) { 00853 if (chan->generator && chan->generator->release) 00854 chan->generator->release(chan, chan->generatordata); 00855 chan->generatordata = NULL; 00856 chan->generator = NULL; 00857 chan->writeinterrupt = 0; 00858 ast_settimeout(chan, 0, NULL, NULL); 00859 } 00860 ast_mutex_unlock(&chan->lock); 00861 }
|
|
Asks a channel for device state.
Definition at line 1966 of file channel.c. References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_log(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parse_device_state(), backends, chanlist::devicestate, LOG_WARNING, chanlist::next, and chanlist::type. 01967 { 01968 char tech[AST_MAX_EXTENSION] = ""; 01969 char *number; 01970 struct chanlist *chanls; 01971 int res = 0; 01972 01973 strncpy(tech, device, sizeof(tech)-1); 01974 number = strchr(tech, '/'); 01975 if (!number) { 01976 return AST_DEVICE_INVALID; 01977 } 01978 *number = 0; 01979 number++; 01980 01981 if (ast_mutex_lock(&chlock)) { 01982 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 01983 return -1; 01984 } 01985 chanls = backends; 01986 while(chanls) { 01987 if (!strcasecmp(tech, chanls->type)) { 01988 ast_mutex_unlock(&chlock); 01989 if (!chanls->devicestate) 01990 return ast_parse_device_state(device); 01991 else { 01992 res = chanls->devicestate(number); 01993 if (res == AST_DEVICE_UNKNOWN) 01994 return ast_parse_device_state(device); 01995 else 01996 return res; 01997 } 01998 } 01999 chanls = chanls->next; 02000 } 02001 ast_mutex_unlock(&chlock); 02002 return AST_DEVICE_INVALID; 02003 }
|
|
Definition at line 2255 of file channel.c. References ast_channel::_softhangup, ast_channel::_state, ast_channel::adsicpe, ast_channel_free(), AST_FRAME_NULL, ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_queue_frame(), ast_set_read_format(), ast_set_write_format(), AST_SOFTHANGUP_DEV, ast_channel::callerid, ast_channel::dnid, EVENT_FLAG_CALL, ast_channel::exception, ast_channel::fdno, ast_channel::fds, ast_channel_pvt::fixup, ast_channel_pvt::hangup, ast_channel::language, ast_channel::lock, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::masqr, ast_channel::musicclass, ast_channel::name, ast_channel::nativeformats, ast_frame::next, ast_channel_pvt::pvt, ast_channel::pvt, ast_channel_pvt::readq, ast_channel::timingfd, ast_channel::type, ast_channel::uniqueid, and ast_channel::zombie. Referenced by ast_async_goto(), ast_hangup(), ast_read(), ast_waitfor_nandfds(), and ast_write(). 02256 { 02257 int x,i; 02258 int res=0; 02259 int origstate; 02260 char *tmp; 02261 struct ast_var_t *varptr; 02262 struct ast_frame *cur, *prev; 02263 struct ast_channel_pvt *p; 02264 struct ast_channel *clone = original->masq; 02265 int rformat = original->readformat; 02266 int wformat = original->writeformat; 02267 char newn[100]; 02268 char orig[100]; 02269 char masqn[100]; 02270 char zombn[100]; 02271 02272 #if 1 02273 ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n", 02274 clone->name, clone->_state, original->name, original->_state); 02275 #endif 02276 /* XXX This is a seriously wacked out operation. We're essentially putting the guts of 02277 the clone channel into the original channel. Start by killing off the original 02278 channel's backend. I'm not sure we're going to keep this function, because 02279 while the features are nice, the cost is very high in terms of pure nastiness. XXX */ 02280 02281 /* We need the clone's lock, too */ 02282 ast_mutex_lock(&clone->lock); 02283 02284 ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock); 02285 02286 /* Having remembered the original read/write formats, we turn off any translation on either 02287 one */ 02288 free_translation(clone); 02289 free_translation(original); 02290 02291 02292 /* Unlink the masquerade */ 02293 original->masq = NULL; 02294 clone->masqr = NULL; 02295 02296 /* Save the original name */ 02297 strncpy(orig, original->name, sizeof(orig) - 1); 02298 /* Save the new name */ 02299 strncpy(newn, clone->name, sizeof(newn) - 1); 02300 /* Create the masq name */ 02301 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn); 02302 02303 /* Copy the name from the clone channel */ 02304 strncpy(original->name, newn, sizeof(original->name)-1); 02305 02306 /* Mangle the name of the clone channel */ 02307 strncpy(clone->name, masqn, sizeof(clone->name) - 1); 02308 02309 /* Notify any managers of the change, first the masq then the other */ 02310 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid); 02311 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid); 02312 02313 /* Swap the guts */ 02314 p = original->pvt; 02315 original->pvt = clone->pvt; 02316 clone->pvt = p; 02317 02318 /* Save any pending frames on both sides. Start by counting 02319 * how many we're going to need... */ 02320 prev = NULL; 02321 cur = clone->pvt->readq; 02322 x = 0; 02323 while(cur) { 02324 x++; 02325 prev = cur; 02326 cur = cur->next; 02327 } 02328 /* If we had any, prepend them to the ones already in the queue, and 02329 * load up the alertpipe */ 02330 if (prev) { 02331 prev->next = original->pvt->readq; 02332 original->pvt->readq = clone->pvt->readq; 02333 clone->pvt->readq = NULL; 02334 if (original->pvt->alertpipe[1] > -1) { 02335 for (i=0;i<x;i++) 02336 write(original->pvt->alertpipe[1], &x, sizeof(x)); 02337 } 02338 } 02339 clone->_softhangup = AST_SOFTHANGUP_DEV; 02340 02341 02342 /* And of course, so does our current state. Note we need not 02343 call ast_setstate since the event manager doesn't really consider 02344 these separate. We do this early so that the clone has the proper 02345 state of the original channel. */ 02346 origstate = original->_state; 02347 original->_state = clone->_state; 02348 clone->_state = origstate; 02349 02350 if (clone->pvt->fixup){ 02351 res = clone->pvt->fixup(original, clone); 02352 if (res) 02353 ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name); 02354 } 02355 02356 /* Start by disconnecting the original's physical side */ 02357 02358 if (clone->pvt->hangup) 02359 res = clone->pvt->hangup(clone); 02360 if (res) { 02361 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n"); 02362 ast_mutex_unlock(&clone->lock); 02363 return -1; 02364 } 02365 02366 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig); 02367 /* Mangle the name of the clone channel */ 02368 strncpy(clone->name, zombn, sizeof(clone->name) - 1); 02369 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid); 02370 02371 /* Update the type. */ 02372 original->type = clone->type; 02373 02374 /* Keep the same language. */ 02375 strncpy(original->language, clone->language, sizeof(original->language)); 02376 02377 /* Copy the FD's */ 02378 for (x=0;x<AST_MAX_FDS;x++) { 02379 original->fds[x] = clone->fds[x]; 02380 } 02381 /* Append variables from clone channel into original channel */ 02382 /* XXX Is this always correct? We have to in order to keep MACROS working XXX */ 02383 varptr = original->varshead.first; 02384 if (varptr) { 02385 while(varptr->entries.next) { 02386 varptr = varptr->entries.next; 02387 } 02388 varptr->entries.next = clone->varshead.first; 02389 } else { 02390 original->varshead.first = clone->varshead.first; 02391 } 02392 clone->varshead.first = NULL; 02393 /* Presense of ADSI capable CPE follows clone */ 02394 original->adsicpe = clone->adsicpe; 02395 /* Bridge remains the same */ 02396 /* CDR fields remain the same */ 02397 /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */ 02398 /* Application and data remain the same */ 02399 /* Clone exception becomes real one, as with fdno */ 02400 original->exception = clone->exception; 02401 original->fdno = clone->fdno; 02402 /* Schedule context remains the same */ 02403 /* Stream stuff stays the same */ 02404 /* Keep the original state. The fixup code will need to work with it most likely */ 02405 02406 /* dnid and callerid change to become the new, HOWEVER, we also link the original's 02407 fields back into the defunct 'clone' so that they will be freed when 02408 ast_frfree is eventually called */ 02409 tmp = original->dnid; 02410 original->dnid = clone->dnid; 02411 clone->dnid = tmp; 02412 02413 tmp = original->callerid; 02414 original->callerid = clone->callerid; 02415 clone->callerid = tmp; 02416 02417 /* Restore original timing file descriptor */ 02418 original->fds[AST_MAX_FDS - 2] = original->timingfd; 02419 02420 /* Our native formats are different now */ 02421 original->nativeformats = clone->nativeformats; 02422 02423 /* Context, extension, priority, app data, jump table, remain the same */ 02424 /* pvt switches. pbx stays the same, as does next */ 02425 02426 /* Set the write format */ 02427 ast_set_write_format(original, wformat); 02428 02429 /* Set the read format */ 02430 ast_set_read_format(original, rformat); 02431 02432 /* Copy the music class */ 02433 strncpy(original->musicclass, clone->musicclass, sizeof(original->musicclass) - 1); 02434 02435 ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat); 02436 02437 /* Okay. Last thing is to let the channel driver know about all this mess, so he 02438 can fix up everything as best as possible */ 02439 if (original->pvt->fixup) { 02440 res = original->pvt->fixup(clone, original); 02441 if (res) { 02442 ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n", 02443 original->type, original->name); 02444 ast_mutex_unlock(&clone->lock); 02445 return -1; 02446 } 02447 } else 02448 ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)! Bad things may happen.\n", 02449 original->type, original->name); 02450 02451 /* Now, at this point, the "clone" channel is totally F'd up. We mark it as 02452 a zombie so nothing tries to touch it. If it's already been marked as a 02453 zombie, then free it now (since it already is considered invalid). */ 02454 if (clone->zombie) { 02455 ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name); 02456 ast_mutex_unlock(&clone->lock); 02457 ast_channel_free(clone); 02458 manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn); 02459 } else { 02460 struct ast_frame null_frame = { AST_FRAME_NULL, }; 02461 ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name); 02462 clone->zombie=1; 02463 ast_queue_frame(clone, &null_frame); 02464 ast_mutex_unlock(&clone->lock); 02465 } 02466 02467 /* Signal any blocker */ 02468 if (original->blocking) 02469 pthread_kill(original->blocker, SIGURG); 02470 ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n", 02471 original->name, original->_state); 02472 return 0; 02473 }
|
|
Get channel by name (locks channel).
Definition at line 530 of file channel.c. References ast_channel_walk_locked(), ast_mutex_unlock, ast_channel::lock, and ast_channel::name. 00531 { 00532 struct ast_channel *chan; 00533 chan = ast_channel_walk_locked(NULL); 00534 while(chan) { 00535 if (!strcasecmp(chan->name, channame)) 00536 return chan; 00537 ast_mutex_unlock(&chan->lock); 00538 chan = ast_channel_walk_locked(chan); 00539 } 00540 return NULL; 00541 }
|
|
Get channel by uniqueid (locks channel).
Definition at line 543 of file channel.c. References ast_channel_walk_locked(), ast_mutex_unlock, ast_channel::lock, and ast_channel::uniqueid. 00544 { 00545 struct ast_channel *chan; 00546 chan = ast_channel_walk_locked(NULL); 00547 while(chan) { 00548 if (!strcasecmp(chan->uniqueid, uniqueid)) 00549 return chan; 00550 ast_mutex_unlock(&chan->lock); 00551 chan = ast_channel_walk_locked(chan); 00552 } 00553 return NULL; 00554 }
|
|
Definition at line 2954 of file channel.c. References ast_log(), LOG_ERROR, LOG_WARNING, and s. 02955 { 02956 char *copy; 02957 char *piece; 02958 char *c=NULL; 02959 int start=0, finish=0,x; 02960 unsigned int group = 0; 02961 copy = ast_strdupa(s); 02962 if (!copy) { 02963 ast_log(LOG_ERROR, "Out of memory\n"); 02964 return 0; 02965 } 02966 c = copy; 02967 02968 while((piece = strsep(&c, ","))) { 02969 if (sscanf(piece, "%d-%d", &start, &finish) == 2) { 02970 /* Range */ 02971 } else if (sscanf(piece, "%d", &start)) { 02972 /* Just one */ 02973 finish = start; 02974 } else { 02975 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.\n", s, piece); 02976 continue; 02977 } 02978 for (x=start;x<=finish;x++) { 02979 if ((x > 31) || (x < 0)) { 02980 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x); 02981 } else 02982 group |= (1 << x); 02983 } 02984 } 02985 return group; 02986 }
|
|
Hang up a channel.
Definition at line 722 of file channel.c. References ast_cdr_end(), ast_cdr_free(), ast_cdr_post(), ast_channel_free(), ast_closestream(), ast_do_masquerade(), ast_log(), ast_mutex_lock, ast_mutex_unlock, CRASH, EVENT_FLAG_CALL, LOG_DEBUG, LOG_WARNING, manager_event(), option_debug, and sched_context_destroy(). Referenced by __ast_request_and_dial(), ast_async_goto(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_pbx_run(), and ast_pbx_run_app(). 00723 { 00724 int res = 0; 00725 /* Don't actually hang up a channel that will masquerade as someone else, or 00726 if someone is going to masquerade as us */ 00727 ast_mutex_lock(&chan->lock); 00728 if (chan->masq) { 00729 if (ast_do_masquerade(chan)) 00730 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 00731 } 00732 00733 if (chan->masq) { 00734 ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name); 00735 ast_mutex_unlock(&chan->lock); 00736 return 0; 00737 } 00738 /* If this channel is one which will be masqueraded into something, 00739 mark it as a zombie already, so we know to free it later */ 00740 if (chan->masqr) { 00741 chan->zombie=1; 00742 ast_mutex_unlock(&chan->lock); 00743 return 0; 00744 } 00745 free_translation(chan); 00746 if (chan->stream) 00747 ast_closestream(chan->stream); 00748 if (chan->vstream) 00749 ast_closestream(chan->vstream); 00750 if (chan->sched) 00751 sched_context_destroy(chan->sched); 00752 /* Clear any tone stuff remaining */ 00753 if (chan->generatordata) 00754 chan->generator->release(chan, chan->generatordata); 00755 chan->generatordata = NULL; 00756 chan->generator = NULL; 00757 if (chan->cdr) { 00758 /* End the CDR if it hasn't already */ 00759 ast_cdr_end(chan->cdr); 00760 /* Post and Free the CDR */ 00761 ast_cdr_post(chan->cdr); 00762 ast_cdr_free(chan->cdr); 00763 } 00764 if (chan->blocking) { 00765 ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd " 00766 "is blocked by thread %ld in procedure %s! Expect a failure\n", 00767 (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc); 00768 CRASH; 00769 } 00770 if (!chan->zombie) { 00771 if (option_debug) 00772 ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name); 00773 if (chan->pvt->hangup) 00774 res = chan->pvt->hangup(chan); 00775 } else 00776 if (option_debug) 00777 ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name); 00778 00779 ast_mutex_unlock(&chan->lock); 00780 manager_event(EVENT_FLAG_CALL, "Hangup", 00781 "Channel: %s\r\n" 00782 "Uniqueid: %s\r\n" 00783 "Cause: %i\r\n", 00784 chan->name, chan->uniqueid, chan->hangupcause); 00785 ast_channel_free(chan); 00786 return res; 00787 }
|
|
Indicates condition of channel.
Definition at line 1440 of file channel.c. References ast_check_hangup(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_get_indication_tone(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_playtones_start(), ast_playtones_stop(), tone_zone_sound::data, LOG_DEBUG, and LOG_WARNING. 01441 { 01442 int res = -1; 01443 /* Stop if we're a zombie or need a soft hangup */ 01444 if (chan->zombie || ast_check_hangup(chan)) 01445 return -1; 01446 ast_mutex_lock(&chan->lock); 01447 if (chan->pvt->indicate) 01448 res = chan->pvt->indicate(chan, condition); 01449 ast_mutex_unlock(&chan->lock); 01450 if (!chan->pvt->indicate || res) { 01451 /* 01452 * Device does not support (that) indication, lets fake 01453 * it by doing our own tone generation. (PM2002) 01454 */ 01455 if (condition >= 0) { 01456 const struct tone_zone_sound *ts = NULL; 01457 switch (condition) { 01458 case AST_CONTROL_RINGING: 01459 ts = ast_get_indication_tone(chan->zone, "ring"); 01460 break; 01461 case AST_CONTROL_BUSY: 01462 ts = ast_get_indication_tone(chan->zone, "busy"); 01463 break; 01464 case AST_CONTROL_CONGESTION: 01465 ts = ast_get_indication_tone(chan->zone, "congestion"); 01466 break; 01467 } 01468 if (ts && ts->data[0]) { 01469 ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition); 01470 ast_playtones_start(chan,0,ts->data, 1); 01471 res = 0; 01472 } else if (condition == AST_CONTROL_PROGRESS) { 01473 /* ast_playtones_stop(chan); */ 01474 } else if (condition == AST_CONTROL_PROCEEDING) { 01475 /* Do nothing, really */ 01476 } else { 01477 /* not handled */ 01478 ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name); 01479 res = -1; 01480 } 01481 } 01482 else ast_playtones_stop(chan); 01483 } 01484 return res; 01485 }
|
|
|
|
|
|
Search the Channels by Name.
Definition at line 1942 of file channel.c. References ast_channel::_state, AST_CHANNEL_NAME, ast_channel_walk_locked(), AST_DEVICE_INUSE, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, ast_mutex_unlock, AST_STATE_RINGING, ast_channel::lock, and ast_channel::name. Referenced by ast_device_state(). 01943 { 01944 char name[AST_CHANNEL_NAME] = ""; 01945 char *cut; 01946 struct ast_channel *chan; 01947 01948 chan = ast_channel_walk_locked(NULL); 01949 while (chan) { 01950 strncpy(name, chan->name, sizeof(name)-1); 01951 ast_mutex_unlock(&chan->lock); 01952 cut = strchr(name,'-'); 01953 if (cut) 01954 *cut = 0; 01955 if (!strcmp(name, device)) { 01956 if (chan->_state == AST_STATE_RINGING) 01957 return AST_DEVICE_RINGING; 01958 else 01959 return AST_DEVICE_INUSE; 01960 } 01961 chan = ast_channel_walk_locked(chan); 01962 } 01963 return AST_DEVICE_UNKNOWN; 01964 }
|
|
Definition at line 1578 of file channel.c. References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), AST_STATE_UP, ast_write(), ast_frame::data, LOG_DEBUG, LOG_WARNING, and ast_frame::subclass. Referenced by ast_activate_generator(). 01579 { 01580 struct ast_frame a = { AST_FRAME_VOICE }; 01581 char nothing[128]; 01582 /* Send an empty audio frame to get things moving */ 01583 if (chan->_state != AST_STATE_UP) { 01584 ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name); 01585 a.subclass = chan->pvt->rawwriteformat; 01586 a.data = nothing + AST_FRIENDLY_OFFSET; 01587 if (ast_write(chan, &a)) 01588 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name); 01589 } 01590 return 0; 01591 }
|
|
Definition at line 454 of file channel.c. References AST_FRAME_CONTROL, ast_queue_frame(), and ast_frame::subclass. 00455 { 00456 struct ast_frame f = { AST_FRAME_CONTROL, }; 00457 f.subclass = control; 00458 return ast_queue_frame(chan, &f); 00459 }
|
|
Queue an outgoing frame Definition at line 390 of file channel.c. References AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_VOICE, ast_frdup(), ast_frfree(), ast_log(), ast_mutex_lock, ast_mutex_unlock, CRASH, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_frame::next, and ast_frame::subclass. Referenced by ast_channel_masquerade(), ast_channel_masquerade_locked(), ast_do_masquerade(), ast_dsp_process(), ast_queue_control(), ast_queue_hangup(), and ast_softhangup_nolock(). 00391 { 00392 struct ast_frame *f; 00393 struct ast_frame *prev, *cur; 00394 int blah = 1; 00395 int qlen = 0; 00396 /* Build us a copy and free the original one */ 00397 f = ast_frdup(fin); 00398 if (!f) { 00399 ast_log(LOG_WARNING, "Unable to duplicate frame\n"); 00400 return -1; 00401 } 00402 ast_mutex_lock(&chan->lock); 00403 prev = NULL; 00404 cur = chan->pvt->readq; 00405 while(cur) { 00406 if ((cur->frametype == AST_FRAME_CONTROL) && (cur->subclass == AST_CONTROL_HANGUP)) { 00407 /* Don't bother actually queueing anything after a hangup */ 00408 ast_frfree(f); 00409 ast_mutex_unlock(&chan->lock); 00410 return 0; 00411 } 00412 prev = cur; 00413 cur = cur->next; 00414 qlen++; 00415 } 00416 /* Allow up to 96 voice frames outstanding, and up to 128 total frames */ 00417 if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen > 128)) { 00418 if (fin->frametype != AST_FRAME_VOICE) { 00419 ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name); 00420 CRASH; 00421 } else { 00422 ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name); 00423 ast_frfree(f); 00424 ast_mutex_unlock(&chan->lock); 00425 return 0; 00426 } 00427 } 00428 if (prev) 00429 prev->next = f; 00430 else 00431 chan->pvt->readq = f; 00432 if (chan->pvt->alertpipe[1] > -1) { 00433 if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) 00434 ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n", 00435 chan->name, f->frametype, f->subclass, qlen, strerror(errno)); 00436 #ifdef ZAPTEL_OPTIMIZATIONS 00437 } else if (chan->timingfd > -1) { 00438 ioctl(chan->timingfd, ZT_TIMERPING, &blah); 00439 #endif 00440 } else if (chan->blocking) { 00441 pthread_kill(chan->blocker, SIGURG); 00442 } 00443 ast_mutex_unlock(&chan->lock); 00444 return 0; 00445 }
|
|
Definition at line 447 of file channel.c. References AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_queue_frame(), and AST_SOFTHANGUP_DEV. 00448 { 00449 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP }; 00450 chan->_softhangup |= AST_SOFTHANGUP_DEV; 00451 return ast_queue_frame(chan, &f); 00452 }
|
|
Reads a frame.
Definition at line 1222 of file channel.c. References ast_cdr_answer(), ast_cdr_end(), ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, ast_deactivate_generator(), ast_do_masquerade(), AST_FRAME_CNG, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dump(), AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_seekstream(), ast_setstate(), ast_settimeout(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_translate(), ast_writestream(), ast_frame::datalen, ast_channel::fin, ast_frame::frametype, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::next, ast_frame::samples, SEEK_FORCECUR, ast_frame::subclass, and ast_channel::timingfunc. Referenced by __ast_request_and_dial(), ast_app_getvoice(), ast_channel_bridge(), ast_play_and_prepend(), ast_play_and_record(), ast_recvchar(), ast_rtp_bridge(), ast_safe_sleep(), ast_safe_sleep_conditional(), ast_tonepair(), ast_waitfordigit(), ast_waitfordigit_full(), ast_waitstream(), ast_waitstream_fr(), and ast_waitstream_full(). 01223 { 01224 struct ast_frame *f = NULL; 01225 int blah; 01226 #ifdef ZAPTEL_OPTIMIZATIONS 01227 int (*func)(void *); 01228 void *data; 01229 int res; 01230 #endif 01231 static struct ast_frame null_frame = 01232 { 01233 AST_FRAME_NULL, 01234 }; 01235 01236 ast_mutex_lock(&chan->lock); 01237 if (chan->masq) { 01238 if (ast_do_masquerade(chan)) { 01239 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 01240 f = NULL; 01241 } else 01242 f = &null_frame; 01243 ast_mutex_unlock(&chan->lock); 01244 return f; 01245 } 01246 01247 /* Stop if we're a zombie or need a soft hangup */ 01248 if (chan->zombie || ast_check_hangup(chan)) { 01249 if (chan->generator) 01250 ast_deactivate_generator(chan); 01251 ast_mutex_unlock(&chan->lock); 01252 return NULL; 01253 } 01254 01255 if (!chan->deferdtmf && !ast_strlen_zero(chan->dtmfq)) { 01256 /* We have DTMF that has been deferred. Return it now */ 01257 chan->dtmff.frametype = AST_FRAME_DTMF; 01258 chan->dtmff.subclass = chan->dtmfq[0]; 01259 /* Drop first digit */ 01260 memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1); 01261 ast_mutex_unlock(&chan->lock); 01262 return &chan->dtmff; 01263 } 01264 01265 /* Read and ignore anything on the alertpipe, but read only 01266 one sizeof(blah) per frame that we send from it */ 01267 if (chan->pvt->alertpipe[0] > -1) { 01268 read(chan->pvt->alertpipe[0], &blah, sizeof(blah)); 01269 } 01270 #ifdef ZAPTEL_OPTIMIZATIONS 01271 if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) { 01272 chan->exception = 0; 01273 blah = -1; 01274 /* IF we can't get event, assume it's an expired as-per the old interface */ 01275 res = ioctl(chan->timingfd, ZT_GETEVENT, &blah); 01276 if (res) 01277 blah = ZT_EVENT_TIMER_EXPIRED; 01278 01279 if (blah == ZT_EVENT_TIMER_PING) { 01280 #if 0 01281 ast_log(LOG_NOTICE, "Oooh, there's a PING!\n"); 01282 #endif 01283 if (!chan->pvt->readq || !chan->pvt->readq->next) { 01284 /* Acknowledge PONG unless we need it again */ 01285 #if 0 01286 ast_log(LOG_NOTICE, "Sending a PONG!\n"); 01287 #endif 01288 if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) { 01289 ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno)); 01290 } 01291 } 01292 } else if (blah == ZT_EVENT_TIMER_EXPIRED) { 01293 ioctl(chan->timingfd, ZT_TIMERACK, &blah); 01294 func = chan->timingfunc; 01295 data = chan->timingdata; 01296 ast_mutex_unlock(&chan->lock); 01297 if (func) { 01298 #if 0 01299 ast_log(LOG_DEBUG, "Calling private function\n"); 01300 #endif 01301 func(data); 01302 } else { 01303 blah = 0; 01304 ast_mutex_lock(&chan->lock); 01305 ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah); 01306 chan->timingdata = NULL; 01307 ast_mutex_unlock(&chan->lock); 01308 } 01309 f = &null_frame; 01310 return f; 01311 } else 01312 ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name); 01313 } 01314 #endif 01315 /* Check for pending read queue */ 01316 if (chan->pvt->readq) { 01317 f = chan->pvt->readq; 01318 chan->pvt->readq = f->next; 01319 /* Interpret hangup and return NULL */ 01320 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) { 01321 ast_frfree(f); 01322 f = NULL; 01323 } 01324 } else { 01325 chan->blocker = pthread_self(); 01326 if (chan->exception) { 01327 if (chan->pvt->exception) 01328 f = chan->pvt->exception(chan); 01329 else { 01330 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name); 01331 f = &null_frame; 01332 } 01333 /* Clear the exception flag */ 01334 chan->exception = 0; 01335 } else 01336 if (chan->pvt->read) 01337 f = chan->pvt->read(chan); 01338 else 01339 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name); 01340 } 01341 01342 01343 if (f && (f->frametype == AST_FRAME_VOICE)) { 01344 if (!(f->subclass & chan->nativeformats)) { 01345 /* This frame can't be from the current native formats -- drop it on the 01346 floor */ 01347 ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", chan->name, ast_getformatname(f->subclass), ast_getformatname(chan->nativeformats)); 01348 ast_frfree(f); 01349 f = &null_frame; 01350 } else { 01351 if (chan->monitor && chan->monitor->read_stream ) { 01352 #ifndef MONITOR_CONSTANT_DELAY 01353 int jump = chan->outsmpl - chan->insmpl - 2 * f->samples; 01354 if (jump >= 0) { 01355 if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1) 01356 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 01357 chan->insmpl += jump + 2 * f->samples; 01358 } else 01359 chan->insmpl+= f->samples; 01360 #else 01361 int jump = chan->outsmpl - chan->insmpl; 01362 if (jump - MONITOR_DELAY >= 0) { 01363 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) 01364 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 01365 chan->insmpl += jump; 01366 } else 01367 chan->insmpl += f->samples; 01368 #endif 01369 if (ast_writestream(chan->monitor->read_stream, f) < 0) 01370 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n"); 01371 } 01372 if (chan->pvt->readtrans) { 01373 f = ast_translate(chan->pvt->readtrans, f, 1); 01374 if (!f) 01375 f = &null_frame; 01376 } 01377 } 01378 } 01379 01380 /* Make sure we always return NULL in the future */ 01381 if (!f) { 01382 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01383 if (chan->generator) 01384 ast_deactivate_generator(chan); 01385 /* End the CDR if appropriate */ 01386 if (chan->cdr) 01387 ast_cdr_end(chan->cdr); 01388 } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) { 01389 if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) 01390 chan->dtmfq[strlen(chan->dtmfq)] = f->subclass; 01391 else 01392 ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name); 01393 f = &null_frame; 01394 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) { 01395 if (chan->_state == AST_STATE_UP) { 01396 ast_log(LOG_DEBUG, "Dropping duplicate answer!\n"); 01397 f = &null_frame; 01398 } 01399 /* Answer the CDR */ 01400 ast_setstate(chan, AST_STATE_UP); 01401 ast_cdr_answer(chan->cdr); 01402 } 01403 01404 /* Run any generator sitting on the line */ 01405 if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) { 01406 /* Mask generator data temporarily and apply. If there is a timing function, it 01407 will be calling the generator instead */ 01408 void *tmp; 01409 int res; 01410 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples); 01411 if (chan->timingfunc) { 01412 ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n"); 01413 ast_settimeout(chan, 0, NULL, NULL); 01414 } 01415 tmp = chan->generatordata; 01416 chan->generatordata = NULL; 01417 generate = chan->generator->generate; 01418 res = generate(chan, tmp, f->datalen, f->samples); 01419 chan->generatordata = tmp; 01420 if (res) { 01421 ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); 01422 ast_deactivate_generator(chan); 01423 } 01424 } else if (f && (f->frametype == AST_FRAME_CNG)) { 01425 if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) { 01426 ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n"); 01427 ast_settimeout(chan, 160, generator_force, chan); 01428 } 01429 } 01430 if (chan->fin & 0x80000000) 01431 ast_frame_dump(chan->name, f, "<<"); 01432 if ((chan->fin & 0x7fffffff) == 0x7fffffff) 01433 chan->fin &= 0x80000000; 01434 else 01435 chan->fin++; 01436 ast_mutex_unlock(&chan->lock); 01437 return f; 01438 }
|
|
Reads multiple digits.
Definition at line 2040 of file channel.c. References ast_check_hangup(), AST_DIGIT_ANY, ast_stopstream(), ast_waitfordigit(), ast_waitstream(), and s. Referenced by ast_app_getdata(). 02041 { 02042 int pos=0; 02043 int to = ftimeout; 02044 char d; 02045 /* XXX Merge with full version? XXX */ 02046 /* Stop if we're a zombie or need a soft hangup */ 02047 if (c->zombie || ast_check_hangup(c)) 02048 return -1; 02049 if (!len) 02050 return -1; 02051 do { 02052 if (c->stream) { 02053 d = ast_waitstream(c, AST_DIGIT_ANY); 02054 ast_stopstream(c); 02055 usleep(1000); 02056 if (!d) 02057 d = ast_waitfordigit(c, to); 02058 } else { 02059 d = ast_waitfordigit(c, to); 02060 } 02061 if (d < 0) 02062 return -1; 02063 if (d == 0) { 02064 s[pos]='\0'; 02065 return 1; 02066 } 02067 if (!strchr(enders, d)) 02068 s[pos++] = d; 02069 if (strchr(enders, d) || (pos >= len)) { 02070 s[pos]='\0'; 02071 return 0; 02072 } 02073 to = timeout; 02074 } while(1); 02075 /* Never reached */ 02076 return 0; 02077 }
|
|
Definition at line 2079 of file channel.c. References ast_check_hangup(), AST_DIGIT_ANY, ast_stopstream(), ast_waitfordigit_full(), ast_waitstream_full(), and s. Referenced by ast_app_getdata_full(). 02080 { 02081 int pos=0; 02082 int to = ftimeout; 02083 char d; 02084 /* Stop if we're a zombie or need a soft hangup */ 02085 if (c->zombie || ast_check_hangup(c)) 02086 return -1; 02087 if (!len) 02088 return -1; 02089 do { 02090 if (c->stream) { 02091 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd); 02092 ast_stopstream(c); 02093 usleep(1000); 02094 if (!d) 02095 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 02096 } else { 02097 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 02098 } 02099 if (d < 0) 02100 return -1; 02101 if (d == 0) { 02102 s[pos]='\0'; 02103 return 1; 02104 } 02105 if (d == 1) { 02106 s[pos]='\0'; 02107 return 2; 02108 } 02109 if (!strchr(enders, d)) 02110 s[pos++] = d; 02111 if (strchr(enders, d) || (pos >= len)) { 02112 s[pos]='\0'; 02113 return 0; 02114 } 02115 to = timeout; 02116 } while(1); 02117 /* Never reached */ 02118 return 0; 02119 }
|
|
Definition at line 1487 of file channel.c. References ast_check_hangup(), AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_frfree(), ast_read(), ast_waitfor(), ast_frame::data, ast_frame::frametype, and ast_frame::subclass. 01488 { 01489 int res,ourto,c; 01490 struct ast_frame *f; 01491 01492 ourto = timeout; 01493 for(;;) 01494 { 01495 if (ast_check_hangup(chan)) return -1; 01496 res = ast_waitfor(chan,ourto); 01497 if (res <= 0) /* if timeout */ 01498 { 01499 return 0; 01500 } 01501 ourto = res; 01502 f = ast_read(chan); 01503 if (f == NULL) return -1; /* if hangup */ 01504 if ((f->frametype == AST_FRAME_CONTROL) && 01505 (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */ 01506 if (f->frametype == AST_FRAME_TEXT) /* if a text frame */ 01507 { 01508 c = *((char *)f->data); /* get the data */ 01509 ast_frfree(f); 01510 return(c); 01511 } 01512 ast_frfree(f); 01513 } 01514 }
|
|
Requests a channel.
Definition at line 1896 of file channel.c. References ast_channel::_state, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_state2str(), AST_STATE_DOWN, ast_translator_best_choice(), backends, ast_channel::callerid, chanlist::capabilities, EVENT_FLAG_CALL, LOG_WARNING, manager_event(), ast_channel::name, chanlist::next, chanlist::requester, type, chanlist::type, and ast_channel::uniqueid. Referenced by __ast_request_and_dial(). 01897 { 01898 struct chanlist *chan; 01899 struct ast_channel *c = NULL; 01900 int capabilities; 01901 int fmt; 01902 int res; 01903 if (ast_mutex_lock(&chlock)) { 01904 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 01905 return NULL; 01906 } 01907 chan = backends; 01908 while(chan) { 01909 if (!strcasecmp(type, chan->type)) { 01910 capabilities = chan->capabilities; 01911 fmt = format; 01912 res = ast_translator_best_choice(&fmt, &capabilities); 01913 if (res < 0) { 01914 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format); 01915 ast_mutex_unlock(&chlock); 01916 return NULL; 01917 } 01918 ast_mutex_unlock(&chlock); 01919 if (chan->requester) 01920 c = chan->requester(type, capabilities, data); 01921 if (c) { 01922 if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid)); 01923 if (c->_state == AST_STATE_DOWN) { 01924 manager_event(EVENT_FLAG_CALL, "Newchannel", 01925 "Channel: %s\r\n" 01926 "State: %s\r\n" 01927 "CallerID: %s\r\n" 01928 "Uniqueid: %s\r\n", 01929 c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid); 01930 } 01931 } 01932 return c; 01933 } 01934 chan = chan->next; 01935 } 01936 if (!chan) 01937 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type); 01938 ast_mutex_unlock(&chlock); 01939 return c; 01940 }
|
|
Definition at line 1891 of file channel.c. References __ast_request_and_dial(), and type. Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten(). 01892 { 01893 return __ast_request_and_dial(type, format, data, timeout, outstate, 0, callerid, NULL, uniqueid); 01894 }
|
|
Wait for a specied amount of time, looking for hangups.
Definition at line 577 of file channel.c. References ast_frfree(), ast_read(), and ast_waitfor(). Referenced by ast_dtmf_stream(). 00578 { 00579 struct ast_frame *f; 00580 while(ms > 0) { 00581 ms = ast_waitfor(chan, ms); 00582 if (ms <0) 00583 return -1; 00584 if (ms > 0) { 00585 f = ast_read(chan); 00586 if (!f) 00587 return -1; 00588 ast_frfree(f); 00589 } 00590 } 00591 return 0; 00592 }
|
|
Wait for a specied amount of time, looking for hangups and a condition argument.
Definition at line 556 of file channel.c. References ast_frfree(), ast_read(), and ast_waitfor(). 00558 { 00559 struct ast_frame *f; 00560 00561 while(ms > 0) { 00562 if( cond && ((*cond)(data) == 0 ) ) 00563 return 0; 00564 ms = ast_waitfor(chan, ms); 00565 if (ms <0) 00566 return -1; 00567 if (ms > 0) { 00568 f = ast_read(chan); 00569 if (!f) 00570 return -1; 00571 ast_frfree(f); 00572 } 00573 } 00574 return 0; 00575 }
|
|
Receives a text character from a channel.
Definition at line 1573 of file channel.c. 01574 {
01575 return do_senddigit(chan, digit);
01576 }
|
|
Sends text to a channel.
Definition at line 1516 of file channel.c. References ast_check_hangup(), and CHECK_BLOCKING. 01517 { 01518 int res = 0; 01519 /* Stop if we're a zombie or need a soft hangup */ 01520 if (chan->zombie || ast_check_hangup(chan)) 01521 return -1; 01522 CHECK_BLOCKING(chan); 01523 if (chan->pvt->send_text) 01524 res = chan->pvt->send_text(chan, text); 01525 chan->blocking = 0; 01526 return res; 01527 }
|
|
Definition at line 2475 of file channel.c. References ast_channel::ani, ast_cdr_setcid(), ast_channel::callerid, EVENT_FLAG_CALL, free, manager_event(), and strdup. Referenced by __ast_request_and_dial(). 02476 { 02477 if (chan->callerid) 02478 free(chan->callerid); 02479 if (anitoo && chan->ani) 02480 free(chan->ani); 02481 if (callerid) { 02482 chan->callerid = strdup(callerid); 02483 if (anitoo) 02484 chan->ani = strdup(callerid); 02485 } else { 02486 chan->callerid = NULL; 02487 if (anitoo) 02488 chan->ani = NULL; 02489 } 02490 if (chan->cdr) 02491 ast_cdr_setcid(chan->cdr, chan); 02492 manager_event(EVENT_FLAG_CALL, "Newcallerid", 02493 "Channel: %s\r\n" 02494 "CallerID: %s\r\n" 02495 "Uniqueid: %s\r\n", 02496 chan->name, chan->callerid ? 02497 chan->callerid : "<Unknown>", 02498 chan->uniqueid); 02499 }
|
|
Sets read format on channel chan.
Definition at line 1745 of file channel.c. References ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), LOG_DEBUG, LOG_NOTICE, and option_debug. Referenced by ast_app_getvoice(), ast_channel_make_compatible(), ast_do_masquerade(), ast_play_and_prepend(), and ast_play_and_record(). 01746 { 01747 int fmt; 01748 int native; 01749 int res; 01750 01751 ast_mutex_lock(&chan->lock); 01752 native = chan->nativeformats; 01753 fmt = fmts; 01754 /* Find a translation path from the native read format to one of the user's read formats */ 01755 res = ast_translator_best_choice(&fmt, &native); 01756 if (res < 0) { 01757 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n", 01758 ast_getformatname(chan->nativeformats), ast_getformatname(fmts)); 01759 ast_mutex_unlock(&chan->lock); 01760 return -1; 01761 } 01762 01763 /* Now we have a good choice for both. We'll write using our native format. */ 01764 chan->pvt->rawreadformat = native; 01765 /* User perspective is fmt */ 01766 chan->readformat = fmt; 01767 /* Free any read translation we have right now */ 01768 if (chan->pvt->readtrans) 01769 ast_translator_free_path(chan->pvt->readtrans); 01770 /* Build a translation path from the raw read format to the user reading format */ 01771 chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat); 01772 if (option_debug) 01773 ast_log(LOG_DEBUG, "Set channel %s to read format %s\n", 01774 chan->name, ast_getformatname(chan->readformat)); 01775 ast_mutex_unlock(&chan->lock); 01776 return 0; 01777 }
|
|
Sets write format on channel chan.
Definition at line 1712 of file channel.c. References ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), LOG_DEBUG, LOG_NOTICE, and option_debug. Referenced by ast_channel_make_compatible(), ast_do_masquerade(), ast_openstream(), and ast_stopstream(). 01713 { 01714 int fmt; 01715 int native; 01716 int res; 01717 01718 ast_mutex_lock(&chan->lock); 01719 native = chan->nativeformats; 01720 fmt = fmts; 01721 01722 res = ast_translator_best_choice(&native, &fmt); 01723 if (res < 0) { 01724 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n", 01725 ast_getformatname(fmts), ast_getformatname(chan->nativeformats)); 01726 ast_mutex_unlock(&chan->lock); 01727 return -1; 01728 } 01729 01730 /* Now we have a good choice for both. We'll write using our native format. */ 01731 chan->pvt->rawwriteformat = native; 01732 /* User perspective is fmt */ 01733 chan->writeformat = fmt; 01734 /* Free any write translation we have right now */ 01735 if (chan->pvt->writetrans) 01736 ast_translator_free_path(chan->pvt->writetrans); 01737 /* Build a translation path from the user write format to the raw writing format */ 01738 chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat); 01739 if (option_debug) 01740 ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat)); 01741 ast_mutex_unlock(&chan->lock); 01742 return 0; 01743 }
|
|
Change the state of a channel Definition at line 2501 of file channel.c. References ast_channel::_state, ast_device_state_changed(), ast_state2str(), AST_STATE_DOWN, EVENT_FLAG_CALL, and manager_event(). Referenced by ast_answer(), ast_async_goto(), and ast_read(). 02502 { 02503 if (chan->_state != state) { 02504 int oldstate = chan->_state; 02505 chan->_state = state; 02506 if (oldstate == AST_STATE_DOWN) { 02507 ast_device_state_changed(chan->name); 02508 manager_event(EVENT_FLAG_CALL, "Newchannel", 02509 "Channel: %s\r\n" 02510 "State: %s\r\n" 02511 "CallerID: %s\r\n" 02512 "Uniqueid: %s\r\n", 02513 chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid); 02514 } else { 02515 ast_device_state_changed(chan->name); 02516 manager_event(EVENT_FLAG_CALL, "Newstate", 02517 "Channel: %s\r\n" 02518 "State: %s\r\n" 02519 "CallerID: %s\r\n" 02520 "Uniqueid: %s\r\n", 02521 chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid); 02522 } 02523 } 02524 return 0; 02525 }
|
|
Definition at line 1152 of file channel.c. References ast_log(), and LOG_DEBUG. Referenced by ast_activate_generator(), ast_closestream(), ast_deactivate_generator(), and ast_read(). 01153 { 01154 int res = -1; 01155 #ifdef ZAPTEL_OPTIMIZATIONS 01156 if (c->timingfd > -1) { 01157 if (!func) { 01158 samples = 0; 01159 data = 0; 01160 } 01161 ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples); 01162 res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples); 01163 c->timingfunc = func; 01164 c->timingdata = data; 01165 } 01166 #endif 01167 return res; 01168 }
|
|
Returns non-zero if Asterisk is being shut down Definition at line 142 of file channel.c. 00143 {
00144 return shutting_down;
00145 }
|
|
Softly hangup up a channel.
Definition at line 701 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, and ast_softhangup_nolock(). Referenced by ast_begin_shutdown(). 00702 { 00703 int res; 00704 ast_mutex_lock(&chan->lock); 00705 res = ast_softhangup_nolock(chan, cause); 00706 ast_mutex_unlock(&chan->lock); 00707 return res; 00708 }
|
|
Definition at line 686 of file channel.c. References AST_FRAME_NULL, ast_log(), ast_queue_frame(), LOG_DEBUG, and option_debug. Referenced by ast_async_goto(), and ast_softhangup(). 00687 { 00688 int res = 0; 00689 struct ast_frame f = { AST_FRAME_NULL }; 00690 if (option_debug) 00691 ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name); 00692 /* Inform channel driver that we need to be hung up, if it cares */ 00693 chan->_softhangup |= cause; 00694 ast_queue_frame(chan, &f); 00695 /* Interrupt any poll call or such */ 00696 if (chan->blocking) 00697 pthread_kill(chan->blocker, SIGURG); 00698 return res; 00699 }
|
|
Gives the string form of a given state.
Definition at line 208 of file channel.c. References AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_OFFHOOK, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, and AST_STATE_UP. Referenced by ast_request(), and ast_setstate(). 00209 { 00210 /* XXX Not reentrant XXX */ 00211 static char localtmp[256]; 00212 switch(state) { 00213 case AST_STATE_DOWN: 00214 return "Down"; 00215 case AST_STATE_RESERVED: 00216 return "Rsrvd"; 00217 case AST_STATE_OFFHOOK: 00218 return "OffHook"; 00219 case AST_STATE_DIALING: 00220 return "Dialing"; 00221 case AST_STATE_RING: 00222 return "Ring"; 00223 case AST_STATE_RINGING: 00224 return "Ringing"; 00225 case AST_STATE_UP: 00226 return "Up"; 00227 case AST_STATE_BUSY: 00228 return "Busy"; 00229 default: 00230 snprintf(localtmp, sizeof(localtmp), "Unknown (%d)\n", state); 00231 return localtmp; 00232 } 00233 }
|
|
Play a tone pair for a given amount of time Definition at line 2936 of file channel.c. References ast_frfree(), ast_read(), ast_tonepair_start(), and ast_waitfor(). 02937 { 02938 struct ast_frame *f; 02939 int res; 02940 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol))) 02941 return res; 02942 02943 /* Give us some wiggle room */ 02944 while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) { 02945 f = ast_read(chan); 02946 if (f) 02947 ast_frfree(f); 02948 else 02949 return -1; 02950 } 02951 return 0; 02952 }
|
|
Start a tone going Definition at line 2916 of file channel.c. References ast_activate_generator(), tonepair_def::duration, tonepair_def::freq1, tonepair_def::freq2, and tonepair_def::vol. Referenced by ast_tonepair(). 02917 { 02918 struct tonepair_def d = { 0, }; 02919 d.freq1 = freq1; 02920 d.freq2 = freq2; 02921 d.duration = duration; 02922 if (vol < 1) 02923 d.vol = 8192; 02924 else 02925 d.vol = vol; 02926 if (ast_activate_generator(chan, &tonepair, &d)) 02927 return -1; 02928 return 0; 02929 }
|
|
Stop a tone from playing Definition at line 2931 of file channel.c. References ast_deactivate_generator(). 02932 { 02933 ast_deactivate_generator(chan); 02934 }
|
|
Definition at line 2020 of file channel.c. References ast_check_hangup(), ast_mutex_lock, and ast_mutex_unlock. 02021 { 02022 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 02023 If the remote end does not answer within the timeout, then do NOT hang up, but 02024 return anyway. */ 02025 int res = -1; 02026 /* Stop if we're a zombie or need a soft hangup */ 02027 ast_mutex_lock(&chan->lock); 02028 if (!chan->zombie && !ast_check_hangup(chan)) { 02029 if (chan->pvt->transfer) { 02030 res = chan->pvt->transfer(chan, dest); 02031 if (!res) 02032 res = 1; 02033 } else 02034 res = 0; 02035 } 02036 ast_mutex_unlock(&chan->lock); 02037 return res; 02038 }
|
|
Wait for input on a channel.
Definition at line 1111 of file channel.c. References ast_waitfor_n(). Referenced by __ast_request_and_dial(), ast_app_getvoice(), ast_dtmf_stream(), ast_play_and_prepend(), ast_play_and_record(), ast_recvchar(), ast_safe_sleep(), ast_safe_sleep_conditional(), ast_tonepair(), ast_waitfordigit(), ast_waitstream(), and ast_waitstream_fr(). 01112 { 01113 struct ast_channel *chan; 01114 int oldms = ms; 01115 chan = ast_waitfor_n(&c, 1, &ms); 01116 if (ms < 0) { 01117 if (oldms < 0) 01118 return 0; 01119 else 01120 return -1; 01121 } 01122 return ms; 01123 }
|
|
Waits for input on a group of channels. Wait for input on an array of channels for a given # of milliseconds. Return channel with activity, or NULL if none has activity. time "ms" is modified in-place, if applicable Definition at line 1106 of file channel.c. References ast_waitfor_nandfds(). Referenced by ast_channel_bridge(), ast_rtp_bridge(), and ast_waitfor(). 01107 { 01108 return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms); 01109 }
|
|
Waits for input on an fd. This version works on fd's only. Be careful with it. Definition at line 902 of file channel.c. References ast_log(), pollfd::events, pollfd::fd, LOG_WARNING, poll(), POLLIN, and POLLPRI. 00903 { 00904 /* Wait for x amount of time on a file descriptor to have input. */ 00905 struct timeval start, now; 00906 int res; 00907 int x, y; 00908 int winner = -1; 00909 int spoint; 00910 struct pollfd *pfds; 00911 00912 pfds = alloca(sizeof(struct pollfd) * n); 00913 if (!pfds) { 00914 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n"); 00915 return -1; 00916 } 00917 if (*ms > 0) 00918 gettimeofday(&start, NULL); 00919 y = 0; 00920 for (x=0;x<n;x++) { 00921 if (fds[x] > -1) { 00922 pfds[y].fd = fds[x]; 00923 pfds[y].events = POLLIN | POLLPRI; 00924 y++; 00925 } 00926 } 00927 res = poll(pfds, y, *ms); 00928 if (res < 0) { 00929 /* Simulate a timeout if we were interrupted */ 00930 if (errno != EINTR) 00931 *ms = -1; 00932 else 00933 *ms = 0; 00934 return -1; 00935 } 00936 spoint = 0; 00937 for (x=0;x<n;x++) { 00938 if (fds[x] > -1) { 00939 if ((res = ast_fdisset(pfds, fds[x], y, &spoint))) { 00940 winner = fds[x]; 00941 if (exception) { 00942 if (res & POLLPRI) 00943 *exception = -1; 00944 else 00945 *exception = 0; 00946 } 00947 } 00948 } 00949 } 00950 if (*ms > 0) { 00951 long passed; 00952 gettimeofday(&now, NULL); 00953 passed = (now.tv_sec - start.tv_sec) * 1000; 00954 passed += (now.tv_usec - start.tv_usec) / 1000; 00955 if (passed <= *ms) 00956 *ms -= passed; 00957 else 00958 *ms = 0; 00959 } 00960 return winner; 00961 }
|
|
Waits for activity on a group of channels.
Definition at line 963 of file channel.c. References ast_do_masquerade(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_TIMEOUT, CHECK_BLOCKING, pollfd::events, ast_channel::exception, pollfd::fd, ast_channel::fdno, LOG_WARNING, poll(), POLLIN, and POLLPRI. Referenced by ast_waitfor_n(), ast_waitfordigit_full(), and ast_waitstream_full(). 00965 { 00966 /* Wait for x amount of time on a file descriptor to have input. */ 00967 struct timeval start, end; 00968 struct pollfd *pfds; 00969 int res; 00970 long rms; 00971 int x, y, max; 00972 int spoint; 00973 time_t now = 0; 00974 long whentohangup = 0, havewhen = 0, diff; 00975 struct ast_channel *winner = NULL; 00976 00977 pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds)); 00978 if (!pfds) { 00979 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n"); 00980 *outfd = -1; 00981 return NULL; 00982 } 00983 00984 if (outfd) 00985 *outfd = -99999; 00986 if (exception) 00987 *exception = 0; 00988 00989 /* Perform any pending masquerades */ 00990 for (x=0;x<n;x++) { 00991 ast_mutex_lock(&c[x]->lock); 00992 if (c[x]->whentohangup) { 00993 if (!havewhen) 00994 time(&now); 00995 diff = c[x]->whentohangup - now; 00996 if (!havewhen || (diff < whentohangup)) { 00997 havewhen++; 00998 whentohangup = diff; 00999 } 01000 } 01001 if (c[x]->masq) { 01002 if (ast_do_masquerade(c[x])) { 01003 ast_log(LOG_WARNING, "Masquerade failed\n"); 01004 *ms = -1; 01005 ast_mutex_unlock(&c[x]->lock); 01006 return NULL; 01007 } 01008 } 01009 ast_mutex_unlock(&c[x]->lock); 01010 } 01011 01012 rms = *ms; 01013 01014 if (havewhen) { 01015 if ((*ms < 0) || (whentohangup * 1000 < *ms)) { 01016 rms = whentohangup * 1000; 01017 } 01018 } 01019 max = 0; 01020 for (x=0;x<n;x++) { 01021 for (y=0;y<AST_MAX_FDS;y++) { 01022 if (c[x]->fds[y] > -1) { 01023 pfds[max].fd = c[x]->fds[y]; 01024 pfds[max].events = POLLIN | POLLPRI; 01025 max++; 01026 } 01027 } 01028 CHECK_BLOCKING(c[x]); 01029 } 01030 for (x=0;x<nfds; x++) { 01031 if (fds[x] > -1) { 01032 pfds[max].fd = fds[x]; 01033 pfds[max].events = POLLIN | POLLPRI; 01034 max++; 01035 } 01036 } 01037 if (*ms > 0) 01038 gettimeofday(&start, NULL); 01039 res = poll(pfds, max, rms); 01040 if (res < 0) { 01041 for (x=0;x<n;x++) 01042 c[x]->blocking = 0; 01043 /* Simulate a timeout if we were interrupted */ 01044 if (errno != EINTR) 01045 *ms = -1; 01046 else { 01047 /* Just an interrupt */ 01048 #if 0 01049 *ms = 0; 01050 #endif 01051 } 01052 return NULL; 01053 } 01054 01055 if (havewhen) 01056 time(&now); 01057 spoint = 0; 01058 for (x=0;x<n;x++) { 01059 c[x]->blocking = 0; 01060 if (havewhen && c[x]->whentohangup && (now > c[x]->whentohangup)) { 01061 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 01062 if (!winner) 01063 winner = c[x]; 01064 } 01065 for (y=0;y<AST_MAX_FDS;y++) { 01066 if (c[x]->fds[y] > -1) { 01067 if ((res = ast_fdisset(pfds, c[x]->fds[y], max, &spoint))) { 01068 if (res & POLLPRI) 01069 c[x]->exception = -1; 01070 else 01071 c[x]->exception = 0; 01072 c[x]->fdno = y; 01073 winner = c[x]; 01074 } 01075 } 01076 } 01077 } 01078 for (x=0;x<nfds;x++) { 01079 if (fds[x] > -1) { 01080 if ((res = ast_fdisset(pfds, fds[x], max, &spoint))) { 01081 if (outfd) 01082 *outfd = fds[x]; 01083 if (exception) { 01084 if (res & POLLPRI) 01085 *exception = -1; 01086 else 01087 *exception = 0; 01088 } 01089 winner = NULL; 01090 } 01091 } 01092 } 01093 if (*ms > 0) { 01094 long diff; 01095 gettimeofday(&end, NULL); 01096 diff = (end.tv_sec - start.tv_sec) * 1000; 01097 diff += (end.tv_usec - start.tv_usec) / 1000; 01098 if (diff < *ms) 01099 *ms -= diff; 01100 else 01101 *ms = 0; 01102 } 01103 return winner; 01104 }
|
|
Waits for a digit.
Definition at line 1125 of file channel.c. References ast_check_hangup(), AST_FRAME_DTMF, ast_frfree(), ast_read(), ast_waitfor(), ast_frame::frametype, and ast_frame::subclass. Referenced by ast_control_streamfile(), ast_pbx_run(), and ast_readstring(). 01126 { 01127 /* XXX Should I be merged with waitfordigit_full XXX */ 01128 struct ast_frame *f; 01129 char result = 0; 01130 /* Stop if we're a zombie or need a soft hangup */ 01131 if (c->zombie || ast_check_hangup(c)) 01132 return -1; 01133 /* Wait for a digit, no more than ms milliseconds total. */ 01134 while(ms && !result) { 01135 ms = ast_waitfor(c, ms); 01136 if (ms < 0) /* Error */ 01137 result = -1; 01138 else if (ms > 0) { 01139 /* Read something */ 01140 f = ast_read(c); 01141 if (f) { 01142 if (f->frametype == AST_FRAME_DTMF) 01143 result = f->subclass; 01144 ast_frfree(f); 01145 } else 01146 result = -1; 01147 } 01148 } 01149 return result; 01150 }
|
|
Definition at line 1169 of file channel.c. References ast_check_hangup(), AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_waitfor_nandfds(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass. Referenced by ast_readstring_full(). 01170 { 01171 struct ast_frame *f; 01172 struct ast_channel *rchan; 01173 int outfd; 01174 int res; 01175 /* Stop if we're a zombie or need a soft hangup */ 01176 if (c->zombie || ast_check_hangup(c)) 01177 return -1; 01178 /* Wait for a digit, no more than ms milliseconds total. */ 01179 while(ms) { 01180 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 01181 if ((!rchan) && (outfd < 0) && (ms)) { 01182 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 01183 return -1; 01184 } else if (outfd > -1) { 01185 /* The FD we were watching has something waiting */ 01186 return 1; 01187 } else if (rchan) { 01188 f = ast_read(c); 01189 if(!f) { 01190 return -1; 01191 } 01192 01193 switch(f->frametype) { 01194 case AST_FRAME_DTMF: 01195 res = f->subclass; 01196 ast_frfree(f); 01197 return res; 01198 case AST_FRAME_CONTROL: 01199 switch(f->subclass) { 01200 case AST_CONTROL_HANGUP: 01201 ast_frfree(f); 01202 return -1; 01203 case AST_CONTROL_RINGING: 01204 case AST_CONTROL_ANSWER: 01205 /* Unimportant */ 01206 break; 01207 default: 01208 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass); 01209 } 01210 case AST_FRAME_VOICE: 01211 /* Write audio if appropriate */ 01212 if (audiofd > -1) 01213 write(audiofd, f->data, f->datalen); 01214 } 01215 /* Ignore */ 01216 ast_frfree(f); 01217 } 01218 } 01219 return 0; // Time is up 01220 }
|
|
Write a frame to a channel.
Definition at line 1604 of file channel.c. References ast_check_hangup(), ast_deactivate_generator(), ast_do_masquerade(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dump(), AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_seekstream(), AST_SOFTHANGUP_DEV, ast_translate(), ast_writestream(), CHECK_BLOCKING, ast_frame::frametype, LOG_WARNING, ast_frame::samples, and SEEK_FORCECUR. Referenced by ast_channel_bridge(), ast_dtmf_stream(), ast_prod(), ast_rtp_bridge(), and ast_write_video(). 01605 { 01606 int res = -1; 01607 struct ast_frame *f = NULL; 01608 /* Stop if we're a zombie or need a soft hangup */ 01609 ast_mutex_lock(&chan->lock); 01610 if (chan->zombie || ast_check_hangup(chan)) { 01611 ast_mutex_unlock(&chan->lock); 01612 return -1; 01613 } 01614 /* Handle any pending masquerades */ 01615 if (chan->masq) { 01616 if (ast_do_masquerade(chan)) { 01617 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 01618 ast_mutex_unlock(&chan->lock); 01619 return -1; 01620 } 01621 } 01622 if (chan->masqr) { 01623 ast_mutex_unlock(&chan->lock); 01624 return 0; 01625 } 01626 if (chan->generatordata) { 01627 if (chan->writeinterrupt) 01628 ast_deactivate_generator(chan); 01629 else { 01630 ast_mutex_unlock(&chan->lock); 01631 return 0; 01632 } 01633 } 01634 if (chan->fout & 0x80000000) 01635 ast_frame_dump(chan->name, fr, ">>"); 01636 CHECK_BLOCKING(chan); 01637 switch(fr->frametype) { 01638 case AST_FRAME_CONTROL: 01639 /* XXX Interpret control frames XXX */ 01640 ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n"); 01641 break; 01642 case AST_FRAME_DTMF: 01643 chan->blocking = 0; 01644 ast_mutex_unlock(&chan->lock); 01645 res = do_senddigit(chan,fr->subclass); 01646 ast_mutex_lock(&chan->lock); 01647 CHECK_BLOCKING(chan); 01648 break; 01649 case AST_FRAME_TEXT: 01650 if (chan->pvt->send_text) 01651 res = chan->pvt->send_text(chan, (char *) fr->data); 01652 break; 01653 case AST_FRAME_VIDEO: 01654 /* XXX Handle translation of video codecs one day XXX */ 01655 if (chan->pvt->write_video) 01656 res = chan->pvt->write_video(chan, fr); 01657 else 01658 res = 0; 01659 break; 01660 default: 01661 if (chan->pvt->write) { 01662 if (chan->pvt->writetrans) { 01663 f = ast_translate(chan->pvt->writetrans, fr, 0); 01664 } else 01665 f = fr; 01666 if (f) { 01667 res = chan->pvt->write(chan, f); 01668 if( chan->monitor && 01669 chan->monitor->write_stream && 01670 f && ( f->frametype == AST_FRAME_VOICE ) ) { 01671 #ifndef MONITOR_CONSTANT_DELAY 01672 int jump = chan->insmpl - chan->outsmpl - 2 * f->samples; 01673 if (jump >= 0) { 01674 if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1) 01675 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 01676 chan->outsmpl += jump + 2 * f->samples; 01677 } else 01678 chan->outsmpl += f->samples; 01679 #else 01680 int jump = chan->insmpl - chan->outsmpl; 01681 if (jump - MONITOR_DELAY >= 0) { 01682 if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1) 01683 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 01684 chan->outsmpl += jump; 01685 } else 01686 chan->outsmpl += f->samples; 01687 #endif 01688 if (ast_writestream(chan->monitor->write_stream, f) < 0) 01689 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n"); 01690 } 01691 } else 01692 res = 0; 01693 } 01694 } 01695 if (f && (f != fr)) 01696 ast_frfree(f); 01697 chan->blocking = 0; 01698 /* Consider a write failure to force a soft hangup */ 01699 if (res < 0) 01700 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01701 else { 01702 if ((chan->fout & 0x7fffffff) == 0x7fffffff) 01703 chan->fout &= 0x80000000; 01704 else 01705 chan->fout++; 01706 chan->fout++; 01707 } 01708 ast_mutex_unlock(&chan->lock); 01709 return res; 01710 }
|
|
Write video frame to a channel.
Definition at line 1593 of file channel.c. References ast_write(). 01594 { 01595 int res; 01596 if (!chan->pvt->write_video) 01597 return 0; 01598 res = ast_write(chan, fr); 01599 if (!res) 01600 res = 1; 01601 return res; 01602 }
|
|
Definition at line 87 of file asterisk.c. |
|
Referenced by ast_channel_register_ex(), ast_channel_unregister(), ast_device_state(), and ast_request(). |
|
Definition at line 75 of file channel.c. Referenced by ast_active_channels(), ast_begin_shutdown(), ast_channel_alloc(), ast_channel_free(), and ast_channel_walk_locked(). |