#include <asterisk/frame.h>#include <asterisk/sched.h>#include <asterisk/chanvars.h>#include <unistd.h>#include <setjmp.h>#include <sys/poll.h>#include <asterisk/lock.h>#include <asterisk/cdr.h>#include <asterisk/monitor.h>Go to the source code of this file.
Data Structures | |
| struct | ast_bridge_config |
| struct | ast_channel |
| Main Channel structure associated with a channel. More... | |
| struct | ast_generator |
| struct | outgoing_helper |
Defines | |
| #define | AST_MAX_EXTENSION 80 |
| Max length of an extension. More... | |
| #define | AST_CHANNEL_NAME 80 |
| #define | AST_CHANNEL_MAX_STACK 32 |
| #define | MAX_LANGUAGE 20 |
| #define | AST_MAX_FDS 8 |
| #define | AST_FLAG_DIGITAL 1 |
| #define | LOAD_OH(oh) |
| #define | AST_CDR_TRANSFER (1 << 0) |
| #define | AST_CDR_FORWARD (1 << 1) |
| #define | AST_CDR_CALLWAIT (1 << 2) |
| #define | AST_CDR_CONFERENCE (1 << 3) |
| #define | AST_ADSI_UNKNOWN (0) |
| #define | AST_ADSI_AVAILABLE (1) |
| #define | AST_ADSI_UNAVAILABLE (2) |
| #define | AST_ADSI_OFFHOOKONLY (3) |
| #define | AST_SOFTHANGUP_DEV (1 << 0) |
| #define | AST_SOFTHANGUP_ASYNCGOTO (1 << 1) |
| #define | AST_SOFTHANGUP_SHUTDOWN (1 << 2) |
| #define | AST_SOFTHANGUP_TIMEOUT (1 << 3) |
| #define | AST_SOFTHANGUP_APPUNLOAD (1 << 4) |
| #define | AST_SOFTHANGUP_EXPLICIT (1 << 5) |
| #define | AST_STATE_DOWN 0 |
| #define | AST_STATE_RESERVED 1 |
| #define | AST_STATE_OFFHOOK 2 |
| #define | AST_STATE_DIALING 3 |
| #define | AST_STATE_RING 4 |
| #define | AST_STATE_RINGING 5 |
| #define | AST_STATE_UP 6 |
| #define | AST_STATE_BUSY 7 |
| #define | AST_STATE_DIALING_OFFHOOK 8 |
| #define | AST_STATE_PRERING 9 |
| #define | AST_STATE_MUTE (1 << 16) |
| #define | AST_DEVICE_UNKNOWN 0 |
| #define | AST_DEVICE_NOT_INUSE 1 |
| #define | AST_DEVICE_INUSE 2 |
| #define | AST_DEVICE_BUSY 3 |
| #define | AST_DEVICE_INVALID 4 |
| #define | AST_DEVICE_UNAVAILABLE 5 |
| #define | AST_BRIDGE_DTMF_CHANNEL_0 (1 << 0) |
| #define | AST_BRIDGE_DTMF_CHANNEL_1 (1 << 1) |
| #define | AST_BRIDGE_REC_CHANNEL_0 (1 << 2) |
| #define | AST_BRIDGE_REC_CHANNEL_1 (1 << 3) |
| #define | AST_BRIDGE_IGNORE_SIGS (1 << 4) |
| #define | CRASH do { } while(0) |
| #define | CHECK_BLOCKING(c) |
Functions | |
| ast_channel * | ast_request (char *type, int format, void *data) |
| Requests a channel. More... | |
| int | ast_parse_device_state (char *device) |
| Search the Channels by Name. More... | |
| int | ast_device_state (char *device) |
| Asks a channel for device state. More... | |
| ast_channel * | ast_request_and_dial (char *type, int format, void *data, int timeout, int *reason, char *callerid) |
| ast_channel * | __ast_request_and_dial (char *type, int format, void *data, int timeout, int *reason, char *callerid, struct outgoing_helper *oh) |
| int | ast_channel_register (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data)) |
| Registers a channel. More... | |
| 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)) |
| void | ast_channel_unregister (char *type) |
| Unregister a channel class. More... | |
| int | ast_hangup (struct ast_channel *chan) |
| Hang up a channel. More... | |
| int | ast_softhangup (struct ast_channel *chan, int cause) |
| Softly hangup up a channel. More... | |
| int | ast_softhangup_nolock (struct ast_channel *chan, int cause) |
| int | ast_check_hangup (struct ast_channel *chan) |
| Check to see if a channel is needing hang up. More... | |
| void | ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset) |
| Set when to hang a channel up. More... | |
| int | ast_answer (struct ast_channel *chan) |
| Answer a ringing call. More... | |
| int | ast_call (struct ast_channel *chan, char *addr, int timeout) |
| Make a call. More... | |
| int | ast_indicate (struct ast_channel *chan, int condition) |
| Indicates condition of channel. More... | |
| int | ast_waitfor (struct ast_channel *chan, int ms) |
| Wait for input on a channel. More... | |
| int | ast_safe_sleep (struct ast_channel *chan, int ms) |
| Wait for a specied amount of time, looking for hangups. More... | |
| 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. More... | |
| ast_channel * | ast_waitfor_nandfds (struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms) |
| Waits for activity on a group of channels. More... | |
| ast_channel * | ast_waitfor_n (struct ast_channel **chan, int n, int *ms) |
| Waits for input on a group of channels. More... | |
| int | ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception) |
| Waits for input on an fd. More... | |
| ast_frame * | ast_read (struct ast_channel *chan) |
| Reads a frame. More... | |
| int | ast_write (struct ast_channel *chan, struct ast_frame *frame) |
| Write a frame to a channel. More... | |
| int | ast_write_video (struct ast_channel *chan, struct ast_frame *frame) |
| Write video frame to a channel. More... | |
| int | ast_prod (struct ast_channel *chan) |
| int | ast_set_read_format (struct ast_channel *chan, int format) |
| Sets read format on channel chan. More... | |
| int | ast_set_write_format (struct ast_channel *chan, int format) |
| Sets write format on channel chan. More... | |
| int | ast_sendtext (struct ast_channel *chan, char *text) |
| Sends text to a channel. More... | |
| int | ast_senddigit (struct ast_channel *chan, char digit) |
| Receives a text character from a channel. More... | |
| int | ast_recvchar (struct ast_channel *chan, int timeout) |
| ast_channel * | ast_channel_walk_locked (struct ast_channel *prev) |
| Browse channels in use. More... | |
| ast_channel * | ast_get_channel_by_name_locked (char *channame) |
| Get channel by name (locks channel). More... | |
| char | ast_waitfordigit (struct ast_channel *c, int ms) |
| Waits for a digit. More... | |
| char | ast_waitfordigit_full (struct ast_channel *c, int ms, int audiofd, int ctrlfd) |
| int | ast_readstring (struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders) |
| Reads multiple digits. More... | |
| int | ast_readstring_full (struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd) |
| int | ast_channel_make_compatible (struct ast_channel *c0, struct ast_channel *c1) |
| Makes two channel formats compatible. More... | |
| 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. More... | |
| int | ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone) |
| Weird function made for call transfers. More... | |
| char * | ast_state2str (int state) |
| Gives the string form of a given state. More... | |
| int | ast_channel_setoption (struct ast_channel *channel, int option, void *data, int datalen, int block) |
| Sets an option on a channel. More... | |
| ast_frame * | ast_channel_queryoption (struct ast_channel *channel, int option, void *data, int *datalen, int block) |
| Checks the value of an option. More... | |
| int | ast_channel_supports_html (struct ast_channel *channel) |
| Checks for HTML support on a channel. More... | |
| int | ast_channel_sendhtml (struct ast_channel *channel, int subclass, char *data, int datalen) |
| Sends HTML on given channel. More... | |
| int | ast_channel_sendurl (struct ast_channel *channel, char *url) |
| Sends a URL on a given link. More... | |
| int | ast_channel_defer_dtmf (struct ast_channel *chan) |
| Defers DTMF. More... | |
| void | ast_channel_undefer_dtmf (struct ast_channel *chan) |
| Undeos a defer. More... | |
| void | ast_begin_shutdown (int hangup) |
| void | ast_cancel_shutdown (void) |
| int | ast_active_channels (void) |
| int | ast_shutting_down (void) |
| int | ast_activate_generator (struct ast_channel *chan, struct ast_generator *gen, void *params) |
| void | ast_deactivate_generator (struct ast_channel *chan) |
| void | ast_set_callerid (struct ast_channel *chan, char *callerid, int anitoo) |
| 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) |
| int | ast_autoservice_start (struct ast_channel *chan) |
| int | ast_autoservice_stop (struct ast_channel *chan) |
| int | ast_settimeout (struct ast_channel *c, int samples, int(*func)(void *data), void *data) |
| int | ast_transfer (struct ast_channel *chan, char *dest) |
| int | ast_do_masquerade (struct ast_channel *chan) |
| unsigned int | ast_get_group (char *s) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Report DTMF on channel 0 Definition at line 665 of file channel.h. Referenced by ast_channel_bridge(), and ast_rtp_bridge(). |
|
|
Report DTMF on channel 1 Definition at line 667 of file channel.h. Referenced by ast_channel_bridge(), and ast_rtp_bridge(). |
|
|
Ignore all signal frames except NULL Definition at line 673 of file channel.h. Referenced by ast_channel_bridge(). |
|
|
Return all voice frames on channel 0 |
|
|
Return all voice frames on channel 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 38 of file channel.h. Referenced by pbx_exec(). |
|
|
Definition at line 37 of file channel.h. Referenced by ast_channel_free(), and ast_parse_device_state(). |
|
|
Device is busy |
|
|
Device is in use Definition at line 353 of file channel.h. Referenced by ast_parse_device_state(). |
|
|
Device is invalid Definition at line 357 of file channel.h. Referenced by ast_device_state(). |
|
|
Device is not used |
|
|
Device is unavailable |
|
|
Device is valid but channel didn't know state Definition at line 349 of file channel.h. Referenced by ast_device_state(), and ast_parse_device_state(). |
|
|
|
|
|
Max length of an extension.
Definition at line 31 of file channel.h. Referenced by ast_cdr_init(), ast_cdr_setcid(), ast_cdr_update(), ast_device_state(), and ast_device_state_changed(). |
|
|
Definition at line 43 of file channel.h. Referenced by ast_channel_alloc(), ast_do_masquerade(), ast_read(), and ast_waitfor_nandfds(). |
|
|
|
|
|
Definition at line 316 of file channel.h. Referenced by ast_async_goto(), and ast_pbx_run(). |
|
|
Definition at line 315 of file channel.h. Referenced by ast_do_masquerade(), ast_dsp_process(), ast_queue_hangup(), ast_read(), and ast_write(). |
|
|
|
|
|
Definition at line 317 of file channel.h. Referenced by ast_begin_shutdown(). |
|
|
Definition at line 318 of file channel.h. Referenced by ast_check_hangup(), ast_pbx_run(), and ast_waitfor_nandfds(). |
|
|
Line is busy Definition at line 338 of file channel.h. Referenced by ast_state2str(). |
|
|
Digits (or equivalent) have been dialed Definition at line 330 of file channel.h. Referenced by ast_state2str(). |
|
|
Digits (or equivalent) have been dialed while offhook |
|
|
Channel is down and available Definition at line 324 of file channel.h. Referenced by ast_channel_alloc(), ast_request(), ast_setstate(), and ast_state2str(). |
|
|
Do not transmit voice data |
|
|
Channel is off hook Definition at line 328 of file channel.h. Referenced by ast_state2str(). |
|
|
Channel has detected an incoming call and is waiting for ring |
|
|
Channel is down, but reserved Definition at line 326 of file channel.h. Referenced by ast_state2str(). |
|
|
Line is ringing Definition at line 332 of file channel.h. Referenced by ast_answer(), and ast_state2str(). |
|
|
Remote end is ringing Definition at line 334 of file channel.h. Referenced by ast_answer(), and ast_state2str(). |
|
|
Line is up Definition at line 336 of file channel.h. Referenced by __ast_request_and_dial(), ast_answer(), ast_cdr_init(), ast_control_streamfile(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_prod(), ast_read(), and ast_state2str(). |
|
|
Definition at line 879 of file channel.h. Referenced by ast_sendtext(), ast_waitfor_nandfds(), and ast_write(). |
|
|
Definition at line 876 of file channel.h. Referenced by ast_hangup(), ast_queue_frame(), ast_rtcp_read(), ast_rtp_read(), and ast_sched_del(). |
|
|
Definition at line 287 of file channel.h. Referenced by ast_pbx_outgoing_exten(). |
|
|
Definition at line 40 of file channel.h. Referenced by ast_fileexists(), and ast_openvstream(). |
|
||||||||||||||||||||||||||||||||
|
Definition at line 1746 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_frfree(), ast_hangup(), ast_log(), ast_read(), ast_request(), ast_set_callerid(), AST_STATE_UP, ast_waitfor(), ast_channel::callerid, ast_channel::cdr, ast_channel::context, ast_channel::exten, ast_frame::frametype, ast_channel::hangupcause, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar(), ast_channel::priority, and ast_frame::subclass. Referenced by ast_pbx_outgoing_exten(), and ast_request_and_dial().
01747 {
01748 int state = 0;
01749 struct ast_channel *chan;
01750 struct ast_frame *f;
01751 int res = 0;
01752 char *variable;
01753 chan = ast_request(type, format, data);
01754 if (chan) {
01755 if (oh) {
01756 char *tmp, *var;
01757 /* JDG chanvar */
01758 if (oh->variable)
01759 variable = ast_strdupa(oh->variable);
01760 else
01761 variable = NULL;
01762 tmp = variable;
01763 /* FIXME replace this call with strsep NOT*/
01764 while( (var = strtok_r(NULL, "|", &tmp)) ) {
01765 pbx_builtin_setvar( chan, var );
01766 } /* /JDG */
01767 if (oh->callerid && *oh->callerid)
01768 ast_set_callerid(chan, oh->callerid, 1);
01769 if (oh->account && *oh->account)
01770 ast_cdr_setaccount(chan, oh->account);
01771 }
01772 if (callerid && !ast_strlen_zero(callerid))
01773 ast_set_callerid(chan, callerid, 1);
01774
01775 if (!ast_call(chan, data, 0)) {
01776 while(timeout && (chan->_state != AST_STATE_UP)) {
01777 res = ast_waitfor(chan, timeout);
01778 if (res < 0) {
01779 /* Something not cool, or timed out */
01780 break;
01781 }
01782 /* If done, break out */
01783 if (!res)
01784 break;
01785 if (timeout > -1)
01786 timeout = res;
01787 f = ast_read(chan);
01788 if (!f) {
01789 state = AST_CONTROL_HANGUP;
01790 res = 0;
01791 break;
01792 }
01793 if (f->frametype == AST_FRAME_CONTROL) {
01794 if (f->subclass == AST_CONTROL_RINGING)
01795 state = AST_CONTROL_RINGING;
01796 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01797 state = f->subclass;
01798 ast_frfree(f);
01799 break;
01800 } else if (f->subclass == AST_CONTROL_ANSWER) {
01801 state = f->subclass;
01802 ast_frfree(f);
01803 break;
01804 } else if (f->subclass == AST_CONTROL_PROGRESS) {
01805 /* Ignore */
01806 } else if (f->subclass == -1) {
01807 /* Ignore -- just stopping indications */
01808 } else {
01809 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
01810 }
01811 }
01812 ast_frfree(f);
01813 }
01814 } else
01815 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01816 } else
01817 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01818 if (chan) {
01819 /* Final fixups */
01820 if (oh) {
01821 if (oh->context && *oh->context)
01822 strncpy(chan->context, oh->context, sizeof(chan->context) - 1);
01823 if (oh->exten && *oh->exten)
01824 strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1);
01825 chan->priority = oh->priority;
01826 }
01827 if (chan->_state == AST_STATE_UP)
01828 state = AST_CONTROL_ANSWER;
01829 }
01830 if (outstate)
01831 *outstate = state;
01832 if (chan && res <= 0) {
01833 if (!chan->cdr) {
01834 chan->cdr = ast_cdr_alloc();
01835 if (chan->cdr)
01836 ast_cdr_init(chan->cdr, chan);
01837 }
01838 if (chan->cdr) {
01839 char tmp[256];
01840 snprintf(tmp, 256, "%s/%s", type, (char *)data);
01841 ast_cdr_setapp(chan->cdr,"Dial",tmp);
01842 ast_cdr_update(chan);
01843 ast_cdr_start(chan->cdr);
01844 ast_cdr_end(chan->cdr);
01845 /* If the cause wasn't handled properly */
01846 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
01847 ast_cdr_failed(chan->cdr);
01848 } else
01849 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01850 ast_hangup(chan);
01851 chan = NULL;
01852 }
01853 return chan;
01854 }
|
|
||||||||||||||||
|
Activate a given generator Definition at line 849 of file channel.c. References ast_generator::alloc, ast_mutex_lock, ast_mutex_unlock, ast_prod(), ast_settimeout(), ast_channel::generator, ast_channel::generatordata, ast_channel::lock, and ast_generator::release. Referenced by ast_linear_stream(), ast_playtones_start(), and ast_tonepair_start().
00850 {
00851 int res = 0;
00852 ast_mutex_lock(&chan->lock);
00853 if (chan->generatordata) {
00854 if (chan->generator && chan->generator->release)
00855 chan->generator->release(chan, chan->generatordata);
00856 chan->generatordata = NULL;
00857 }
00858 ast_prod(chan);
00859 if ((chan->generatordata = gen->alloc(chan, params))) {
00860 ast_settimeout(chan, 160, generator_force, chan);
00861 chan->generator = gen;
00862 } else {
00863 res = -1;
00864 }
00865 ast_mutex_unlock(&chan->lock);
00866 return res;
00867 }
|
|
|
Returns number of active/allocated channels Definition at line 120 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, and ast_channel::next.
00121 {
00122 struct ast_channel *c;
00123 int cnt = 0;
00124 ast_mutex_lock(&chlock);
00125 c = channels;
00126 while(c) {
00127 cnt++;
00128 c = c->next;
00129 }
00130 ast_mutex_unlock(&chlock);
00131 return cnt;
00132 }
|
|
|
Answer a ringing call.
Definition at line 785 of file channel.c. References ast_channel::_state, ast_channel_pvt::answer, ast_cdr_answer(), ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_channel::cdr, ast_channel::lock, ast_channel::pvt, and ast_channel::zombie. Referenced by ast_control_streamfile().
00786 {
00787 int res = 0;
00788 ast_mutex_lock(&chan->lock);
00789 /* Stop if we're a zombie or need a soft hangup */
00790 if (chan->zombie || ast_check_hangup(chan)) {
00791 ast_mutex_unlock(&chan->lock);
00792 return -1;
00793 }
00794 switch(chan->_state) {
00795 case AST_STATE_RINGING:
00796 case AST_STATE_RING:
00797 if (chan->pvt->answer)
00798 res = chan->pvt->answer(chan);
00799 ast_setstate(chan, AST_STATE_UP);
00800 if (chan->cdr)
00801 ast_cdr_answer(chan->cdr);
00802 ast_mutex_unlock(&chan->lock);
00803 return res;
00804 break;
00805 case AST_STATE_UP:
00806 if (chan->cdr)
00807 ast_cdr_answer(chan->cdr);
00808 break;
00809 }
00810 ast_mutex_unlock(&chan->lock);
00811 return 0;
00812 }
|
|
|
Automatically service a channel for us... Definition at line 88 of file autoservice.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create(), AST_PTHREADT_NULL, asent::chan, free, LOG_WARNING, malloc, and asent::next. Referenced by ast_dtmf_stream(), ast_get_enum(), ast_get_srv(), and ast_get_txt().
00089 {
00090 int res = -1;
00091 struct asent *as;
00092 int needstart;
00093 ast_mutex_lock(&autolock);
00094 needstart = (asthread == AST_PTHREADT_NULL) ? 1 : 0 /* aslist ? 0 : 1 */;
00095 as = aslist;
00096 while(as) {
00097 if (as->chan == chan)
00098 break;
00099 as = as->next;
00100 }
00101 if (!as) {
00102 as = malloc(sizeof(struct asent));
00103 if (as) {
00104 memset(as, 0, sizeof(struct asent));
00105 as->chan = chan;
00106 as->next = aslist;
00107 aslist = as;
00108 res = 0;
00109 if (needstart) {
00110 if (ast_pthread_create(&asthread, NULL, autoservice_run, NULL)) {
00111 ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
00112 free(aslist);
00113 aslist = NULL;
00114 res = -1;
00115 } else
00116 pthread_kill(asthread, SIGURG);
00117 }
00118 }
00119 }
00120 ast_mutex_unlock(&autolock);
00121 return res;
00122 }
|
|
|
Stop servicing a channel for us... Returns -1 on error or if channel has been hungup Definition at line 124 of file autoservice.c. References ast_channel::_softhangup, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, ast_channel::blocking, asent::chan, free, and asent::next. Referenced by ast_dtmf_stream(), ast_get_enum(), ast_get_srv(), and ast_get_txt().
00125 {
00126 int res = -1;
00127 struct asent *as, *prev;
00128 ast_mutex_lock(&autolock);
00129 as = aslist;
00130 prev = NULL;
00131 while(as) {
00132 if (as->chan == chan)
00133 break;
00134 prev = as;
00135 as = as->next;
00136 }
00137 if (as) {
00138 if (prev)
00139 prev->next = as->next;
00140 else
00141 aslist = as->next;
00142 free(as);
00143 if (!chan->_softhangup)
00144 res = 0;
00145 }
00146 if (asthread != AST_PTHREADT_NULL)
00147 pthread_kill(asthread, SIGURG);
00148 ast_mutex_unlock(&autolock);
00149 /* Wait for it to un-block */
00150 while(chan->blocking)
00151 usleep(1000);
00152 return res;
00153 }
|
|
|
Initiate system shutdown -- prevents new channels from being allocated. If "hangup" is non-zero, all existing channels will receive soft hangups Definition at line 105 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), AST_SOFTHANGUP_SHUTDOWN, and ast_channel::next.
00106 {
00107 struct ast_channel *c;
00108 shutting_down = 1;
00109 if (hangup) {
00110 ast_mutex_lock(&chlock);
00111 c = channels;
00112 while(c) {
00113 ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
00114 c = c->next;
00115 }
00116 ast_mutex_unlock(&chlock);
00117 }
00118 }
|
|
||||||||||||||||
|
Make a call.
Definition at line 1965 of file channel.c. References ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_channel_pvt::call, ast_channel::lock, ast_channel::pvt, and ast_channel::zombie. Referenced by __ast_request_and_dial().
01966 {
01967 /* Place an outgoing call, but don't wait any longer than timeout ms before returning.
01968 If the remote end does not answer within the timeout, then do NOT hang up, but
01969 return anyway. */
01970 int res = -1;
01971 /* Stop if we're a zombie or need a soft hangup */
01972 ast_mutex_lock(&chan->lock);
01973 if (!chan->zombie && !ast_check_hangup(chan))
01974 if (chan->pvt->call)
01975 res = chan->pvt->call(chan, addr, timeout);
01976 ast_mutex_unlock(&chan->lock);
01977 return res;
01978 }
|
|
|
Cancels an existing shutdown and returns to normal operation Definition at line 134 of file channel.c.
00135 {
00136 shutting_down = 0;
00137 }
|
|
||||||||||||||||||||||||
|
Bridge two channels together.
Definition at line 2497 of file channel.c. References ast_bridge_config::allowdisconnect_in, ast_bridge_config::allowdisconnect_out, ast_bridge_config::allowredirect_in, ast_bridge_config::allowredirect_out, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, ast_channel_make_compatible(), ast_check_hangup(), ast_frfree(), ast_log(), ast_read(), ast_verbose(), ast_waitfor_n(), ast_write(), ast_channel_pvt::bridge, ast_channel::bridge, ast_bridge_config::end_sound, EVENT_FLAG_CALL, ast_bridge_config::firstpass, ast_frame::frametype, ast_channel::generator, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::monitor, ast_channel::name, ast_channel::nativeformats, ast_bridge_config::play_to_callee, ast_bridge_config::play_to_caller, ast_bridge_config::play_warning, ast_channel::pvt, ast_channel::readformat, ast_bridge_config::start_sound, ast_frame::subclass, ast_bridge_config::timelimit, ast_channel::uniqueid, VERBOSE_PREFIX_3, ast_bridge_config::warning_freq, ast_bridge_config::warning_sound, ast_channel::writeformat, and ast_channel::zombie.
02498 {
02499 /* Copy voice back and forth between the two channels. Give the peer
02500 the ability to transfer calls with '#<extension' syntax. */
02501 int flags;
02502 struct ast_channel *cs[3];
02503 int to = -1;
02504 struct ast_frame *f;
02505 struct ast_channel *who = NULL;
02506 int res=0;
02507 int nativefailed=0;
02508 int firstpass;
02509 int o0nativeformats;
02510 int o1nativeformats;
02511 struct timeval start_time,precise_now;
02512 long elapsed_ms=0, time_left_ms=0;
02513 int playit=0, playitagain=1, first_time=1;
02514
02515 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);
02516
02517 firstpass = config->firstpass;
02518 config->firstpass = 0;
02519
02520 /* timestamp */
02521 gettimeofday(&start_time,NULL);
02522 time_left_ms = config->timelimit;
02523
02524 if (config->play_to_caller && config->start_sound && firstpass)
02525 bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000);
02526 if (config->play_to_callee && config->start_sound && firstpass)
02527 bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000);
02528
02529 /* Stop if we're a zombie or need a soft hangup */
02530 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1))
02531 return -1;
02532 if (c0->bridge) {
02533 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
02534 c0->name, c0->bridge->name);
02535 return -1;
02536 }
02537 if (c1->bridge) {
02538 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
02539 c1->name, c1->bridge->name);
02540 return -1;
02541 }
02542
02543 /* Keep track of bridge */
02544 c0->bridge = c1;
02545 c1->bridge = c0;
02546 cs[0] = c0;
02547 cs[1] = c1;
02548
02549 manager_event(EVENT_FLAG_CALL, "Link",
02550 "Channel1: %s\r\n"
02551 "Channel2: %s\r\n"
02552 "Uniqueid1: %s\r\n"
02553 "Uniqueid2: %s\r\n",
02554 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02555 o1nativeformats = c1->nativeformats;
02556 o0nativeformats = c0->nativeformats;
02557 for (/* ever */;;) {
02558 /* timestamp */
02559 if (config->timelimit) {
02560 gettimeofday(&precise_now,NULL);
02561 elapsed_ms = tvdiff(&precise_now,&start_time);
02562 time_left_ms = config->timelimit - elapsed_ms;
02563
02564 if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) {
02565 /* narrowing down to the end */
02566 if (config->warning_freq == 0) {
02567 playit = 1;
02568 first_time=0;
02569 playitagain=0;
02570 } else if (first_time) {
02571 playit = 1;
02572 first_time=0;
02573 } else {
02574 if ((time_left_ms % config->warning_freq) <= 50) {
02575 playit = 1;
02576 }
02577 }
02578 }
02579 if (time_left_ms <= 0) {
02580 if (config->play_to_caller && config->end_sound)
02581 bridge_playfile(c0,c1,config->end_sound,0);
02582 if (config->play_to_callee && config->end_sound)
02583 bridge_playfile(c1,c0,config->end_sound,0);
02584 *fo = NULL;
02585 if (who) *rc = who;
02586 res = 0;
02587 break;
02588 }
02589 if (time_left_ms >= 5000 && playit) {
02590 if (config->play_to_caller && config->warning_sound && config->play_warning)
02591 bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000);
02592 if (config->play_to_callee && config->warning_sound && config->play_warning)
02593 bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000);
02594 playit = 0;
02595 }
02596
02597 }
02598 /* Stop if we're a zombie or need a soft hangup */
02599 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
02600 *fo = NULL;
02601 if (who) *rc = who;
02602 res = 0;
02603 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");
02604 break;
02605 }
02606 if (c0->pvt->bridge && config->timelimit==0 &&
02607 (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
02608 /* Looks like they share a bridge code */
02609 if (option_verbose > 2)
02610 ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
02611 if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
02612 c0->bridge = NULL;
02613 c1->bridge = NULL;
02614 manager_event(EVENT_FLAG_CALL, "Unlink",
02615 "Channel1: %s\r\n"
02616 "Channel2: %s\r\n"
02617 "Uniqueid1: %s\r\n"
02618 "Uniqueid2: %s\r\n",
02619 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02620 ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
02621 return 0;
02622 }
02623 /* If they return non-zero then continue on normally. Let "-2" mean don't worry about
02624 my not wanting to bridge */
02625 if ((res != -2) && (res != -3))
02626 ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
02627 if (res != -3) nativefailed++;
02628 }
02629
02630 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) &&
02631 !(c0->generator || c1->generator)) {
02632 if (ast_channel_make_compatible(c0, c1)) {
02633 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
02634 manager_event(EVENT_FLAG_CALL, "Unlink",
02635 "Channel1: %s\r\n"
02636 "Channel2: %s\r\n"
02637 "Uniqueid1: %s\r\n"
02638 "Uniqueid2: %s\r\n",
02639 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02640 return -1;
02641 }
02642 o0nativeformats = c0->nativeformats;
02643 o1nativeformats = c1->nativeformats;
02644 }
02645 who = ast_waitfor_n(cs, 2, &to);
02646 if (!who) {
02647 ast_log(LOG_DEBUG, "Nobody there, continuing...\n");
02648 continue;
02649 }
02650 f = ast_read(who);
02651 if (!f) {
02652 *fo = NULL;
02653 *rc = who;
02654 res = 0;
02655 ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
02656 break;
02657 }
02658
02659 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02660 *fo = f;
02661 *rc = who;
02662 res = 0;
02663 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
02664 break;
02665 }
02666 if ((f->frametype == AST_FRAME_VOICE) ||
02667 (f->frametype == AST_FRAME_TEXT) ||
02668 (f->frametype == AST_FRAME_VIDEO) ||
02669 (f->frametype == AST_FRAME_IMAGE) ||
02670 (f->frametype == AST_FRAME_DTMF)) {
02671 if ((f->frametype == AST_FRAME_DTMF) &&
02672 (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
02673 if ((who == c0)) {
02674 if ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
02675 *rc = c0;
02676 *fo = f;
02677 /* Take out of conference mode */
02678 res = 0;
02679 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
02680 break;
02681 } else
02682 goto tackygoto;
02683 } else
02684 if ((who == c1)) {
02685 if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
02686 *rc = c1;
02687 *fo = f;
02688 res = 0;
02689 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
02690 break;
02691 } else
02692 goto tackygoto;
02693 }
02694 } else {
02695 #if 0
02696 ast_log(LOG_DEBUG, "Read from %s\n", who->name);
02697 if (who == last)
02698 ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
02699 last = who;
02700 #endif
02701 tackygoto:
02702 /* Don't copy packets if there is a generator on either one, since they're
02703 not supposed to be listening anyway */
02704 if (who == c0)
02705 ast_write(c1, f);
02706 else
02707 ast_write(c0, f);
02708 }
02709 ast_frfree(f);
02710 } else
02711 ast_frfree(f);
02712 /* Swap who gets priority */
02713 cs[2] = cs[0];
02714 cs[0] = cs[1];
02715 cs[1] = cs[2];
02716 }
02717 c0->bridge = NULL;
02718 c1->bridge = NULL;
02719 manager_event(EVENT_FLAG_CALL, "Unlink",
02720 "Channel1: %s\r\n"
02721 "Channel2: %s\r\n"
02722 "Uniqueid1: %s\r\n"
02723 "Uniqueid2: %s\r\n",
02724 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02725 ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name);
02726 return res;
02727 }
|
|
|
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 441 of file channel.c. References ast_channel::deferdtmf.
|
|
||||||||||||
|
Makes two channel formats compatible.
Definition at line 2102 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_set_read_format(), ast_set_write_format(), ast_translator_best_choice(), ast_channel::lock, LOG_WARNING, ast_channel::name, and ast_channel::nativeformats. Referenced by ast_channel_bridge().
02103 {
02104 int peerf;
02105 int chanf;
02106 int res;
02107 ast_mutex_lock(&peer->lock);
02108 peerf = peer->nativeformats;
02109 ast_mutex_unlock(&peer->lock);
02110 ast_mutex_lock(&chan->lock);
02111 chanf = chan->nativeformats;
02112 ast_mutex_unlock(&chan->lock);
02113 res = ast_translator_best_choice(&peerf, &chanf);
02114 if (res < 0) {
02115 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
02116 return -1;
02117 }
02118 /* Set read format on channel */
02119 res = ast_set_read_format(chan, peerf);
02120 if (res < 0) {
02121 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
02122 return -1;
02123 }
02124 /* Set write format on peer channel */
02125 res = ast_set_write_format(peer, peerf);
02126 if (res < 0) {
02127 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
02128 return -1;
02129 }
02130 /* Now we go the other way */
02131 peerf = peer->nativeformats;
02132 chanf = chan->nativeformats;
02133 res = ast_translator_best_choice(&chanf, &peerf);
02134 if (res < 0) {
02135 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
02136 return -1;
02137 }
02138 /* Set writeformat on channel */
02139 res = ast_set_write_format(chan, chanf);
02140 if (res < 0) {
02141 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
02142 return -1;
02143 }
02144 /* Set read format on peer channel */
02145 res = ast_set_read_format(peer, chanf);
02146 if (res < 0) {
02147 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
02148 return -1;
02149 }
02150 return 0;
02151 }
|
|
||||||||||||
|
Weird function made for call transfers.
Definition at line 2153 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_queue_frame(), ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, and ast_channel::name. Referenced by ast_async_goto().
02154 {
02155 struct ast_frame null = { AST_FRAME_NULL, };
02156 int res = -1;
02157 ast_mutex_lock(&original->lock);
02158 while(ast_mutex_trylock(&clone->lock)) {
02159 ast_mutex_unlock(&original->lock);
02160 usleep(1);
02161 ast_mutex_lock(&original->lock);
02162 }
02163 ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
02164 clone->name, original->name);
02165 if (original->masq) {
02166 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
02167 original->masq->name, original->name);
02168 } else if (clone->masqr) {
02169 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
02170 clone->name, clone->masqr->name);
02171 } else {
02172 original->masq = clone;
02173 clone->masqr = original;
02174 ast_queue_frame(original, &null);
02175 ast_queue_frame(clone, &null);
02176 ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
02177 res = 0;
02178 }
02179 ast_mutex_unlock(&clone->lock);
02180 ast_mutex_unlock(&original->lock);
02181 return res;
02182 }
|
|
||||||||||||||||||||||||
|
Checks the value of an option. Query the value of an option, optionally blocking until a reply is received Works similarly to setoption except only reads the options. |
|
||||||||||||||||||||
|
Registers a channel.
Definition at line 156 of file channel.c. References ast_channel_register_ex(), description(), and type.
00158 {
00159 return ast_channel_register_ex(type, description, capabilities, requester, NULL);
00160 }
|
|
||||||||||||||||||||||||
|
Definition at line 162 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, chanlist::requester, chanlist::type, type, and VERBOSE_PREFIX_2. Referenced by ast_channel_register().
00165 {
00166 struct chanlist *chan, *last=NULL;
00167 if (ast_mutex_lock(&chlock)) {
00168 ast_log(LOG_WARNING, "Unable to lock channel list\n");
00169 return -1;
00170 }
00171 chan = backends;
00172 while (chan) {
00173 if (!strcasecmp(type, chan->type)) {
00174 ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
00175 ast_mutex_unlock(&chlock);
00176 return -1;
00177 }
00178 last = chan;
00179 chan = chan->next;
00180 }
00181 chan = malloc(sizeof(struct chanlist));
00182 if (!chan) {
00183 ast_log(LOG_WARNING, "Out of memory\n");
00184 ast_mutex_unlock(&chlock);
00185 return -1;
00186 }
00187 strncpy(chan->type, type, sizeof(chan->type)-1);
00188 strncpy(chan->description, description, sizeof(chan->description)-1);
00189 chan->capabilities = capabilities;
00190 chan->requester = requester;
00191 chan->devicestate = devicestate;
00192 chan->next = NULL;
00193 if (last)
00194 last->next = chan;
00195 else
00196 backends = chan;
00197 if (option_debug)
00198 ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
00199 else if (option_verbose > 1)
00200 ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
00201 ast_mutex_unlock(&chlock);
00202 return 0;
00203 }
|
|
||||||||||||||||||||
|
Sends HTML on given channel. Send HTML or URL on link. Returns 0 on success or -1 on failure Definition at line 2088 of file channel.c. References ast_channel::pvt, and ast_channel_pvt::send_html.
|
|
||||||||||||
|
Sends a URL on a given link. Send URL on link. Returns 0 on success or -1 on failure Definition at line 2095 of file channel.c. References ast_channel::pvt, and ast_channel_pvt::send_html.
|
|
||||||||||||||||||||||||
|
Sets an option on a channel.
Definition at line 2729 of file channel.c. References ast_log(), LOG_ERROR, ast_channel::pvt, and ast_channel_pvt::setoption.
02730 {
02731 int res;
02732 if (chan->pvt->setoption) {
02733 res = chan->pvt->setoption(chan, option, data, datalen);
02734 if (res < 0)
02735 return res;
02736 } else {
02737 errno = ENOSYS;
02738 return -1;
02739 }
02740 if (block) {
02741 /* XXX Implement blocking -- just wait for our option frame reply, discarding
02742 intermediate packets. XXX */
02743 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
02744 return -1;
02745 }
02746 return 0;
02747 }
|
|
||||||||||||
|
Set when to hang a channel up.
Definition at line 144 of file channel.c. References ast_channel::whentohangup.
00145 {
00146 time_t myt;
00147
00148 time(&myt);
00149 if (offset)
00150 chan->whentohangup = myt + offset;
00151 else
00152 chan->whentohangup = 0;
00153 return;
00154 }
|
|
|
Checks for HTML support on a channel. Returns 0 if channel does not support HTML or non-zero if it does Definition at line 2081 of file channel.c. References ast_channel::pvt, and ast_channel_pvt::send_html.
|
|
|
Undeos a defer. Undo defer. ast_read will return any dtmf characters that were queued Definition at line 451 of file channel.c. References ast_channel::deferdtmf.
00452 {
00453 if (chan)
00454 chan->deferdtmf = 0;
00455 }
|
|
|
Unregister a channel class.
Definition at line 756 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), backends, free, LOG_DEBUG, LOG_WARNING, chanlist::next, chanlist::type, type, and VERBOSE_PREFIX_2.
00757 {
00758 struct chanlist *chan, *last=NULL;
00759 if (option_debug)
00760 ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type);
00761 if (ast_mutex_lock(&chlock)) {
00762 ast_log(LOG_WARNING, "Unable to lock channel list\n");
00763 return;
00764 }
00765 if (option_verbose > 1)
00766 ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type);
00767
00768 chan = backends;
00769 while(chan) {
00770 if (!strcasecmp(chan->type, type)) {
00771 if (last)
00772 last->next = chan->next;
00773 else
00774 backends = backends->next;
00775 free(chan);
00776 ast_mutex_unlock(&chlock);
00777 return;
00778 }
00779 last = chan;
00780 chan = chan->next;
00781 }
00782 ast_mutex_unlock(&chlock);
00783 }
|
|
|
Browse channels in use.
Definition at line 457 of file channel.c. References ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, 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(), and ast_parse_device_state().
00458 {
00459 /* Returns next channel (locked) */
00460 struct ast_channel *l, *ret;
00461 int retries = 0;
00462 retry:
00463 ret=NULL;
00464 ast_mutex_lock(&chlock);
00465 l = channels;
00466 if (!prev) {
00467 if (l) {
00468 if (ast_mutex_trylock(&l->lock)) {
00469 if (retries < 10)
00470 ast_log(LOG_DEBUG, "Avoiding initial deadlock for '%s'\n", l->name);
00471 else
00472 ast_log(LOG_WARNING, "Avoided initial deadlock for '%s', %d retries!\n", l->name, retries);
00473 ast_mutex_unlock(&chlock);
00474 if (retries < 10) {
00475 usleep(1);
00476 retries++;
00477 goto retry;
00478 } else
00479 return NULL;
00480 }
00481 }
00482 ast_mutex_unlock(&chlock);
00483 return l;
00484 }
00485 while(l) {
00486 if (l == prev)
00487 ret = l->next;
00488 l = l->next;
00489 }
00490 if (ret) {
00491 if (ast_mutex_trylock(&ret->lock)) {
00492 if (retries < 10)
00493 ast_log(LOG_DEBUG, "Avoiding deadlock for '%s'\n", ret->name);
00494 else
00495 ast_log(LOG_WARNING, "Avoided deadlock for '%s', %d retries!\n", ret->name, retries);
00496 ast_mutex_unlock(&chlock);
00497 if (retries < 10) {
00498 usleep(1);
00499 retries++;
00500 goto retry;
00501 } else
00502 return NULL;
00503 }
00504 }
00505 ast_mutex_unlock(&chlock);
00506 return ret;
00507
00508 }
|
|
|
Check to see if a channel is needing hang up.
Definition at line 79 of file channel.c. References ast_channel::_softhangup, AST_SOFTHANGUP_TIMEOUT, ast_channel_pvt::pvt, ast_channel::pvt, and ast_channel::whentohangup. Referenced by ast_answer(), ast_call(), ast_channel_bridge(), ast_indicate(), ast_read(), ast_readstring(), ast_readstring_full(), ast_recvchar(), ast_rtp_bridge(), ast_sendtext(), ast_transfer(), ast_waitfordigit(), ast_waitfordigit_full(), and ast_write().
00080 {
00081 time_t myt;
00082
00083 /* if soft hangup flag, return true */
00084 if (chan->_softhangup) return 1;
00085 /* if no private structure, return true */
00086 if (!chan->pvt->pvt) return 1;
00087 /* if no hangup scheduled, just return here */
00088 if (!chan->whentohangup) return 0;
00089 time(&myt); /* get current time */
00090 /* return, if not yet */
00091 if (chan->whentohangup > myt) return 0;
00092 chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
00093 return 1;
00094 }
|
|
|
Deactive an active generator Definition at line 816 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, ast_settimeout(), ast_channel::generator, ast_channel::generatordata, ast_channel::lock, ast_generator::release, and ast_channel::writeinterrupt. Referenced by ast_openstream(), ast_playtones_stop(), ast_read(), ast_tonepair_stop(), and ast_write().
00817 {
00818 ast_mutex_lock(&chan->lock);
00819 if (chan->generatordata) {
00820 if (chan->generator && chan->generator->release)
00821 chan->generator->release(chan, chan->generatordata);
00822 chan->generatordata = NULL;
00823 chan->generator = NULL;
00824 chan->writeinterrupt = 0;
00825 ast_settimeout(chan, 0, NULL, NULL);
00826 }
00827 ast_mutex_unlock(&chan->lock);
00828 }
|
|
|
Asks a channel for device state.
Definition at line 1926 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.
01927 {
01928 char tech[AST_MAX_EXTENSION] = "";
01929 char *number;
01930 struct chanlist *chanls;
01931 int res = 0;
01932
01933 strncpy(tech, device, sizeof(tech)-1);
01934 number = strchr(tech, '/');
01935 if (!number) {
01936 return AST_DEVICE_INVALID;
01937 }
01938 *number = 0;
01939 number++;
01940
01941 if (ast_mutex_lock(&chlock)) {
01942 ast_log(LOG_WARNING, "Unable to lock channel list\n");
01943 return -1;
01944 }
01945 chanls = backends;
01946 while(chanls) {
01947 if (!strcasecmp(tech, chanls->type)) {
01948 ast_mutex_unlock(&chlock);
01949 if (!chanls->devicestate)
01950 return ast_parse_device_state(device);
01951 else {
01952 res = chanls->devicestate(number);
01953 if (res == AST_DEVICE_UNKNOWN)
01954 return ast_parse_device_state(device);
01955 else
01956 return res;
01957 }
01958 }
01959 chanls = chanls->next;
01960 }
01961 ast_mutex_unlock(&chlock);
01962 return AST_DEVICE_INVALID;
01963 }
|
|
|
Definition at line 2192 of file channel.c. References ast_channel::_softhangup, ast_channel::_state, ast_channel::adsicpe, ast_channel_pvt::alertpipe, ast_channel_free(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, ast_set_read_format(), ast_set_write_format(), AST_SOFTHANGUP_DEV, ast_channel::blocker, ast_channel::blocking, ast_channel::callerid, ast_channel::dnid, EVENT_FLAG_CALL, ast_channel::exception, ast_channel::fdno, ast_channel::fds, ast_channel_pvt::fixup, ast_channel_pvt::hangup, ast_channel::lock, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_channel::nativeformats, ast_frame::next, ast_channel::pvt, ast_channel::readformat, ast_channel_pvt::readq, ast_channel::timingfd, ast_channel::type, ast_channel::uniqueid, ast_channel::writeformat, and ast_channel::zombie. Referenced by ast_async_goto(), ast_hangup(), ast_read(), ast_waitfor_nandfds(), and ast_write().
02193 {
02194 int x,i;
02195 int res=0;
02196 int origstate;
02197 char *tmp;
02198 struct ast_var_t *varptr;
02199 struct ast_frame *cur, *prev;
02200 struct ast_channel_pvt *p;
02201 struct ast_channel *clone = original->masq;
02202 int rformat = original->readformat;
02203 int wformat = original->writeformat;
02204 char newn[100];
02205 char orig[100];
02206 char masqn[100];
02207 char zombn[100];
02208
02209 #if 1
02210 ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
02211 clone->name, clone->_state, original->name, original->_state);
02212 #endif
02213 /* XXX This is a seriously wacked out operation. We're essentially putting the guts of
02214 the clone channel into the original channel. Start by killing off the original
02215 channel's backend. I'm not sure we're going to keep this function, because
02216 while the features are nice, the cost is very high in terms of pure nastiness. XXX */
02217
02218 /* We need the clone's lock, too */
02219 ast_mutex_lock(&clone->lock);
02220
02221 ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock);
02222
02223 /* Having remembered the original read/write formats, we turn off any translation on either
02224 one */
02225 free_translation(clone);
02226 free_translation(original);
02227
02228
02229 /* Unlink the masquerade */
02230 original->masq = NULL;
02231 clone->masqr = NULL;
02232
02233 /* Save the original name */
02234 strncpy(orig, original->name, sizeof(orig) - 1);
02235 /* Save the new name */
02236 strncpy(newn, clone->name, sizeof(newn) - 1);
02237 /* Create the masq name */
02238 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn);
02239
02240 /* Copy the name from the clone channel */
02241 strncpy(original->name, newn, sizeof(original->name)-1);
02242
02243 /* Mangle the name of the clone channel */
02244 strncpy(clone->name, masqn, sizeof(clone->name) - 1);
02245
02246 /* Notify any managers of the change, first the masq then the other */
02247 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
02248 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
02249
02250 /* Swap the guts */
02251 p = original->pvt;
02252 original->pvt = clone->pvt;
02253 clone->pvt = p;
02254
02255 /* Save any pending frames on both sides. Start by counting
02256 * how many we're going to need... */
02257 prev = NULL;
02258 cur = clone->pvt->readq;
02259 x = 0;
02260 while(cur) {
02261 x++;
02262 prev = cur;
02263 cur = cur->next;
02264 }
02265 /* If we had any, prepend them to the ones already in the queue, and
02266 * load up the alertpipe */
02267 if (prev) {
02268 prev->next = original->pvt->readq;
02269 original->pvt->readq = clone->pvt->readq;
02270 clone->pvt->readq = NULL;
02271 if (original->pvt->alertpipe[1] > -1) {
02272 for (i=0;i<x;i++)
02273 write(original->pvt->alertpipe[1], &x, sizeof(x));
02274 }
02275 }
02276 clone->_softhangup = AST_SOFTHANGUP_DEV;
02277
02278
02279 /* And of course, so does our current state. Note we need not
02280 call ast_setstate since the event manager doesn't really consider
02281 these separate. We do this early so that the clone has the proper
02282 state of the original channel. */
02283 origstate = original->_state;
02284 original->_state = clone->_state;
02285 clone->_state = origstate;
02286
02287 if (clone->pvt->fixup){
02288 res = clone->pvt->fixup(original, clone);
02289 if (res)
02290 ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
02291 }
02292
02293 /* Start by disconnecting the original's physical side */
02294 if (clone->pvt->hangup)
02295 res = clone->pvt->hangup(clone);
02296 if (res) {
02297 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n");
02298 ast_mutex_unlock(&clone->lock);
02299 return -1;
02300 }
02301
02302 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig);
02303 /* Mangle the name of the clone channel */
02304 strncpy(clone->name, zombn, sizeof(clone->name) - 1);
02305 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid);
02306
02307 /* Keep the same language. */
02308 /* Update the type. */
02309 original->type = clone->type;
02310 /* Copy the FD's */
02311 for (x=0;x<AST_MAX_FDS;x++) {
02312 original->fds[x] = clone->fds[x];
02313 }
02314 /* Append variables from clone channel into original channel */
02315 /* XXX Is this always correct? We have to in order to keep MACROS working XXX */
02316 varptr = original->varshead.first;
02317 if (varptr) {
02318 while(varptr->entries.next) {
02319 varptr = varptr->entries.next;
02320 }
02321 varptr->entries.next = clone->varshead.first;
02322 } else {
02323 original->varshead.first = clone->varshead.first;
02324 }
02325 clone->varshead.first = NULL;
02326 /* Presense of ADSI capable CPE follows clone */
02327 original->adsicpe = clone->adsicpe;
02328 /* Bridge remains the same */
02329 /* CDR fields remain the same */
02330 /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */
02331 /* Application and data remain the same */
02332 /* Clone exception becomes real one, as with fdno */
02333 original->exception = clone->exception;
02334 original->fdno = clone->fdno;
02335 /* Schedule context remains the same */
02336 /* Stream stuff stays the same */
02337 /* Keep the original state. The fixup code will need to work with it most likely */
02338
02339 /* dnid and callerid change to become the new, HOWEVER, we also link the original's
02340 fields back into the defunct 'clone' so that they will be freed when
02341 ast_frfree is eventually called */
02342 tmp = original->dnid;
02343 original->dnid = clone->dnid;
02344 clone->dnid = tmp;
02345
02346 tmp = original->callerid;
02347 original->callerid = clone->callerid;
02348 clone->callerid = tmp;
02349
02350 /* Restore original timing file descriptor */
02351 original->fds[AST_MAX_FDS - 2] = original->timingfd;
02352
02353 /* Our native formats are different now */
02354 original->nativeformats = clone->nativeformats;
02355
02356 /* Context, extension, priority, app data, jump table, remain the same */
02357 /* pvt switches. pbx stays the same, as does next */
02358
02359 /* Set the write format */
02360 ast_set_write_format(original, wformat);
02361
02362 /* Set the read format */
02363 ast_set_read_format(original, rformat);
02364
02365 ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat);
02366
02367 /* Okay. Last thing is to let the channel driver know about all this mess, so he
02368 can fix up everything as best as possible */
02369 if (original->pvt->fixup) {
02370 res = original->pvt->fixup(clone, original);
02371 if (res) {
02372 ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n",
02373 original->type, original->name);
02374 ast_mutex_unlock(&clone->lock);
02375 return -1;
02376 }
02377 } else
02378 ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)! Bad things may happen.\n",
02379 original->type, original->name);
02380
02381 /* Now, at this point, the "clone" channel is totally F'd up. We mark it as
02382 a zombie so nothing tries to touch it. If it's already been marked as a
02383 zombie, then free it now (since it already is considered invalid). */
02384 if (clone->zombie) {
02385 ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name);
02386 ast_mutex_unlock(&clone->lock);
02387 ast_channel_free(clone);
02388 manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
02389 } else {
02390 ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name);
02391 clone->zombie=1;
02392 ast_mutex_unlock(&clone->lock);
02393 }
02394
02395 /* Signal any blocker */
02396 if (original->blocking)
02397 pthread_kill(original->blocker, SIGURG);
02398 ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n",
02399 original->name, original->_state);
02400 return 0;
02401 }
|
|
|
Get channel by name (locks channel).
Definition at line 510 of file channel.c. References ast_channel_walk_locked(), ast_mutex_unlock, ast_channel::lock, and ast_channel::name.
00511 {
00512 struct ast_channel *chan;
00513 chan = ast_channel_walk_locked(NULL);
00514 while(chan) {
00515 if (!strcasecmp(chan->name, channame))
00516 return chan;
00517 ast_mutex_unlock(&chan->lock);
00518 chan = ast_channel_walk_locked(chan);
00519 }
00520 return NULL;
00521 }
|
|
|
Definition at line 2881 of file channel.c. References ast_log(), LOG_ERROR, LOG_WARNING, and s.
02882 {
02883 char *copy;
02884 char *piece;
02885 char *c=NULL;
02886 int start=0, finish=0,x;
02887 unsigned int group = 0;
02888 copy = ast_strdupa(s);
02889 if (!copy) {
02890 ast_log(LOG_ERROR, "Out of memory\n");
02891 return 0;
02892 }
02893 c = copy;
02894
02895 while((piece = strsep(&c, ","))) {
02896 if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
02897 /* Range */
02898 } else if (sscanf(piece, "%d", &start)) {
02899 /* Just one */
02900 finish = start;
02901 } else {
02902 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'. Using '0'\n", s,piece);
02903 return 0;
02904 }
02905 for (x=start;x<=finish;x++) {
02906 if ((x > 31) || (x < 0)) {
02907 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x);
02908 } else
02909 group |= (1 << x);
02910 }
02911 }
02912 return group;
02913 }
|
|
|
Hang up a channel.
Definition at line 689 of file channel.c. References ast_cdr_end(), ast_cdr_free(), ast_cdr_post(), ast_channel_free(), ast_closestream(), ast_do_masquerade(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_channel::blocker, ast_channel::blocking, ast_channel::blockproc, ast_channel::cdr, CRASH, EVENT_FLAG_CALL, ast_channel::generator, ast_channel::generatordata, ast_channel_pvt::hangup, ast_channel::hangupcause, ast_channel::lock, LOG_DEBUG, LOG_WARNING, manager_event(), ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_channel::pvt, ast_generator::release, ast_channel::sched, sched_context_destroy(), ast_channel::stream, ast_channel::uniqueid, ast_channel::vstream, and ast_channel::zombie. Referenced by __ast_request_and_dial(), ast_async_goto(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), and ast_pbx_run().
00690 {
00691 int res = 0;
00692 /* Don't actually hang up a channel that will masquerade as someone else, or
00693 if someone is going to masquerade as us */
00694 ast_mutex_lock(&chan->lock);
00695 if (chan->masq) {
00696 if (ast_do_masquerade(chan))
00697 ast_log(LOG_WARNING, "Failed to perform masquerade\n");
00698 }
00699
00700 if (chan->masq) {
00701 ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
00702 ast_mutex_unlock(&chan->lock);
00703 return 0;
00704 }
00705 /* If this channel is one which will be masqueraded into something,
00706 mark it as a zombie already, so we know to free it later */
00707 if (chan->masqr) {
00708 chan->zombie=1;
00709 ast_mutex_unlock(&chan->lock);
00710 return 0;
00711 }
00712 free_translation(chan);
00713 if (chan->stream)
00714 ast_closestream(chan->stream);
00715 if (chan->vstream)
00716 ast_closestream(chan->vstream);
00717 if (chan->sched)
00718 sched_context_destroy(chan->sched);
00719 /* Clear any tone stuff remaining */
00720 if (chan->generatordata)
00721 chan->generator->release(chan, chan->generatordata);
00722 chan->generatordata = NULL;
00723 chan->generator = NULL;
00724 if (chan->cdr) {
00725 /* End the CDR if it hasn't already */
00726 ast_cdr_end(chan->cdr);
00727 /* Post and Free the CDR */
00728 ast_cdr_post(chan->cdr);
00729 ast_cdr_free(chan->cdr);
00730 }
00731 if (chan->blocking) {
00732 ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
00733 "is blocked by thread %ld in procedure %s! Expect a failure\n",
00734 (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc);
00735 CRASH;
00736 }
00737 if (!chan->zombie) {
00738 if (option_debug)
00739 ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
00740 if (chan->pvt->hangup)
00741 res = chan->pvt->hangup(chan);
00742 } else
00743 if (option_debug)
00744 ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
00745
00746 ast_mutex_unlock(&chan->lock);
00747 manager_event(EVENT_FLAG_CALL, "Hangup",
00748 "Channel: %s\r\n"
00749 "Uniqueid: %s\r\n"
00750 "Cause: %i\r\n",
00751 chan->name, chan->uniqueid, chan->hangupcause);
00752 ast_channel_free(chan);
00753 return res;
00754 }
|
|
||||||||||||
|
Indicates condition of channel.
Definition at line 1407 of file channel.c. References ast_check_hangup(), ast_get_indication_tone(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_playtones_start(), ast_playtones_stop(), tone_zone_sound::data, ast_channel_pvt::indicate, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel::pvt, ast_channel::zombie, and ast_channel::zone.
01408 {
01409 int res = -1;
01410 /* Stop if we're a zombie or need a soft hangup */
01411 if (chan->zombie || ast_check_hangup(chan))
01412 return -1;
01413 ast_mutex_lock(&chan->lock);
01414 if (chan->pvt->indicate)
01415 res = chan->pvt->indicate(chan, condition);
01416 ast_mutex_unlock(&chan->lock);
01417 if (!chan->pvt->indicate || res) {
01418 /*
01419 * Device does not support (that) indication, lets fake
01420 * it by doing our own tone generation. (PM2002)
01421 */
01422 if (condition >= 0) {
01423 const struct tone_zone_sound *ts = NULL;
01424 switch (condition) {
01425 case AST_CONTROL_RINGING:
01426 ts = ast_get_indication_tone(chan->zone, "ring");
01427 break;
01428 case AST_CONTROL_BUSY:
01429 ts = ast_get_indication_tone(chan->zone, "busy");
01430 break;
01431 case AST_CONTROL_CONGESTION:
01432 ts = ast_get_indication_tone(chan->zone, "congestion");
01433 break;
01434 }
01435 if (ts && ts->data[0]) {
01436 ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
01437 ast_playtones_start(chan,0,ts->data, 1);
01438 res = 0;
01439 } else if (condition == AST_CONTROL_PROGRESS) {
01440 /* ast_playtones_stop(chan); */
01441 } else if (condition == AST_CONTROL_PROCEEDING) {
01442 /* Do nothing, really */
01443 } else {
01444 /* not handled */
01445 ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
01446 res = -1;
01447 }
01448 }
01449 else ast_playtones_stop(chan);
01450 }
01451 return res;
01452 }
|
|
|
Search the Channels by Name.
Definition at line 1906 of file channel.c. References AST_CHANNEL_NAME, ast_channel_walk_locked(), AST_DEVICE_INUSE, AST_DEVICE_UNKNOWN, ast_mutex_unlock, ast_channel::lock, and ast_channel::name. Referenced by ast_device_state().
01907 {
01908 char name[AST_CHANNEL_NAME] = "";
01909 char *cut;
01910 struct ast_channel *chan;
01911
01912 chan = ast_channel_walk_locked(NULL);
01913 while (chan) {
01914 strncpy(name, chan->name, sizeof(name)-1);
01915 ast_mutex_unlock(&chan->lock);
01916 cut = strchr(name,'-');
01917 if (cut)
01918 *cut = 0;
01919 if (!strcmp(name, device))
01920 return AST_DEVICE_INUSE;
01921 chan = ast_channel_walk_locked(chan);
01922 }
01923 return AST_DEVICE_UNKNOWN;
01924 }
|
|
|
Definition at line 1545 of file channel.c. References ast_channel::_state, ast_log(), AST_STATE_UP, ast_write(), ast_frame::data, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel::pvt, ast_channel_pvt::rawwriteformat, and ast_frame::subclass. Referenced by ast_activate_generator().
01546 {
01547 struct ast_frame a = { AST_FRAME_VOICE };
01548 char nothing[128];
01549 /* Send an empty audio frame to get things moving */
01550 if (chan->_state != AST_STATE_UP) {
01551 ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
01552 a.subclass = chan->pvt->rawwriteformat;
01553 a.data = nothing + AST_FRIENDLY_OFFSET;
01554 if (ast_write(chan, &a))
01555 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name);
01556 }
01557 return 0;
01558 }
|
|
|
Reads a frame.
Definition at line 1189 of file channel.c. References ast_cdr_answer(), ast_cdr_end(), ast_check_hangup(), ast_deactivate_generator(), ast_do_masquerade(), ast_frame_dump(), 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::data, ast_frame::datalen, 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().
01190 {
01191 struct ast_frame *f = NULL;
01192 int blah;
01193 #ifdef ZAPTEL_OPTIMIZATIONS
01194 int (*func)(void *);
01195 void *data;
01196 int res;
01197 #endif
01198 static struct ast_frame null_frame =
01199 {
01200 AST_FRAME_NULL,
01201 };
01202
01203 ast_mutex_lock(&chan->lock);
01204 if (chan->masq) {
01205 if (ast_do_masquerade(chan)) {
01206 ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01207 f = NULL;
01208 } else
01209 f = &null_frame;
01210 ast_mutex_unlock(&chan->lock);
01211 return f;
01212 }
01213
01214 /* Stop if we're a zombie or need a soft hangup */
01215 if (chan->zombie || ast_check_hangup(chan)) {
01216 if (chan->generator)
01217 ast_deactivate_generator(chan);
01218 ast_mutex_unlock(&chan->lock);
01219 return NULL;
01220 }
01221
01222 if (!chan->deferdtmf && !ast_strlen_zero(chan->dtmfq)) {
01223 /* We have DTMF that has been deferred. Return it now */
01224 chan->dtmff.frametype = AST_FRAME_DTMF;
01225 chan->dtmff.subclass = chan->dtmfq[0];
01226 /* Drop first digit */
01227 memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
01228 ast_mutex_unlock(&chan->lock);
01229 return &chan->dtmff;
01230 }
01231
01232 /* Read and ignore anything on the alertpipe, but read only
01233 one sizeof(blah) per frame that we send from it */
01234 if (chan->pvt->alertpipe[0] > -1) {
01235 read(chan->pvt->alertpipe[0], &blah, sizeof(blah));
01236 }
01237 #ifdef ZAPTEL_OPTIMIZATIONS
01238 if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) {
01239 chan->exception = 0;
01240 blah = -1;
01241 /* IF we can't get event, assume it's an expired as-per the old interface */
01242 res = ioctl(chan->timingfd, ZT_GETEVENT, &blah);
01243 if (res)
01244 blah = ZT_EVENT_TIMER_EXPIRED;
01245
01246 if (blah == ZT_EVENT_TIMER_PING) {
01247 #if 0
01248 ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
01249 #endif
01250 if (!chan->pvt->readq || !chan->pvt->readq->next) {
01251 /* Acknowledge PONG unless we need it again */
01252 #if 0
01253 ast_log(LOG_NOTICE, "Sending a PONG!\n");
01254 #endif
01255 if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) {
01256 ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno));
01257 }
01258 }
01259 } else if (blah == ZT_EVENT_TIMER_EXPIRED) {
01260 ioctl(chan->timingfd, ZT_TIMERACK, &blah);
01261 func = chan->timingfunc;
01262 data = chan->timingdata;
01263 ast_mutex_unlock(&chan->lock);
01264 if (func) {
01265 #if 0
01266 ast_log(LOG_DEBUG, "Calling private function\n");
01267 #endif
01268 func(data);
01269 } else {
01270 blah = 0;
01271 ast_mutex_lock(&chan->lock);
01272 ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
01273 chan->timingdata = NULL;
01274 ast_mutex_unlock(&chan->lock);
01275 }
01276 f = &null_frame;
01277 return f;
01278 } else
01279 ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
01280 }
01281 #endif
01282 /* Check for pending read queue */
01283 if (chan->pvt->readq) {
01284 f = chan->pvt->readq;
01285 chan->pvt->readq = f->next;
01286 /* Interpret hangup and return NULL */
01287 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
01288 ast_frfree(f);
01289 f = NULL;
01290 }
01291 } else {
01292 chan->blocker = pthread_self();
01293 if (chan->exception) {
01294 if (chan->pvt->exception)
01295 f = chan->pvt->exception(chan);
01296 else {
01297 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
01298 f = &null_frame;
01299 }
01300 /* Clear the exception flag */
01301 chan->exception = 0;
01302 } else
01303 if (chan->pvt->read)
01304 f = chan->pvt->read(chan);
01305 else
01306 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
01307 }
01308
01309
01310 if (f && (f->frametype == AST_FRAME_VOICE)) {
01311 if (!(f->subclass & chan->nativeformats)) {
01312 /* This frame can't be from the current native formats -- drop it on the
01313 floor */
01314 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));
01315 ast_frfree(f);
01316 f = &null_frame;
01317 } else {
01318 if (chan->monitor && chan->monitor->read_stream ) {
01319 #ifndef MONITOR_CONSTANT_DELAY
01320 int jump = chan->outsmpl - chan->insmpl - 2 * f->samples;
01321 if (jump >= 0) {
01322 if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01323 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01324 chan->insmpl += jump + 2 * f->samples;
01325 } else
01326 chan->insmpl+= f->samples;
01327 #else
01328 int jump = chan->outsmpl - chan->insmpl;
01329 if (jump - MONITOR_DELAY >= 0) {
01330 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01331 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01332 chan->insmpl += jump;
01333 } else
01334 chan->insmpl += f->samples;
01335 #endif
01336 if (ast_writestream(chan->monitor->read_stream, f) < 0)
01337 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
01338 }
01339 if (chan->pvt->readtrans) {
01340 f = ast_translate(chan->pvt->readtrans, f, 1);
01341 if (!f)
01342 f = &null_frame;
01343 }
01344 }
01345 }
01346
01347 /* Make sure we always return NULL in the future */
01348 if (!f) {
01349 chan->_softhangup |= AST_SOFTHANGUP_DEV;
01350 if (chan->generator)
01351 ast_deactivate_generator(chan);
01352 /* End the CDR if appropriate */
01353 if (chan->cdr)
01354 ast_cdr_end(chan->cdr);
01355 } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
01356 if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
01357 chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
01358 else
01359 ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
01360 f = &null_frame;
01361 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
01362 if (chan->_state == AST_STATE_UP) {
01363 ast_log(LOG_DEBUG, "Dropping duplicate answer!\n");
01364 f = &null_frame;
01365 }
01366 /* Answer the CDR */
01367 ast_setstate(chan, AST_STATE_UP);
01368 ast_cdr_answer(chan->cdr);
01369 }
01370
01371 /* Run any generator sitting on the line */
01372 if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
01373 /* Mask generator data temporarily and apply. If there is a timing function, it
01374 will be calling the generator instead */
01375 void *tmp;
01376 int res;
01377 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
01378 if (chan->timingfunc) {
01379 ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
01380 ast_settimeout(chan, 0, NULL, NULL);
01381 }
01382 tmp = chan->generatordata;
01383 chan->generatordata = NULL;
01384 generate = chan->generator->generate;
01385 res = generate(chan, tmp, f->datalen, f->samples);
01386 chan->generatordata = tmp;
01387 if (res) {
01388 ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
01389 ast_deactivate_generator(chan);
01390 }
01391 } else if (f && (f->frametype == AST_FRAME_CNG)) {
01392 if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) {
01393 ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n");
01394 ast_settimeout(chan, 160, generator_force, chan);
01395 }
01396 }
01397 if (chan->fin & 0x80000000)
01398 ast_frame_dump(chan->name, f, "<<");
01399 if ((chan->fin & 0x7fffffff) == 0x7fffffff)
01400 chan->fin &= 0x80000000;
01401 else
01402 chan->fin++;
01403 ast_mutex_unlock(&chan->lock);
01404 return f;
01405 }
|
|
||||||||||||||||||||||||||||
|
Reads multiple digits.
Definition at line 2000 of file channel.c. References ast_check_hangup(), AST_DIGIT_ANY, ast_stopstream(), ast_waitfordigit(), ast_waitstream(), s, ast_channel::stream, and ast_channel::zombie. Referenced by ast_app_getdata().
02001 {
02002 int pos=0;
02003 int to = ftimeout;
02004 char d;
02005 /* XXX Merge with full version? XXX */
02006 /* Stop if we're a zombie or need a soft hangup */
02007 if (c->zombie || ast_check_hangup(c))
02008 return -1;
02009 if (!len)
02010 return -1;
02011 do {
02012 if (c->stream) {
02013 d = ast_waitstream(c, AST_DIGIT_ANY);
02014 ast_stopstream(c);
02015 usleep(1000);
02016 if (!d)
02017 d = ast_waitfordigit(c, to);
02018 } else {
02019 d = ast_waitfordigit(c, to);
02020 }
02021 if (d < 0)
02022 return -1;
02023 if (d == 0) {
02024 s[pos]='\0';
02025 return 1;
02026 }
02027 if (!strchr(enders, d))
02028 s[pos++] = d;
02029 if (strchr(enders, d) || (pos >= len)) {
02030 s[pos]='\0';
02031 return 0;
02032 }
02033 to = timeout;
02034 } while(1);
02035 /* Never reached */
02036 return 0;
02037 }
|
|
||||||||||||||||||||||||||||||||||||
|
Definition at line 2039 of file channel.c. References ast_check_hangup(), AST_DIGIT_ANY, ast_stopstream(), ast_waitfordigit_full(), ast_waitstream_full(), s, ast_channel::stream, and ast_channel::zombie. Referenced by ast_app_getdata_full().
02040 {
02041 int pos=0;
02042 int to = ftimeout;
02043 char d;
02044 /* Stop if we're a zombie or need a soft hangup */
02045 if (c->zombie || ast_check_hangup(c))
02046 return -1;
02047 if (!len)
02048 return -1;
02049 do {
02050 if (c->stream) {
02051 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
02052 ast_stopstream(c);
02053 usleep(1000);
02054 if (!d)
02055 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02056 } else {
02057 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02058 }
02059 if (d < 0)
02060 return -1;
02061 if (d == 0) {
02062 s[pos]='\0';
02063 return 1;
02064 }
02065 if (d == 1) {
02066 s[pos]='\0';
02067 return 2;
02068 }
02069 if (!strchr(enders, d))
02070 s[pos++] = d;
02071 if (strchr(enders, d) || (pos >= len)) {
02072 s[pos]='\0';
02073 return 0;
02074 }
02075 to = timeout;
02076 } while(1);
02077 /* Never reached */
02078 return 0;
02079 }
|
|
||||||||||||
|
Definition at line 1454 of file channel.c. References ast_check_hangup(), ast_frfree(), ast_read(), ast_waitfor(), ast_frame::data, ast_frame::frametype, ast_frame::subclass, and timeout.
01455 {
01456 int res,ourto,c;
01457 struct ast_frame *f;
01458
01459 ourto = timeout;
01460 for(;;)
01461 {
01462 if (ast_check_hangup(chan)) return -1;
01463 res = ast_waitfor(chan,ourto);
01464 if (res <= 0) /* if timeout */
01465 {
01466 return 0;
01467 }
01468 ourto = res;
01469 f = ast_read(chan);
01470 if (f == NULL) return -1; /* if hangup */
01471 if ((f->frametype == AST_FRAME_CONTROL) &&
01472 (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
01473 if (f->frametype == AST_FRAME_TEXT) /* if a text frame */
01474 {
01475 c = *((char *)f->data); /* get the data */
01476 ast_frfree(f);
01477 return(c);
01478 }
01479 ast_frfree(f);
01480 }
01481 }
|
|
||||||||||||||||
|
Requests a channel.
Definition at line 1861 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, chanlist::type, and ast_channel::uniqueid. Referenced by __ast_request_and_dial().
01862 {
01863 struct chanlist *chan;
01864 struct ast_channel *c = NULL;
01865 int capabilities;
01866 int fmt;
01867 int res;
01868 if (ast_mutex_lock(&chlock)) {
01869 ast_log(LOG_WARNING, "Unable to lock channel list\n");
01870 return NULL;
01871 }
01872 chan = backends;
01873 while(chan) {
01874 if (!strcasecmp(type, chan->type)) {
01875 capabilities = chan->capabilities;
01876 fmt = format;
01877 res = ast_translator_best_choice(&fmt, &capabilities);
01878 if (res < 0) {
01879 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
01880 ast_mutex_unlock(&chlock);
01881 return NULL;
01882 }
01883 ast_mutex_unlock(&chlock);
01884 if (chan->requester)
01885 c = chan->requester(type, capabilities, data);
01886 if (c) {
01887 if (c->_state == AST_STATE_DOWN) {
01888 manager_event(EVENT_FLAG_CALL, "Newchannel",
01889 "Channel: %s\r\n"
01890 "State: %s\r\n"
01891 "Callerid: %s\r\n"
01892 "Uniqueid: %s\r\n",
01893 c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid);
01894 }
01895 }
01896 return c;
01897 }
01898 chan = chan->next;
01899 }
01900 if (!chan)
01901 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
01902 ast_mutex_unlock(&chlock);
01903 return c;
01904 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 1856 of file channel.c. References __ast_request_and_dial(). Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
01857 {
01858 return __ast_request_and_dial(type, format, data, timeout, outstate, callerid, NULL);
01859 }
|
|
||||||||||||
|
Wait for a specied amount of time, looking for hangups.
Definition at line 544 of file channel.c. References ast_frfree(), ast_read(), and ast_waitfor(). Referenced by ast_dtmf_stream().
00545 {
00546 struct ast_frame *f;
00547 while(ms > 0) {
00548 ms = ast_waitfor(chan, ms);
00549 if (ms <0)
00550 return -1;
00551 if (ms > 0) {
00552 f = ast_read(chan);
00553 if (!f)
00554 return -1;
00555 ast_frfree(f);
00556 }
00557 }
00558 return 0;
00559 }
|
|
||||||||||||||||||||
|
Wait for a specied amount of time, looking for hangups and a condition argument.
Definition at line 523 of file channel.c. References ast_frfree(), ast_read(), and ast_waitfor().
00525 {
00526 struct ast_frame *f;
00527
00528 while(ms > 0) {
00529 if( cond && ((*cond)(data) == 0 ) )
00530 return 0;
00531 ms = ast_waitfor(chan, ms);
00532 if (ms <0)
00533 return -1;
00534 if (ms > 0) {
00535 f = ast_read(chan);
00536 if (!f)
00537 return -1;
00538 ast_frfree(f);
00539 }
00540 }
00541 return 0;
00542 }
|
|
||||||||||||
|
Receives a text character from a channel.
Definition at line 1540 of file channel.c.
01541 {
01542 return do_senddigit(chan, digit);
01543 }
|
|
||||||||||||
|
Sends text to a channel.
Definition at line 1483 of file channel.c. References ast_check_hangup(), ast_channel::blocking, CHECK_BLOCKING, ast_channel::pvt, ast_channel_pvt::send_text, and ast_channel::zombie.
01484 {
01485 int res = 0;
01486 /* Stop if we're a zombie or need a soft hangup */
01487 if (chan->zombie || ast_check_hangup(chan))
01488 return -1;
01489 CHECK_BLOCKING(chan);
01490 if (chan->pvt->send_text)
01491 res = chan->pvt->send_text(chan, text);
01492 chan->blocking = 0;
01493 return res;
01494 }
|
|
||||||||||||||||
|
Definition at line 2403 of file channel.c. References ast_channel::ani, ast_cdr_setcid(), ast_channel::callerid, ast_channel::cdr, EVENT_FLAG_CALL, free, manager_event(), ast_channel::name, strdup, and ast_channel::uniqueid. Referenced by __ast_request_and_dial().
02404 {
02405 if (chan->callerid)
02406 free(chan->callerid);
02407 if (anitoo && chan->ani)
02408 free(chan->ani);
02409 if (callerid) {
02410 chan->callerid = strdup(callerid);
02411 if (anitoo)
02412 chan->ani = strdup(callerid);
02413 } else {
02414 chan->callerid = NULL;
02415 if (anitoo)
02416 chan->ani = NULL;
02417 }
02418 if (chan->cdr)
02419 ast_cdr_setcid(chan->cdr, chan);
02420 manager_event(EVENT_FLAG_CALL, "Newcallerid",
02421 "Channel: %s\r\n"
02422 "Callerid: %s\r\n"
02423 "Uniqueid: %s\r\n",
02424 chan->name, chan->callerid ?
02425 chan->callerid : "<Unknown>",
02426 chan->uniqueid);
02427 }
|
|
||||||||||||
|
Sets read 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(), ast_channel::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::name, ast_channel::nativeformats, ast_channel::pvt, ast_channel_pvt::rawreadformat, ast_channel::readformat, and ast_channel_pvt::readtrans. Referenced by ast_app_getvoice(), ast_channel_make_compatible(), ast_do_masquerade(), ast_play_and_prepend(), and ast_play_and_record().
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 /* Find a translation path from the native read format to one of the user's read formats */
01722 res = ast_translator_best_choice(&fmt, &native);
01723 if (res < 0) {
01724 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01725 ast_getformatname(chan->nativeformats), ast_getformatname(fmts));
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->rawreadformat = native;
01732 /* User perspective is fmt */
01733 chan->readformat = fmt;
01734 /* Free any read translation we have right now */
01735 if (chan->pvt->readtrans)
01736 ast_translator_free_path(chan->pvt->readtrans);
01737 /* Build a translation path from the raw read format to the user reading format */
01738 chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
01739 if (option_debug)
01740 ast_log(LOG_DEBUG, "Set channel %s to read format %s\n",
01741 chan->name, ast_getformatname(chan->readformat));
01742 ast_mutex_unlock(&chan->lock);
01743 return 0;
01744 }
|
|
||||||||||||
|
Sets write format on channel chan.
Definition at line 1679 of file channel.c. References ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), ast_channel::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::name, ast_channel::nativeformats, ast_channel::pvt, ast_channel_pvt::rawwriteformat, ast_channel::writeformat, and ast_channel_pvt::writetrans. Referenced by ast_channel_make_compatible(), ast_do_masquerade(), ast_openstream(), and ast_stopstream().
01680 {
01681 int fmt;
01682 int native;
01683 int res;
01684
01685 ast_mutex_lock(&chan->lock);
01686 native = chan->nativeformats;
01687 fmt = fmts;
01688
01689 res = ast_translator_best_choice(&native, &fmt);
01690 if (res < 0) {
01691 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01692 ast_getformatname(fmts), ast_getformatname(chan->nativeformats));
01693 ast_mutex_unlock(&chan->lock);
01694 return -1;
01695 }
01696
01697 /* Now we have a good choice for both. We'll write using our native format. */
01698 chan->pvt->rawwriteformat = native;
01699 /* User perspective is fmt */
01700 chan->writeformat = fmt;
01701 /* Free any write translation we have right now */
01702 if (chan->pvt->writetrans)
01703 ast_translator_free_path(chan->pvt->writetrans);
01704 /* Build a translation path from the user write format to the raw writing format */
01705 chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
01706 if (option_debug)
01707 ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat));
01708 ast_mutex_unlock(&chan->lock);
01709 return 0;
01710 }
|
|
||||||||||||||||||||
|
Definition at line 1119 of file channel.c. References ast_log(), LOG_DEBUG, ast_channel::timingdata, ast_channel::timingfd, and ast_channel::timingfunc. Referenced by ast_activate_generator(), ast_closestream(), ast_deactivate_generator(), and ast_read().
01120 {
01121 int res = -1;
01122 #ifdef ZAPTEL_OPTIMIZATIONS
01123 if (c->timingfd > -1) {
01124 if (!func) {
01125 samples = 0;
01126 data = 0;
01127 }
01128 ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples);
01129 res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples);
01130 c->timingfunc = func;
01131 c->timingdata = data;
01132 }
01133 #endif
01134 return res;
01135 }
|
|
|
Returns non-zero if Asterisk is being shut down Definition at line 139 of file channel.c.
00140 {
00141 return shutting_down;
00142 }
|
|
||||||||||||
|
Softly hangup up a channel.
Definition at line 668 of file channel.c. References ast_mutex_lock, ast_mutex_unlock, ast_softhangup_nolock(), and ast_channel::lock. Referenced by ast_begin_shutdown().
00669 {
00670 int res;
00671 ast_mutex_lock(&chan->lock);
00672 res = ast_softhangup_nolock(chan, cause);
00673 ast_mutex_unlock(&chan->lock);
00674 return res;
00675 }
|
|
||||||||||||
|
Definition at line 653 of file channel.c. References ast_channel::_softhangup, ast_log(), ast_queue_frame(), ast_channel::blocker, ast_channel::blocking, LOG_DEBUG, and ast_channel::name. Referenced by ast_async_goto(), and ast_softhangup().
00654 {
00655 int res = 0;
00656 struct ast_frame f = { AST_FRAME_NULL };
00657 if (option_debug)
00658 ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name);
00659 /* Inform channel driver that we need to be hung up, if it cares */
00660 chan->_softhangup |= cause;
00661 ast_queue_frame(chan, &f);
00662 /* Interrupt any poll call or such */
00663 if (chan->blocking)
00664 pthread_kill(chan->blocker, SIGURG);
00665 return res;
00666 }
|
|
|
Gives the string form of a given state.
Definition at line 205 of file channel.c. References AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_OFFHOOK, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, and AST_STATE_UP. Referenced by ast_request(), and ast_setstate().
00206 {
00207 /* XXX Not reentrant XXX */
00208 static char localtmp[256];
00209 switch(state) {
00210 case AST_STATE_DOWN:
00211 return "Down";
00212 case AST_STATE_RESERVED:
00213 return "Rsrvd";
00214 case AST_STATE_OFFHOOK:
00215 return "OffHook";
00216 case AST_STATE_DIALING:
00217 return "Dialing";
00218 case AST_STATE_RING:
00219 return "Ring";
00220 case AST_STATE_RINGING:
00221 return "Ringing";
00222 case AST_STATE_UP:
00223 return "Up";
00224 case AST_STATE_BUSY:
00225 return "Busy";
00226 default:
00227 snprintf(localtmp, sizeof(localtmp), "Unknown (%d)\n", state);
00228 return localtmp;
00229 }
00230 }
|
|
||||||||||||||||||||||||
|
Play a tone pair for a given amount of time Definition at line 2863 of file channel.c. References ast_frfree(), ast_read(), ast_tonepair_start(), ast_waitfor(), and ast_channel::generatordata.
02864 {
02865 struct ast_frame *f;
02866 int res;
02867 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
02868 return res;
02869
02870 /* Give us some wiggle room */
02871 while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
02872 f = ast_read(chan);
02873 if (f)
02874 ast_frfree(f);
02875 else
02876 return -1;
02877 }
02878 return 0;
02879 }
|
|
||||||||||||||||||||||||
|
Start a tone going Definition at line 2843 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().
02844 {
02845 struct tonepair_def d = { 0, };
02846 d.freq1 = freq1;
02847 d.freq2 = freq2;
02848 d.duration = duration;
02849 if (vol < 1)
02850 d.vol = 8192;
02851 else
02852 d.vol = vol;
02853 if (ast_activate_generator(chan, &tonepair, &d))
02854 return -1;
02855 return 0;
02856 }
|
|
|
Stop a tone from playing Definition at line 2858 of file channel.c. References ast_deactivate_generator().
02859 {
02860 ast_deactivate_generator(chan);
02861 }
|
|
||||||||||||
|
Definition at line 1980 of file channel.c. References ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_channel::lock, ast_channel::pvt, ast_channel_pvt::transfer, and ast_channel::zombie.
01981 {
01982 /* Place an outgoing call, but don't wait any longer than timeout ms before returning.
01983 If the remote end does not answer within the timeout, then do NOT hang up, but
01984 return anyway. */
01985 int res = -1;
01986 /* Stop if we're a zombie or need a soft hangup */
01987 ast_mutex_lock(&chan->lock);
01988 if (!chan->zombie && !ast_check_hangup(chan)) {
01989 if (chan->pvt->transfer) {
01990 res = chan->pvt->transfer(chan, dest);
01991 if (!res)
01992 res = 1;
01993 } else
01994 res = 0;
01995 }
01996 ast_mutex_unlock(&chan->lock);
01997 return res;
01998 }
|
|
||||||||||||
|
Wait for input on a channel.
Definition at line 1078 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().
01079 {
01080 struct ast_channel *chan;
01081 int oldms = ms;
01082 chan = ast_waitfor_n(&c, 1, &ms);
01083 if (ms < 0) {
01084 if (oldms < 0)
01085 return 0;
01086 else
01087 return -1;
01088 }
01089 return ms;
01090 }
|
|
||||||||||||||||
|
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 1073 of file channel.c. References ast_waitfor_nandfds(). Referenced by ast_channel_bridge(), ast_rtp_bridge(), and ast_waitfor().
01074 {
01075 return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
01076 }
|
|
||||||||||||||||||||
|
Waits for input on an fd. This version works on fd's only. Be careful with it. Definition at line 869 of file channel.c. References ast_log(), pollfd::events, pollfd::fd, LOG_WARNING, poll(), POLLIN, and POLLPRI.
00870 {
00871 /* Wait for x amount of time on a file descriptor to have input. */
00872 struct timeval start, now;
00873 int res;
00874 int x, y;
00875 int winner = -1;
00876 int spoint;
00877 struct pollfd *pfds;
00878
00879 pfds = alloca(sizeof(struct pollfd) * n);
00880 if (!pfds) {
00881 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n");
00882 return -1;
00883 }
00884 if (*ms > 0)
00885 gettimeofday(&start, NULL);
00886 y = 0;
00887 for (x=0;x<n;x++) {
00888 if (fds[x] > -1) {
00889 pfds[y].fd = fds[x];
00890 pfds[y].events = POLLIN | POLLPRI;
00891 y++;
00892 }
00893 }
00894 res = poll(pfds, y, *ms);
00895 if (res < 0) {
00896 /* Simulate a timeout if we were interrupted */
00897 if (errno != EINTR)
00898 *ms = -1;
00899 else
00900 *ms = 0;
00901 return -1;
00902 }
00903 spoint = 0;
00904 for (x=0;x<n;x++) {
00905 if (fds[x] > -1) {
00906 if ((res = ast_fdisset(pfds, fds[x], y, &spoint))) {
00907 winner = fds[x];
00908 if (exception) {
00909 if (res & POLLPRI)
00910 *exception = -1;
00911 else
00912 *exception = 0;
00913 }
00914 }
00915 }
00916 }
00917 if (*ms > 0) {
00918 long passed;
00919 gettimeofday(&now, NULL);
00920 passed = (now.tv_sec - start.tv_sec) * 1000;
00921 passed += (now.tv_usec - start.tv_usec) / 1000;
00922 if (passed <= *ms)
00923 *ms -= passed;
00924 else
00925 *ms = 0;
00926 }
00927 return winner;
00928 }
|
|
||||||||||||||||||||||||||||||||
|
Waits for activity on a group of channels.
Definition at line 930 of file channel.c. References ast_channel::_softhangup, ast_do_masquerade(), ast_log(), AST_MAX_FDS, ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_TIMEOUT, ast_channel::blocking, CHECK_BLOCKING, pollfd::events, ast_channel::exception, pollfd::fd, ast_channel::fdno, ast_channel::fds, ast_channel::lock, LOG_WARNING, ast_channel::masq, poll(), POLLIN, POLLPRI, and ast_channel::whentohangup. Referenced by ast_waitfor_n(), ast_waitfordigit_full(), and ast_waitstream_full().
00932 {
00933 /* Wait for x amount of time on a file descriptor to have input. */
00934 struct timeval start, end;
00935 struct pollfd *pfds;
00936 int res;
00937 long rms;
00938 int x, y, max;
00939 int spoint;
00940 time_t now = 0;
00941 long whentohangup = 0, havewhen = 0, diff;
00942 struct ast_channel *winner = NULL;
00943
00944 pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds));
00945 if (!pfds) {
00946 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n");
00947 *outfd = -1;
00948 return NULL;
00949 }
00950
00951 if (outfd)
00952 *outfd = -99999;
00953 if (exception)
00954 *exception = 0;
00955
00956 /* Perform any pending masquerades */
00957 for (x=0;x<n;x++) {
00958 ast_mutex_lock(&c[x]->lock);
00959 if (c[x]->whentohangup) {
00960 if (!havewhen)
00961 time(&now);
00962 diff = c[x]->whentohangup - now;
00963 if (!havewhen || (diff < whentohangup)) {
00964 havewhen++;
00965 whentohangup = diff;
00966 }
00967 }
00968 if (c[x]->masq) {
00969 if (ast_do_masquerade(c[x])) {
00970 ast_log(LOG_WARNING, "Masquerade failed\n");
00971 *ms = -1;
00972 ast_mutex_unlock(&c[x]->lock);
00973 return NULL;
00974 }
00975 }
00976 ast_mutex_unlock(&c[x]->lock);
00977 }
00978
00979 rms = *ms;
00980
00981 if (havewhen) {
00982 if ((*ms < 0) || (whentohangup * 1000 < *ms)) {
00983 rms = whentohangup * 1000;
00984 }
00985 }
00986 max = 0;
00987 for (x=0;x<n;x++) {
00988 for (y=0;y<AST_MAX_FDS;y++) {
00989 if (c[x]->fds[y] > -1) {
00990 pfds[max].fd = c[x]->fds[y];
00991 pfds[max].events = POLLIN | POLLPRI;
00992 max++;
00993 }
00994 }
00995 CHECK_BLOCKING(c[x]);
00996 }
00997 for (x=0;x<nfds; x++) {
00998 if (fds[x] > -1) {
00999 pfds[max].fd = fds[x];
01000 pfds[max].events = POLLIN | POLLPRI;
01001 max++;
01002 }
01003 }
01004 if (*ms > 0)
01005 gettimeofday(&start, NULL);
01006 res = poll(pfds, max, rms);
01007 if (res < 0) {
01008 for (x=0;x<n;x++)
01009 c[x]->blocking = 0;
01010 /* Simulate a timeout if we were interrupted */
01011 if (errno != EINTR)
01012 *ms = -1;
01013 else {
01014 /* Just an interrupt */
01015 #if 0
01016 *ms = 0;
01017 #endif
01018 }
01019 return NULL;
01020 }
01021
01022 if (havewhen)
01023 time(&now);
01024 spoint = 0;
01025 for (x=0;x<n;x++) {
01026 c[x]->blocking = 0;
01027 if (havewhen && c[x]->whentohangup && (now > c[x]->whentohangup)) {
01028 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
01029 if (!winner)
01030 winner = c[x];
01031 }
01032 for (y=0;y<AST_MAX_FDS;y++) {
01033 if (c[x]->fds[y] > -1) {
01034 if ((res = ast_fdisset(pfds, c[x]->fds[y], max, &spoint))) {
01035 if (res & POLLPRI)
01036 c[x]->exception = -1;
01037 else
01038 c[x]->exception = 0;
01039 c[x]->fdno = y;
01040 winner = c[x];
01041 }
01042 }
01043 }
01044 }
01045 for (x=0;x<nfds;x++) {
01046 if (fds[x] > -1) {
01047 if ((res = ast_fdisset(pfds, fds[x], max, &spoint))) {
01048 if (outfd)
01049 *outfd = fds[x];
01050 if (exception) {
01051 if (res & POLLPRI)
01052 *exception = -1;
01053 else
01054 *exception = 0;
01055 }
01056 winner = NULL;
01057 }
01058 }
01059 }
01060 if (*ms > 0) {
01061 long diff;
01062 gettimeofday(&end, NULL);
01063 diff = (end.tv_sec - start.tv_sec) * 1000;
01064 diff += (end.tv_usec - start.tv_usec) / 1000;
01065 if (diff < *ms)
01066 *ms -= diff;
01067 else
01068 *ms = 0;
01069 }
01070 return winner;
01071 }
|
|
||||||||||||
|
Waits for a digit.
Definition at line 1092 of file channel.c. References ast_check_hangup(), ast_frfree(), ast_read(), ast_waitfor(), ast_frame::frametype, ast_frame::subclass, and ast_channel::zombie. Referenced by ast_control_streamfile(), ast_pbx_run(), and ast_readstring().
01093 {
01094 /* XXX Should I be merged with waitfordigit_full XXX */
01095 struct ast_frame *f;
01096 char result = 0;
01097 /* Stop if we're a zombie or need a soft hangup */
01098 if (c->zombie || ast_check_hangup(c))
01099 return -1;
01100 /* Wait for a digit, no more than ms milliseconds total. */
01101 while(ms && !result) {
01102 ms = ast_waitfor(c, ms);
01103 if (ms < 0) /* Error */
01104 result = -1;
01105 else if (ms > 0) {
01106 /* Read something */
01107 f = ast_read(c);
01108 if (f) {
01109 if (f->frametype == AST_FRAME_DTMF)
01110 result = f->subclass;
01111 ast_frfree(f);
01112 } else
01113 result = -1;
01114 }
01115 }
01116 return result;
01117 }
|
|
||||||||||||||||||||
|
Definition at line 1136 of file channel.c. References ast_check_hangup(), ast_frfree(), ast_log(), ast_read(), ast_waitfor_nandfds(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, ast_frame::subclass, and ast_channel::zombie. Referenced by ast_readstring_full().
01137 {
01138 struct ast_frame *f;
01139 struct ast_channel *rchan;
01140 int outfd;
01141 int res;
01142 /* Stop if we're a zombie or need a soft hangup */
01143 if (c->zombie || ast_check_hangup(c))
01144 return -1;
01145 /* Wait for a digit, no more than ms milliseconds total. */
01146 while(ms) {
01147 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01148 if ((!rchan) && (outfd < 0) && (ms)) {
01149 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01150 return -1;
01151 } else if (outfd > -1) {
01152 /* The FD we were watching has something waiting */
01153 return 1;
01154 } else if (rchan) {
01155 f = ast_read(c);
01156 if(!f) {
01157 return -1;
01158 }
01159
01160 switch(f->frametype) {
01161 case AST_FRAME_DTMF:
01162 res = f->subclass;
01163 ast_frfree(f);
01164 return res;
01165 case AST_FRAME_CONTROL:
01166 switch(f->subclass) {
01167 case AST_CONTROL_HANGUP:
01168 ast_frfree(f);
01169 return -1;
01170 case AST_CONTROL_RINGING:
01171 case AST_CONTROL_ANSWER:
01172 /* Unimportant */
01173 break;
01174 default:
01175 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass);
01176 }
01177 case AST_FRAME_VOICE:
01178 /* Write audio if appropriate */
01179 if (audiofd > -1)
01180 write(audiofd, f->data, f->datalen);
01181 }
01182 /* Ignore */
01183 ast_frfree(f);
01184 }
01185 }
01186 return 0; // Time is up
01187 }
|
|
||||||||||||
|
Write a frame to a channel.
Definition at line 1571 of file channel.c. References ast_channel::_softhangup, ast_check_hangup(), ast_deactivate_generator(), ast_do_masquerade(), ast_frame_dump(), ast_frfree(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_seekstream(), AST_SOFTHANGUP_DEV, ast_translate(), ast_writestream(), ast_channel::blocking, CHECK_BLOCKING, ast_frame::data, ast_channel::fout, ast_frame::frametype, ast_channel::generatordata, ast_channel::insmpl, ast_channel::lock, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, ast_channel::name, ast_channel::outsmpl, ast_channel::pvt, ast_frame::samples, SEEK_FORCECUR, ast_channel_pvt::send_text, ast_frame::subclass, ast_channel_pvt::write, ast_channel_monitor::write_stream, ast_channel_pvt::write_video, ast_channel::writeinterrupt, ast_channel_pvt::writetrans, and ast_channel::zombie. Referenced by ast_channel_bridge(), ast_dtmf_stream(), ast_prod(), ast_rtp_bridge(), and ast_write_video().
01572 {
01573 int res = -1;
01574 struct ast_frame *f = NULL;
01575 /* Stop if we're a zombie or need a soft hangup */
01576 ast_mutex_lock(&chan->lock);
01577 if (chan->zombie || ast_check_hangup(chan)) {
01578 ast_mutex_unlock(&chan->lock);
01579 return -1;
01580 }
01581 /* Handle any pending masquerades */
01582 if (chan->masq) {
01583 if (ast_do_masquerade(chan)) {
01584 ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01585 ast_mutex_unlock(&chan->lock);
01586 return -1;
01587 }
01588 }
01589 if (chan->masqr) {
01590 ast_mutex_unlock(&chan->lock);
01591 return 0;
01592 }
01593 if (chan->generatordata) {
01594 if (chan->writeinterrupt)
01595 ast_deactivate_generator(chan);
01596 else {
01597 ast_mutex_unlock(&chan->lock);
01598 return 0;
01599 }
01600 }
01601 if (chan->fout & 0x80000000)
01602 ast_frame_dump(chan->name, fr, ">>");
01603 CHECK_BLOCKING(chan);
01604 switch(fr->frametype) {
01605 case AST_FRAME_CONTROL:
01606 /* XXX Interpret control frames XXX */
01607 ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
01608 break;
01609 case AST_FRAME_DTMF:
01610 chan->blocking = 0;
01611 ast_mutex_unlock(&chan->lock);
01612 res = do_senddigit(chan,fr->subclass);
01613 ast_mutex_lock(&chan->lock);
01614 CHECK_BLOCKING(chan);
01615 break;
01616 case AST_FRAME_TEXT:
01617 if (chan->pvt->send_text)
01618 res = chan->pvt->send_text(chan, (char *) fr->data);
01619 break;
01620 case AST_FRAME_VIDEO:
01621 /* XXX Handle translation of video codecs one day XXX */
01622 if (chan->pvt->write_video)
01623 res = chan->pvt->write_video(chan, fr);
01624 else
01625 res = 0;
01626 break;
01627 default:
01628 if (chan->pvt->write) {
01629 if (chan->pvt->writetrans) {
01630 f = ast_translate(chan->pvt->writetrans, fr, 0);
01631 } else
01632 f = fr;
01633 if (f) {
01634 res = chan->pvt->write(chan, f);
01635 if( chan->monitor &&
01636 chan->monitor->write_stream &&
01637 f && ( f->frametype == AST_FRAME_VOICE ) ) {
01638 #ifndef MONITOR_CONSTANT_DELAY
01639 int jump = chan->insmpl - chan->outsmpl - 2 * f->samples;
01640 if (jump >= 0) {
01641 if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01642 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01643 chan->outsmpl += jump + 2 * f->samples;
01644 } else
01645 chan->outsmpl += f->samples;
01646 #else
01647 int jump = chan->insmpl - chan->outsmpl;
01648 if (jump - MONITOR_DELAY >= 0) {
01649 if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01650 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01651 chan->outsmpl += jump;
01652 } else
01653 chan->outsmpl += f->samples;
01654 #endif
01655 if (ast_writestream(chan->monitor->write_stream, f) < 0)
01656 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
01657 }
01658 } else
01659 res = 0;
01660 }
01661 }
01662 if (f && (f != fr))
01663 ast_frfree(f);
01664 chan->blocking = 0;
01665 /* Consider a write failure to force a soft hangup */
01666 if (res < 0)
01667 chan->_softhangup |= AST_SOFTHANGUP_DEV;
01668 else {
01669 if ((chan->fout & 0x7fffffff) == 0x7fffffff)
01670 chan->fout &= 0x80000000;
01671 else
01672 chan->fout++;
01673 chan->fout++;
01674 }
01675 ast_mutex_unlock(&chan->lock);
01676 return res;
01677 }
|
|
||||||||||||
|
Write video frame to a channel.
Definition at line 1560 of file channel.c. References ast_write(), ast_channel::pvt, and ast_channel_pvt::write_video.
01561 {
01562 int res;
01563 if (!chan->pvt->write_video)
01564 return 0;
01565 res = ast_write(chan, fr);
01566 if (!res)
01567 res = 1;
01568 return res;
01569 }
|
1.2.15