#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_generator |
| struct | ast_channel |
| Main Channel structure associated with a channel. More... | |
| struct | ast_bridge_config |
| struct | outgoing_helper |
Defines | |
| #define | AST_MAX_EXTENSION 80 |
| Max length of an extension. | |
| #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 | |
| struct ast_channel * | ast_request (char *type, int format, void *data) |
| Requests a channel. | |
| int | ast_parse_device_state (char *device) |
| Search the Channels by Name. | |
| int | ast_device_state (char *device) |
| Asks a channel for device state. | |
| struct ast_channel * | ast_request_and_dial (char *type, int format, void *data, int timeout, int *reason, char *callerid) |
| struct 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. | |
| 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. | |
| int | ast_hangup (struct ast_channel *chan) |
| Hang up a channel. | |
| int | ast_softhangup (struct ast_channel *chan, int cause) |
| Softly hangup up a channel. | |
| 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. | |
| void | ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset) |
| Set when to hang a channel up. | |
| int | ast_answer (struct ast_channel *chan) |
| Answer a ringing call. | |
| int | ast_call (struct ast_channel *chan, char *addr, int timeout) |
| Make a call. | |
| int | ast_indicate (struct ast_channel *chan, int condition) |
| Indicates condition of channel. | |
| int | ast_waitfor (struct ast_channel *chan, int ms) |
| Wait for input on a channel. | |
| int | ast_safe_sleep (struct ast_channel *chan, int ms) |
| Wait for a specied amount of time, looking for hangups. | |
| 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. | |
| struct ast_channel * | ast_waitfor_nandfds (struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms) |
| Waits for activity on a group of channels. | |
| struct ast_channel * | ast_waitfor_n (struct ast_channel **chan, int n, int *ms) |
| Waits for input on a group of channels. | |
| int | ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception) |
| Waits for input on an fd. | |
| struct ast_frame * | ast_read (struct ast_channel *chan) |
| Reads a frame. | |
| int | ast_write (struct ast_channel *chan, struct ast_frame *frame) |
| Write a frame to a channel. | |
| int | ast_write_video (struct ast_channel *chan, struct ast_frame *frame) |
| Write video frame to a channel. | |
| int | ast_prod (struct ast_channel *chan) |
| int | ast_set_read_format (struct ast_channel *chan, int format) |
| Sets read format on channel chan. | |
| int | ast_set_write_format (struct ast_channel *chan, int format) |
| Sets write format on channel chan. | |
| int | ast_sendtext (struct ast_channel *chan, char *text) |
| Sends text to a channel. | |
| int | ast_senddigit (struct ast_channel *chan, char digit) |
| Receives a text character from a channel. | |
| int | ast_recvchar (struct ast_channel *chan, int timeout) |
| struct ast_channel * | ast_channel_walk_locked (struct ast_channel *prev) |
| Browse channels in use. | |
| struct ast_channel * | ast_get_channel_by_name_locked (char *channame) |
| Get channel by name (locks channel). | |
| int | ast_waitfordigit (struct ast_channel *c, int ms) |
| Waits for a digit. | |
| int | 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. | |
| 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. | |
| int | ast_channel_bridge (struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc) |
| Bridge two channels together. | |
| int | ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone) |
| Weird function made for call transfers. | |
| char * | ast_state2str (int state) |
| Gives the string form of a given state. | |
| int | ast_channel_setoption (struct ast_channel *channel, int option, void *data, int datalen, int block) |
| Sets an option on a channel. | |
| struct ast_frame * | ast_channel_queryoption (struct ast_channel *channel, int option, void *data, int *datalen, int block) |
| Checks the value of an option. | |
| int | ast_channel_supports_html (struct ast_channel *channel) |
| Checks for HTML support on a channel. | |
| int | ast_channel_sendhtml (struct ast_channel *channel, int subclass, char *data, int datalen) |
| Sends HTML on given channel. | |
| int | ast_channel_sendurl (struct ast_channel *channel, char *url) |
| Sends a URL on a given link. | |
| int | ast_channel_defer_dtmf (struct ast_channel *chan) |
| Defers DTMF. | |
| void | ast_channel_undefer_dtmf (struct ast_channel *chan) |
| Undeos a defer. | |
| 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) |
| #define AST_BRIDGE_DTMF_CHANNEL_0 (1 << 0) |
| #define AST_BRIDGE_DTMF_CHANNEL_1 (1 << 1) |
| #define AST_BRIDGE_IGNORE_SIGS (1 << 4) |
| #define AST_BRIDGE_REC_CHANNEL_0 (1 << 2) |
| #define AST_BRIDGE_REC_CHANNEL_1 (1 << 3) |
| #define AST_DEVICE_UNKNOWN 0 |
| #define AST_STATE_DIALING 3 |
| #define AST_STATE_DIALING_OFFHOOK 8 |
| #define AST_STATE_MUTE (1 << 16) |
| #define AST_STATE_PRERING 9 |
| #define AST_STATE_RESERVED 1 |
| struct ast_channel* __ast_request_and_dial | ( | char * | type, | |
| int | format, | |||
| void * | data, | |||
| int | timeout, | |||
| int * | reason, | |||
| char * | callerid, | |||
| struct outgoing_helper * | oh | |||
| ) | [read] |
Definition at line 1758 of file channel.c.
01759 { 01760 int state = 0; 01761 struct ast_channel *chan; 01762 struct ast_frame *f; 01763 int res = 0; 01764 char *variable; 01765 chan = ast_request(type, format, data); 01766 if (chan) { 01767 if (oh) { 01768 char *tmp, *var; 01769 /* JDG chanvar */ 01770 if (oh->variable) 01771 variable = ast_strdupa(oh->variable); 01772 else 01773 variable = NULL; 01774 tmp = variable; 01775 /* FIXME replace this call with strsep NOT*/ 01776 while( (var = strtok_r(NULL, "|", &tmp)) ) { 01777 pbx_builtin_setvar( chan, var ); 01778 } /* /JDG */ 01779 if (oh->callerid && *oh->callerid) 01780 ast_set_callerid(chan, oh->callerid, 1); 01781 if (oh->account && *oh->account) 01782 ast_cdr_setaccount(chan, oh->account); 01783 } 01784 if (callerid && !ast_strlen_zero(callerid)) 01785 ast_set_callerid(chan, callerid, 1); 01786 01787 if (!ast_call(chan, data, 0)) { 01788 while(timeout && (chan->_state != AST_STATE_UP)) { 01789 res = ast_waitfor(chan, timeout); 01790 if (res < 0) { 01791 /* Something not cool, or timed out */ 01792 break; 01793 } 01794 /* If done, break out */ 01795 if (!res) 01796 break; 01797 if (timeout > -1) 01798 timeout = res; 01799 f = ast_read(chan); 01800 if (!f) { 01801 state = AST_CONTROL_HANGUP; 01802 res = 0; 01803 break; 01804 } 01805 if (f->frametype == AST_FRAME_CONTROL) { 01806 if (f->subclass == AST_CONTROL_RINGING) 01807 state = AST_CONTROL_RINGING; 01808 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) { 01809 state = f->subclass; 01810 ast_frfree(f); 01811 break; 01812 } else if (f->subclass == AST_CONTROL_ANSWER) { 01813 state = f->subclass; 01814 ast_frfree(f); 01815 break; 01816 } else if (f->subclass == AST_CONTROL_PROGRESS) { 01817 /* Ignore */ 01818 } else if (f->subclass == -1) { 01819 /* Ignore -- just stopping indications */ 01820 } else { 01821 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass); 01822 } 01823 } 01824 ast_frfree(f); 01825 } 01826 } else 01827 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 01828 } else 01829 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 01830 if (chan) { 01831 /* Final fixups */ 01832 if (oh) { 01833 if (oh->context && *oh->context) 01834 strncpy(chan->context, oh->context, sizeof(chan->context) - 1); 01835 if (oh->exten && *oh->exten) 01836 strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1); 01837 chan->priority = oh->priority; 01838 } 01839 if (chan->_state == AST_STATE_UP) 01840 state = AST_CONTROL_ANSWER; 01841 } 01842 if (outstate) 01843 *outstate = state; 01844 if (chan && res <= 0) { 01845 if (!chan->cdr) { 01846 chan->cdr = ast_cdr_alloc(); 01847 if (chan->cdr) 01848 ast_cdr_init(chan->cdr, chan); 01849 } 01850 if (chan->cdr) { 01851 char tmp[256]; 01852 snprintf(tmp, 256, "%s/%s", type, (char *)data); 01853 ast_cdr_setapp(chan->cdr,"Dial",tmp); 01854 ast_cdr_update(chan); 01855 ast_cdr_start(chan->cdr); 01856 ast_cdr_end(chan->cdr); 01857 /* If the cause wasn't handled properly */ 01858 if (ast_cdr_disposition(chan->cdr,chan->hangupcause)) 01859 ast_cdr_failed(chan->cdr); 01860 } else 01861 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 01862 ast_hangup(chan); 01863 chan = NULL; 01864 } 01865 return chan; 01866 }
| int ast_activate_generator | ( | struct ast_channel * | chan, | |
| struct ast_generator * | gen, | |||
| void * | params | |||
| ) |
Activate a given generator
Definition at line 849 of file channel.c.
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 }
| int ast_active_channels | ( | void | ) |
Returns number of active/allocated channels
Definition at line 120 of file channel.c.
00121 { 00122 struct ast_channel *c; 00123 int cnt = 0; 00124 ast_mutex_lock(&chlock); 00125 c = channels; 00126 while(c) { 00127 cnt++; 00128 c = c->next; 00129 } 00130 ast_mutex_unlock(&chlock); 00131 return cnt; 00132 }
| int ast_answer | ( | struct ast_channel * | chan | ) |
Answer a ringing call.
| chan | channel to answer This function answers a channel and handles all necessary call setup functions. Returns 0 on success, -1 on failure |
Definition at line 785 of file channel.c.
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 }
| int ast_autoservice_start | ( | struct ast_channel * | chan | ) |
Automatically service a channel for us...
Definition at line 88 of file autoservice.c.
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 }
| int ast_autoservice_stop | ( | struct ast_channel * | chan | ) |
Stop servicing a channel for us... Returns -1 on error or if channel has been hungup
Definition at line 124 of file autoservice.c.
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 }
| void ast_begin_shutdown | ( | int | hangup | ) |
Initiate system shutdown -- prevents new channels from being allocated. If "hangup" is non-zero, all existing channels will receive soft hangups
Definition at line 105 of file channel.c.
00106 { 00107 struct ast_channel *c; 00108 shutting_down = 1; 00109 if (hangup) { 00110 ast_mutex_lock(&chlock); 00111 c = channels; 00112 while(c) { 00113 ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN); 00114 c = c->next; 00115 } 00116 ast_mutex_unlock(&chlock); 00117 } 00118 }
| int ast_call | ( | struct ast_channel * | chan, | |
| char * | addr, | |||
| int | timeout | |||
| ) |
Make a call.
| chan | which channel to make the call on | |
| addr | destination of the call | |
| timeout | time to wait on for connect Place a call, take no longer than timeout ms. Returns -1 on failure, 0 on not enough time (does not auto matically stop ringing), and the number of seconds the connect took otherwise. Returns 0 on success, -1 on failure |
Definition at line 1977 of file channel.c.
01978 { 01979 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 01980 If the remote end does not answer within the timeout, then do NOT hang up, but 01981 return anyway. */ 01982 int res = -1; 01983 /* Stop if we're a zombie or need a soft hangup */ 01984 ast_mutex_lock(&chan->lock); 01985 if (!chan->zombie && !ast_check_hangup(chan)) 01986 if (chan->pvt->call) 01987 res = chan->pvt->call(chan, addr, timeout); 01988 ast_mutex_unlock(&chan->lock); 01989 return res; 01990 }
| void ast_cancel_shutdown | ( | void | ) |
| 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.
| c0 | first channel to bridge | |
| c1 | second channel to bridge | |
| flags | for the channels | |
| fo | destination frame(?) | |
| rc | destination channel(?) Bridge two channels (c0 and c1) together. If an important frame occurs, we return that frame in rf (remember, it could be NULL) and which channel (0 or 1) in rc |
Definition at line 2523 of file channel.c.
02524 { 02525 /* Copy voice back and forth between the two channels. Give the peer 02526 the ability to transfer calls with '#<extension' syntax. */ 02527 int flags; 02528 struct ast_channel *cs[3]; 02529 int to = -1; 02530 struct ast_frame *f; 02531 struct ast_channel *who = NULL; 02532 int res=0; 02533 int nativefailed=0; 02534 int firstpass; 02535 int o0nativeformats; 02536 int o1nativeformats; 02537 struct timeval start_time,precise_now; 02538 long elapsed_ms=0, time_left_ms=0; 02539 int playit=0, playitagain=1, first_time=1; 02540 02541 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); 02542 02543 firstpass = config->firstpass; 02544 config->firstpass = 0; 02545 02546 /* timestamp */ 02547 gettimeofday(&start_time,NULL); 02548 time_left_ms = config->timelimit; 02549 02550 if (config->play_to_caller && config->start_sound && firstpass) 02551 bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000); 02552 if (config->play_to_callee && config->start_sound && firstpass) 02553 bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000); 02554 02555 /* Stop if we're a zombie or need a soft hangup */ 02556 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 02557 return -1; 02558 if (c0->bridge) { 02559 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 02560 c0->name, c0->bridge->name); 02561 return -1; 02562 } 02563 if (c1->bridge) { 02564 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 02565 c1->name, c1->bridge->name); 02566 return -1; 02567 } 02568 02569 /* Keep track of bridge */ 02570 c0->bridge = c1; 02571 c1->bridge = c0; 02572 cs[0] = c0; 02573 cs[1] = c1; 02574 02575 manager_event(EVENT_FLAG_CALL, "Link", 02576 "Channel1: %s\r\n" 02577 "Channel2: %s\r\n" 02578 "Uniqueid1: %s\r\n" 02579 "Uniqueid2: %s\r\n", 02580 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02581 o1nativeformats = c1->nativeformats; 02582 o0nativeformats = c0->nativeformats; 02583 for (/* ever */;;) { 02584 /* timestamp */ 02585 if (config->timelimit) { 02586 gettimeofday(&precise_now,NULL); 02587 elapsed_ms = tvdiff(&precise_now,&start_time); 02588 time_left_ms = config->timelimit - elapsed_ms; 02589 02590 if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) { 02591 /* narrowing down to the end */ 02592 if (config->warning_freq == 0) { 02593 playit = 1; 02594 first_time=0; 02595 playitagain=0; 02596 } else if (first_time) { 02597 playit = 1; 02598 first_time=0; 02599 } else { 02600 if ((time_left_ms % config->warning_freq) <= 50) { 02601 playit = 1; 02602 } 02603 } 02604 } 02605 if (time_left_ms <= 0) { 02606 if (config->play_to_caller && config->end_sound) 02607 bridge_playfile(c0,c1,config->end_sound,0); 02608 if (config->play_to_callee && config->end_sound) 02609 bridge_playfile(c1,c0,config->end_sound,0); 02610 *fo = NULL; 02611 if (who) *rc = who; 02612 res = 0; 02613 break; 02614 } 02615 if (time_left_ms >= 5000 && playit) { 02616 if (config->play_to_caller && config->warning_sound && config->play_warning) 02617 bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000); 02618 if (config->play_to_callee && config->warning_sound && config->play_warning) 02619 bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000); 02620 playit = 0; 02621 } 02622 02623 } 02624 /* Stop if we're a zombie or need a soft hangup */ 02625 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) { 02626 *fo = NULL; 02627 if (who) *rc = who; 02628 res = 0; 02629 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"); 02630 break; 02631 } 02632 if (c0->pvt->bridge && config->timelimit==0 && 02633 (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) { 02634 /* Looks like they share a bridge code */ 02635 if (option_verbose > 2) 02636 ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name); 02637 if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) { 02638 c0->bridge = NULL; 02639 c1->bridge = NULL; 02640 manager_event(EVENT_FLAG_CALL, "Unlink", 02641 "Channel1: %s\r\n" 02642 "Channel2: %s\r\n" 02643 "Uniqueid1: %s\r\n" 02644 "Uniqueid2: %s\r\n", 02645 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02646 ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name); 02647 return 0; 02648 } 02649 /* If they return non-zero then continue on normally. Let "-2" mean don't worry about 02650 my not wanting to bridge */ 02651 if ((res != -2) && (res != -3)) 02652 ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name); 02653 if (res != -3) nativefailed++; 02654 } 02655 02656 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) && 02657 !(c0->generator || c1->generator)) { 02658 if (ast_channel_make_compatible(c0, c1)) { 02659 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); 02660 manager_event(EVENT_FLAG_CALL, "Unlink", 02661 "Channel1: %s\r\n" 02662 "Channel2: %s\r\n" 02663 "Uniqueid1: %s\r\n" 02664 "Uniqueid2: %s\r\n", 02665 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02666 return -1; 02667 } 02668 o0nativeformats = c0->nativeformats; 02669 o1nativeformats = c1->nativeformats; 02670 } 02671 who = ast_waitfor_n(cs, 2, &to); 02672 if (!who) { 02673 ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 02674 continue; 02675 } 02676 f = ast_read(who); 02677 if (!f) { 02678 *fo = NULL; 02679 *rc = who; 02680 res = 0; 02681 ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name); 02682 break; 02683 } 02684 02685 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 02686 *fo = f; 02687 *rc = who; 02688 res = 0; 02689 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name); 02690 break; 02691 } 02692 if ((f->frametype == AST_FRAME_VOICE) || 02693 (f->frametype == AST_FRAME_TEXT) || 02694 (f->frametype == AST_FRAME_VIDEO) || 02695 (f->frametype == AST_FRAME_IMAGE) || 02696 (f->frametype == AST_FRAME_HTML) || 02697 (f->frametype == AST_FRAME_DTMF)) { 02698 if ((f->frametype == AST_FRAME_DTMF) && 02699 (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) { 02700 if ((who == c0)) { 02701 if ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 02702 *rc = c0; 02703 *fo = f; 02704 /* Take out of conference mode */ 02705 res = 0; 02706 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name); 02707 break; 02708 } else 02709 goto tackygoto; 02710 } else 02711 if ((who == c1)) { 02712 if (flags & AST_BRIDGE_DTMF_CHANNEL_1) { 02713 *rc = c1; 02714 *fo = f; 02715 res = 0; 02716 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name); 02717 break; 02718 } else 02719 goto tackygoto; 02720 } 02721 } else { 02722 #if 0 02723 ast_log(LOG_DEBUG, "Read from %s\n", who->name); 02724 if (who == last) 02725 ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name); 02726 last = who; 02727 #endif 02728 tackygoto: 02729 /* Don't copy packets if there is a generator on either one, since they're 02730 not supposed to be listening anyway */ 02731 if (who == c0) 02732 ast_write(c1, f); 02733 else 02734 ast_write(c0, f); 02735 } 02736 ast_frfree(f); 02737 } else 02738 ast_frfree(f); 02739 /* Swap who gets priority */ 02740 cs[2] = cs[0]; 02741 cs[0] = cs[1]; 02742 cs[1] = cs[2]; 02743 } 02744 c0->bridge = NULL; 02745 c1->bridge = NULL; 02746 manager_event(EVENT_FLAG_CALL, "Unlink", 02747 "Channel1: %s\r\n" 02748 "Channel2: %s\r\n" 02749 "Uniqueid1: %s\r\n" 02750 "Uniqueid2: %s\r\n", 02751 c0->name, c1->name, c0->uniqueid, c1->uniqueid); 02752 ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name); 02753 return res; 02754 }
| int ast_channel_defer_dtmf | ( | struct ast_channel * | chan | ) |
Defers DTMF.
Defer DTMF so that you only read things like hangups and audio. Returns non-zero if channel was already DTMF-deferred or 0 if channel is just now being DTMF-deferred
Definition at line 441 of file channel.c.
00442 { 00443 int pre = 0; 00444 if (chan) { 00445 pre = chan->deferdtmf; 00446 chan->deferdtmf = 1; 00447 } 00448 return pre; 00449 }
| int ast_channel_make_compatible | ( | struct ast_channel * | c0, | |
| struct ast_channel * | c1 | |||
| ) |
Makes two channel formats compatible.
| c0 | first channel to make compatible | |
| c1 | other channel to make compatible Set two channels to compatible formats -- call before ast_channel_bridge in general . Returns 0 on success and -1 if it could not be done |
Definition at line 2114 of file channel.c.
02115 { 02116 int peerf; 02117 int chanf; 02118 int res; 02119 ast_mutex_lock(&peer->lock); 02120 peerf = peer->nativeformats; 02121 ast_mutex_unlock(&peer->lock); 02122 ast_mutex_lock(&chan->lock); 02123 chanf = chan->nativeformats; 02124 ast_mutex_unlock(&chan->lock); 02125 res = ast_translator_best_choice(&peerf, &chanf); 02126 if (res < 0) { 02127 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats); 02128 return -1; 02129 } 02130 /* Set read format on channel */ 02131 res = ast_set_read_format(chan, peerf); 02132 if (res < 0) { 02133 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf); 02134 return -1; 02135 } 02136 /* Set write format on peer channel */ 02137 res = ast_set_write_format(peer, peerf); 02138 if (res < 0) { 02139 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf); 02140 return -1; 02141 } 02142 /* Now we go the other way */ 02143 peerf = peer->nativeformats; 02144 chanf = chan->nativeformats; 02145 res = ast_translator_best_choice(&chanf, &peerf); 02146 if (res < 0) { 02147 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats); 02148 return -1; 02149 } 02150 /* Set writeformat on channel */ 02151 res = ast_set_write_format(chan, chanf); 02152 if (res < 0) { 02153 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf); 02154 return -1; 02155 } 02156 /* Set read format on peer channel */ 02157 res = ast_set_read_format(peer, chanf); 02158 if (res < 0) { 02159 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf); 02160 return -1; 02161 } 02162 return 0; 02163 }
| int ast_channel_masquerade | ( | struct ast_channel * | original, | |
| struct ast_channel * | clone | |||
| ) |
Weird function made for call transfers.
| original | channel to make a copy of | |
| clone | copy of the original channel This is a very strange and freaky function used primarily for transfer. Suppose that "original" and "clone" are two channels in random situations. This function takes the guts out of "clone" and puts them into the "original" channel, then alerts the channel driver of the change, asking it to fixup any private information (like the p->owner pointer) that is affected by the change. The physical layer of the original channel is hung up. |
Definition at line 2165 of file channel.c.
02166 { 02167 struct ast_frame null = { AST_FRAME_NULL, }; 02168 int res = -1; 02169 ast_mutex_lock(&original->lock); 02170 while(ast_mutex_trylock(&clone->lock)) { 02171 ast_mutex_unlock(&original->lock); 02172 usleep(1); 02173 ast_mutex_lock(&original->lock); 02174 } 02175 ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n", 02176 clone->name, original->name); 02177 if (original->masq) { 02178 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02179 original->masq->name, original->name); 02180 } else if (clone->masqr) { 02181 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 02182 clone->name, clone->masqr->name); 02183 } else { 02184 original->masq = clone; 02185 clone->masqr = original; 02186 ast_queue_frame(original, &null); 02187 ast_queue_frame(clone, &null); 02188 ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name); 02189 res = 0; 02190 } 02191 ast_mutex_unlock(&clone->lock); 02192 ast_mutex_unlock(&original->lock); 02193 return res; 02194 }
| struct ast_frame* ast_channel_queryoption | ( | struct ast_channel * | channel, | |
| int | option, | |||
| void * | data, | |||
| int * | datalen, | |||
| int | block | |||
| ) | [read] |
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.
| int ast_channel_register | ( | char * | type, | |
| char * | description, | |||
| int | capabilities, | |||
| struct ast_channel *(*)(char *type, int format, void *data) | requester | |||
| ) |
Registers a channel.
| type | type of channel you are registering | |
| description | short description of the channel | |
| capabilities | a bit mask of the capabilities of the channel | |
| requester | a function pointer that properly responds to a call. See one of the channel drivers for details. Called by a channel module to register the kind of channels it supports. It supplies a brief type, a longer, but still short description, and a routine that creates a channel Returns 0 on success, -1 on failure. |
Definition at line 156 of file channel.c.
00158 { 00159 return ast_channel_register_ex(type, description, capabilities, requester, NULL); 00160 }
| int ast_channel_register_ex | ( | char * | type, | |
| char * | description, | |||
| int | capabilities, | |||
| struct ast_channel *(*)(char *type, int format, void *data) | requester, | |||
| int(*)(void *data) | devicestate | |||
| ) |
Definition at line 162 of file channel.c.
00165 { 00166 struct chanlist *chan, *last=NULL; 00167 if (ast_mutex_lock(&chlock)) { 00168 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 00169 return -1; 00170 } 00171 chan = backends; 00172 while (chan) { 00173 if (!strcasecmp(type, chan->type)) { 00174 ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type); 00175 ast_mutex_unlock(&chlock); 00176 return -1; 00177 } 00178 last = chan; 00179 chan = chan->next; 00180 } 00181 chan = malloc(sizeof(struct chanlist)); 00182 if (!chan) { 00183 ast_log(LOG_WARNING, "Out of memory\n"); 00184 ast_mutex_unlock(&chlock); 00185 return -1; 00186 } 00187 strncpy(chan->type, type, sizeof(chan->type)-1); 00188 strncpy(chan->description, description, sizeof(chan->description)-1); 00189 chan->capabilities = capabilities; 00190 chan->requester = requester; 00191 chan->devicestate = devicestate; 00192 chan->next = NULL; 00193 if (last) 00194 last->next = chan; 00195 else 00196 backends = chan; 00197 if (option_debug) 00198 ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description); 00199 else if (option_verbose > 1) 00200 ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description); 00201 ast_mutex_unlock(&chlock); 00202 return 0; 00203 }
| int ast_channel_sendhtml | ( | struct ast_channel * | channel, | |
| int | subclass, | |||
| char * | data, | |||
| int | datalen | |||
| ) |
| int ast_channel_sendurl | ( | struct ast_channel * | channel, | |
| char * | url | |||
| ) |
Sends a URL on a given link.
Send URL on link. Returns 0 on success or -1 on failure
Definition at line 2107 of file channel.c.
02108 { 02109 if (chan->pvt->send_html) 02110 return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1); 02111 return -1; 02112 }
| int ast_channel_setoption | ( | struct ast_channel * | channel, | |
| int | option, | |||
| void * | data, | |||
| int | datalen, | |||
| int | block | |||
| ) |
Sets an option on a channel.
| channel | channel to set options on | |
| option | option to change | |
| data | data specific to option | |
| datalen | length of the data | |
| block | blocking or not Set an option on a channel (see frame.h), optionally blocking awaiting the reply Returns 0 on success and -1 on failure |
Definition at line 2756 of file channel.c.
02757 { 02758 int res; 02759 if (chan->pvt->setoption) { 02760 res = chan->pvt->setoption(chan, option, data, datalen); 02761 if (res < 0) 02762 return res; 02763 } else { 02764 errno = ENOSYS; 02765 return -1; 02766 } 02767 if (block) { 02768 /* XXX Implement blocking -- just wait for our option frame reply, discarding 02769 intermediate packets. XXX */ 02770 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 02771 return -1; 02772 } 02773 return 0; 02774 }
| void ast_channel_setwhentohangup | ( | struct ast_channel * | chan, | |
| time_t | offset | |||
| ) |
Set when to hang a channel up.
| chan | channel on which to check for hang up | |
| offset | offset in seconds from current time of when to hang up This function sets the absolute time out on a channel (when to hang up). |
Definition at line 144 of file channel.c.
00145 { 00146 time_t myt; 00147 00148 time(&myt); 00149 if (offset) 00150 chan->whentohangup = myt + offset; 00151 else 00152 chan->whentohangup = 0; 00153 return; 00154 }
| int ast_channel_supports_html | ( | struct ast_channel * | channel | ) |
| void ast_channel_undefer_dtmf | ( | struct ast_channel * | chan | ) |
| void ast_channel_unregister | ( | char * | type | ) |
Unregister a channel class.
Definition at line 756 of file channel.c.
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 }
| struct ast_channel* ast_channel_walk_locked | ( | struct ast_channel * | prev | ) | [read] |
Browse channels in use.
| prev | where you want to start in the channel list Browse the channels currently in use Returns the next channel in the list, NULL on end. If it returns a channel, that channel *has been locked*! |
Definition at line 457 of file channel.c.
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 }
| int ast_check_hangup | ( | struct ast_channel * | chan | ) |
Check to see if a channel is needing hang up.
| chan | channel on which to check for hang up This function determines if the channel is being requested to be hung up. Returns 0 if not, or 1 if hang up is requested (including time-out). |
Definition at line 79 of file channel.c.
00080 { 00081 time_t myt; 00082 00083 /* if soft hangup flag, return true */ 00084 if (chan->_softhangup) return 1; 00085 /* if no private structure, return true */ 00086 if (!chan->pvt->pvt) return 1; 00087 /* if no hangup scheduled, just return here */ 00088 if (!chan->whentohangup) return 0; 00089 time(&myt); /* get current time */ 00090 /* return, if not yet */ 00091 if (chan->whentohangup > myt) return 0; 00092 chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 00093 return 1; 00094 }
| void ast_deactivate_generator | ( | struct ast_channel * | chan | ) |
Deactive an active generator
Definition at line 816 of file channel.c.
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 }
| int ast_device_state | ( | char * | device | ) |
Asks a channel for device state.
| device | like a dialstring Asks a channel for device state, data is normaly a number from dialstring used by the low level module Trys the channel devicestate callback if not supported search in the active channels list for the device. Returns an AST_DEVICE_??? state -1 on failure |
Definition at line 1938 of file channel.c.
01939 { 01940 char tech[AST_MAX_EXTENSION] = ""; 01941 char *number; 01942 struct chanlist *chanls; 01943 int res = 0; 01944 01945 strncpy(tech, device, sizeof(tech)-1); 01946 number = strchr(tech, '/'); 01947 if (!number) { 01948 return AST_DEVICE_INVALID; 01949 } 01950 *number = 0; 01951 number++; 01952 01953 if (ast_mutex_lock(&chlock)) { 01954 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 01955 return -1; 01956 } 01957 chanls = backends; 01958 while(chanls) { 01959 if (!strcasecmp(tech, chanls->type)) { 01960 ast_mutex_unlock(&chlock); 01961 if (!chanls->devicestate) 01962 return ast_parse_device_state(device); 01963 else { 01964 res = chanls->devicestate(number); 01965 if (res == AST_DEVICE_UNKNOWN) 01966 return ast_parse_device_state(device); 01967 else 01968 return res; 01969 } 01970 } 01971 chanls = chanls->next; 01972 } 01973 ast_mutex_unlock(&chlock); 01974 return AST_DEVICE_INVALID; 01975 }
| int ast_do_masquerade | ( | struct ast_channel * | chan | ) |
Definition at line 2204 of file channel.c.
02205 { 02206 int x,i; 02207 int res=0; 02208 int origstate; 02209 char *tmp; 02210 struct ast_var_t *varptr; 02211 struct ast_frame *cur, *prev; 02212 struct ast_channel_pvt *p; 02213 struct ast_channel *clone = original->masq; 02214 struct ast_channel_monitor *monitor; 02215 int rformat = original->readformat; 02216 int wformat = original->writeformat; 02217 char newn[100]; 02218 char orig[100]; 02219 char masqn[100]; 02220 char zombn[100]; 02221 02222 #if 1 02223 ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n", 02224 clone->name, clone->_state, original->name, original->_state); 02225 #endif 02226 /* XXX This is a seriously wacked out operation. We're essentially putting the guts of 02227 the clone channel into the original channel. Start by killing off the original 02228 channel's backend. I'm not sure we're going to keep this function, because 02229 while the features are nice, the cost is very high in terms of pure nastiness. XXX */ 02230 02231 /* We need the clone's lock, too */ 02232 ast_mutex_lock(&clone->lock); 02233 02234 ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock); 02235 02236 /* Having remembered the original read/write formats, we turn off any translation on either 02237 one */ 02238 free_translation(clone); 02239 free_translation(original); 02240 02241 02242 /* Unlink the masquerade */ 02243 original->masq = NULL; 02244 clone->masqr = NULL; 02245 02246 /* Save the original name */ 02247 strncpy(orig, original->name, sizeof(orig) - 1); 02248 /* Save the new name */ 02249 strncpy(newn, clone->name, sizeof(newn) - 1); 02250 /* Create the masq name */ 02251 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn); 02252 02253 /* Copy the name from the clone channel */ 02254 strncpy(original->name, newn, sizeof(original->name)-1); 02255 02256 /* Mangle the name of the clone channel */ 02257 strncpy(clone->name, masqn, sizeof(clone->name) - 1); 02258 02259 /* Notify any managers of the change, first the masq then the other */ 02260 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid); 02261 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid); 02262 02263 /* Swap the guts */ 02264 p = original->pvt; 02265 original->pvt = clone->pvt; 02266 clone->pvt = p; 02267 02268 /* Save any pending frames on both sides. Start by counting 02269 * how many we're going to need... */ 02270 prev = NULL; 02271 cur = clone->pvt->readq; 02272 x = 0; 02273 while(cur) { 02274 x++; 02275 prev = cur; 02276 cur = cur->next; 02277 } 02278 /* If we had any, prepend them to the ones already in the queue, and 02279 * load up the alertpipe */ 02280 if (prev) { 02281 prev->next = original->pvt->readq; 02282 original->pvt->readq = clone->pvt->readq; 02283 clone->pvt->readq = NULL; 02284 if (original->pvt->alertpipe[1] > -1) { 02285 for (i=0;i<x;i++) 02286 write(original->pvt->alertpipe[1], &x, sizeof(x)); 02287 } 02288 } 02289 clone->_softhangup = AST_SOFTHANGUP_DEV; 02290 02291 02292 /* And of course, so does our current state. Note we need not 02293 call ast_setstate since the event manager doesn't really consider 02294 these separate. We do this early so that the clone has the proper 02295 state of the original channel. */ 02296 origstate = original->_state; 02297 original->_state = clone->_state; 02298 clone->_state = origstate; 02299 02300 if (clone->pvt->fixup){ 02301 res = clone->pvt->fixup(original, clone); 02302 if (res) 02303 ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name); 02304 } 02305 02306 /* Start by disconnecting the original's physical side */ 02307 if (clone->pvt->hangup) 02308 res = clone->pvt->hangup(clone); 02309 if (res) { 02310 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n"); 02311 ast_mutex_unlock(&clone->lock); 02312 return -1; 02313 } 02314 02315 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig); 02316 /* Mangle the name of the clone channel */ 02317 strncpy(clone->name, zombn, sizeof(clone->name) - 1); 02318 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid); 02319 02320 /* Update the type. */ 02321 original->type = clone->type; 02322 02323 /* copy the monitor */ 02324 monitor = original->monitor; 02325 original->monitor = clone->monitor; 02326 clone->monitor = monitor; 02327 02328 /* Keep the same language. */ 02329 strncpy(original->language, clone->language, sizeof(original->language)); 02330 02331 /* Copy the FD's */ 02332 for (x=0;x<AST_MAX_FDS;x++) { 02333 original->fds[x] = clone->fds[x]; 02334 } 02335 /* Append variables from clone channel into original channel */ 02336 /* XXX Is this always correct? We have to in order to keep MACROS working XXX */ 02337 varptr = original->varshead.first; 02338 if (varptr) { 02339 while(varptr->entries.next) { 02340 varptr = varptr->entries.next; 02341 } 02342 varptr->entries.next = clone->varshead.first; 02343 } else { 02344 original->varshead.first = clone->varshead.first; 02345 } 02346 clone->varshead.first = NULL; 02347 /* Presense of ADSI capable CPE follows clone */ 02348 original->adsicpe = clone->adsicpe; 02349 /* Bridge remains the same */ 02350 /* CDR fields remain the same */ 02351 /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */ 02352 /* Application and data remain the same */ 02353 /* Clone exception becomes real one, as with fdno */ 02354 original->exception = clone->exception; 02355 original->fdno = clone->fdno; 02356 /* Schedule context remains the same */ 02357 /* Stream stuff stays the same */ 02358 /* Keep the original state. The fixup code will need to work with it most likely */ 02359 02360 /* dnid and callerid change to become the new, HOWEVER, we also link the original's 02361 fields back into the defunct 'clone' so that they will be freed when 02362 ast_frfree is eventually called */ 02363 tmp = original->dnid; 02364 original->dnid = clone->dnid; 02365 clone->dnid = tmp; 02366 02367 tmp = original->callerid; 02368 original->callerid = clone->callerid; 02369 clone->callerid = tmp; 02370 02371 /* Restore original timing file descriptor */ 02372 original->fds[AST_MAX_FDS - 2] = original->timingfd; 02373 02374 /* Our native formats are different now */ 02375 original->nativeformats = clone->nativeformats; 02376 02377 /* Context, extension, priority, app data, jump table, remain the same */ 02378 /* pvt switches. pbx stays the same, as does next */ 02379 02380 /* Set the write format */ 02381 ast_set_write_format(original, wformat); 02382 02383 /* Set the read format */ 02384 ast_set_read_format(original, rformat); 02385 02386 /* Copy the music class */ 02387 strncpy(original->musicclass, clone->musicclass, sizeof(original->musicclass) - 1); 02388 02389 ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat); 02390 02391 /* Okay. Last thing is to let the channel driver know about all this mess, so he 02392 can fix up everything as best as possible */ 02393 if (original->pvt->fixup) { 02394 res = original->pvt->fixup(clone, original); 02395 if (res) { 02396 ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n", 02397 original->type, original->name); 02398 ast_mutex_unlock(&clone->lock); 02399 return -1; 02400 } 02401 } else 02402 ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)! Bad things may happen.\n", 02403 original->type, original->name); 02404 02405 /* Now, at this point, the "clone" channel is totally F'd up. We mark it as 02406 a zombie so nothing tries to touch it. If it's already been marked as a 02407 zombie, then free it now (since it already is considered invalid). */ 02408 if (clone->zombie) { 02409 ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name); 02410 ast_mutex_unlock(&clone->lock); 02411 ast_channel_free(clone); 02412 manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn); 02413 } else { 02414 struct ast_frame null_frame = { AST_FRAME_NULL, }; 02415 ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name); 02416 clone->zombie=1; 02417 ast_queue_frame(clone, &null_frame); 02418 ast_mutex_unlock(&clone->lock); 02419 } 02420 02421 /* Signal any blocker */ 02422 if (original->blocking) 02423 pthread_kill(original->blocker, SIGURG); 02424 ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n", 02425 original->name, original->_state); 02426 return 0; 02427 }
| struct ast_channel* ast_get_channel_by_name_locked | ( | char * | channame | ) | [read] |
Get channel by name (locks channel).
Definition at line 510 of file channel.c.
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 }
| unsigned int ast_get_group | ( | char * | s | ) |
Definition at line 2908 of file channel.c.
02909 { 02910 char *copy; 02911 char *piece; 02912 char *c=NULL; 02913 int start=0, finish=0,x; 02914 unsigned int group = 0; 02915 copy = ast_strdupa(s); 02916 if (!copy) { 02917 ast_log(LOG_ERROR, "Out of memory\n"); 02918 return 0; 02919 } 02920 c = copy; 02921 02922 while((piece = strsep(&c, ","))) { 02923 if (sscanf(piece, "%d-%d", &start, &finish) == 2) { 02924 /* Range */ 02925 } else if (sscanf(piece, "%d", &start)) { 02926 /* Just one */ 02927 finish = start; 02928 } else { 02929 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.\n", s, piece); 02930 continue; 02931 } 02932 for (x=start;x<=finish;x++) { 02933 if ((x > 31) || (x < 0)) { 02934 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x); 02935 } else 02936 group |= (1 << x); 02937 } 02938 } 02939 return group; 02940 }
| int ast_hangup | ( | struct ast_channel * | chan | ) |
Hang up a channel.
| chan | channel to hang up This function performs a hard hangup on a channel. Unlike the soft-hangup, this function performs all stream stopping, etc, on the channel that needs to end. chan is no longer valid after this call. Returns 0 on success, -1 on failure. |
Definition at line 689 of file channel.c.
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 }
| int ast_indicate | ( | struct ast_channel * | chan, | |
| int | condition | |||
| ) |
Indicates condition of channel.
| chan | channel to change the indication | |
| condition | which condition to indicate on the channel Indicate a condition such as AST_CONTROL_BUSY, AST_CONTROL_RINGING, or AST_CONTROL_CONGESTION on a channel Returns 0 on success, -1 on failure |
Definition at line 1411 of file channel.c.
01412 { 01413 int res = -1; 01414 /* Stop if we're a zombie or need a soft hangup */ 01415 if (chan->zombie || ast_check_hangup(chan)) 01416 return -1; 01417 ast_mutex_lock(&chan->lock); 01418 if (chan->pvt->indicate) 01419 res = chan->pvt->indicate(chan, condition); 01420 ast_mutex_unlock(&chan->lock); 01421 if (!chan->pvt->indicate || res) { 01422 /* 01423 * Device does not support (that) indication, lets fake 01424 * it by doing our own tone generation. (PM2002) 01425 */ 01426 if (condition >= 0) { 01427 const struct tone_zone_sound *ts = NULL; 01428 switch (condition) { 01429 case AST_CONTROL_RINGING: 01430 ts = ast_get_indication_tone(chan->zone, "ring"); 01431 break; 01432 case AST_CONTROL_BUSY: 01433 ts = ast_get_indication_tone(chan->zone, "busy"); 01434 break; 01435 case AST_CONTROL_CONGESTION: 01436 ts = ast_get_indication_tone(chan->zone, "congestion"); 01437 break; 01438 } 01439 if (ts && ts->data[0]) { 01440 ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition); 01441 ast_playtones_start(chan,0,ts->data, 1); 01442 res = 0; 01443 } else if (condition == AST_CONTROL_PROGRESS) { 01444 /* ast_playtones_stop(chan); */ 01445 } else if (condition == AST_CONTROL_PROCEEDING) { 01446 /* Do nothing, really */ 01447 } else { 01448 /* not handled */ 01449 ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name); 01450 res = -1; 01451 } 01452 } 01453 else ast_playtones_stop(chan); 01454 } 01455 return res; 01456 }
| int ast_parse_device_state | ( | char * | device | ) |
Search the Channels by Name.
| device | like a dialstring Search the Device in active channels by compare the channelname against the devicename. Compared are only the first chars to the first '-' char. Returns an AST_DEVICE_UNKNOWN if no channel found or AST_DEVICE_INUSE if a channel is found |
Definition at line 1918 of file channel.c.
01919 { 01920 char name[AST_CHANNEL_NAME] = ""; 01921 char *cut; 01922 struct ast_channel *chan; 01923 01924 chan = ast_channel_walk_locked(NULL); 01925 while (chan) { 01926 strncpy(name, chan->name, sizeof(name)-1); 01927 ast_mutex_unlock(&chan->lock); 01928 cut = strchr(name,'-'); 01929 if (cut) 01930 *cut = 0; 01931 if (!strcmp(name, device)) 01932 return AST_DEVICE_INUSE; 01933 chan = ast_channel_walk_locked(chan); 01934 } 01935 return AST_DEVICE_UNKNOWN; 01936 }
| int ast_prod | ( | struct ast_channel * | chan | ) |
Definition at line 1549 of file channel.c.
01550 { 01551 struct ast_frame a = { AST_FRAME_VOICE }; 01552 char nothing[128]; 01553 /* Send an empty audio frame to get things moving */ 01554 if (chan->_state != AST_STATE_UP) { 01555 ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name); 01556 a.subclass = chan->pvt->rawwriteformat; 01557 a.data = nothing + AST_FRIENDLY_OFFSET; 01558 if (ast_write(chan, &a)) 01559 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name); 01560 } 01561 return 0; 01562 }
| struct ast_frame* ast_read | ( | struct ast_channel * | chan | ) | [read] |
Reads a frame.
| chan | channel to read a frame from Read a frame. Returns a frame, or NULL on error. If it returns NULL, you best just stop reading frames and assume the channel has been disconnected. |
Definition at line 1192 of file channel.c.
01193 { 01194 struct ast_frame *f = NULL; 01195 int blah; 01196 #ifdef ZAPTEL_OPTIMIZATIONS 01197 int (*func)(void *); 01198 void *data; 01199 int res; 01200 #endif 01201 static struct ast_frame null_frame = 01202 { 01203 AST_FRAME_NULL, 01204 }; 01205 01206 ast_mutex_lock(&chan->lock); 01207 if (chan->masq) { 01208 if (ast_do_masquerade(chan)) { 01209 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 01210 f = NULL; 01211 } else 01212 f = &null_frame; 01213 ast_mutex_unlock(&chan->lock); 01214 return f; 01215 } 01216 01217 /* Stop if we're a zombie or need a soft hangup */ 01218 if (chan->zombie || ast_check_hangup(chan)) { 01219 if (chan->generator) 01220 ast_deactivate_generator(chan); 01221 ast_mutex_unlock(&chan->lock); 01222 return NULL; 01223 } 01224 01225 if (!chan->deferdtmf && !ast_strlen_zero(chan->dtmfq)) { 01226 /* We have DTMF that has been deferred. Return it now */ 01227 chan->dtmff.frametype = AST_FRAME_DTMF; 01228 chan->dtmff.subclass = chan->dtmfq[0]; 01229 /* Drop first digit */ 01230 memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1); 01231 ast_mutex_unlock(&chan->lock); 01232 return &chan->dtmff; 01233 } 01234 01235 /* Read and ignore anything on the alertpipe, but read only 01236 one sizeof(blah) per frame that we send from it */ 01237 if (chan->pvt->alertpipe[0] > -1) { 01238 read(chan->pvt->alertpipe[0], &blah, sizeof(blah)); 01239 } 01240 #ifdef ZAPTEL_OPTIMIZATIONS 01241 if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) { 01242 chan->exception = 0; 01243 blah = -1; 01244 /* IF we can't get event, assume it's an expired as-per the old interface */ 01245 res = ioctl(chan->timingfd, ZT_GETEVENT, &blah); 01246 if (res) 01247 blah = ZT_EVENT_TIMER_EXPIRED; 01248 01249 if (blah == ZT_EVENT_TIMER_PING) { 01250 #if 0 01251 ast_log(LOG_NOTICE, "Oooh, there's a PING!\n"); 01252 #endif 01253 if (!chan->pvt->readq || !chan->pvt->readq->next) { 01254 /* Acknowledge PONG unless we need it again */ 01255 #if 0 01256 ast_log(LOG_NOTICE, "Sending a PONG!\n"); 01257 #endif 01258 if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) { 01259 ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno)); 01260 } 01261 } 01262 } else if (blah == ZT_EVENT_TIMER_EXPIRED) { 01263 ioctl(chan->timingfd, ZT_TIMERACK, &blah); 01264 func = chan->timingfunc; 01265 data = chan->timingdata; 01266 ast_mutex_unlock(&chan->lock); 01267 if (func) { 01268 #if 0 01269 ast_log(LOG_DEBUG, "Calling private function\n"); 01270 #endif 01271 func(data); 01272 } else { 01273 blah = 0; 01274 ast_mutex_lock(&chan->lock); 01275 ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah); 01276 chan->timingdata = NULL; 01277 ast_mutex_unlock(&chan->lock); 01278 } 01279 f = &null_frame; 01280 return f; 01281 } else 01282 ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name); 01283 } 01284 #endif 01285 /* Check for pending read queue */ 01286 if (chan->pvt->readq) { 01287 f = chan->pvt->readq; 01288 chan->pvt->readq = f->next; 01289 /* Interpret hangup and return NULL */ 01290 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) { 01291 ast_frfree(f); 01292 f = NULL; 01293 } 01294 } else { 01295 chan->blocker = pthread_self(); 01296 if (chan->exception) { 01297 if (chan->pvt->exception) 01298 f = chan->pvt->exception(chan); 01299 else { 01300 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name); 01301 f = &null_frame; 01302 } 01303 /* Clear the exception flag */ 01304 chan->exception = 0; 01305 } else 01306 if (chan->pvt->read) 01307 f = chan->pvt->read(chan); 01308 else 01309 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name); 01310 } 01311 01312 01313 if (f && (f->frametype == AST_FRAME_VOICE)) { 01314 if (!(f->subclass & chan->nativeformats)) { 01315 /* This frame can't be from the current native formats -- drop it on the 01316 floor */ 01317 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)); 01318 ast_frfree(f); 01319 f = &null_frame; 01320 } else { 01321 if (chan->monitor && chan->monitor->read_stream ) { 01322 #ifndef MONITOR_CONSTANT_DELAY 01323 int jump = chan->outsmpl - chan->insmpl - 2 * f->samples; 01324 if (jump >= 0) { 01325 if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1) 01326 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 01327 chan->insmpl += jump + 2 * f->samples; 01328 } else 01329 chan->insmpl+= f->samples; 01330 #else 01331 int jump = chan->outsmpl - chan->insmpl; 01332 if (jump - MONITOR_DELAY >= 0) { 01333 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) 01334 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 01335 chan->insmpl += jump; 01336 } else 01337 chan->insmpl += f->samples; 01338 #endif 01339 if (ast_writestream(chan->monitor->read_stream, f) < 0) 01340 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n"); 01341 } 01342 if (chan->pvt->readtrans) { 01343 f = ast_translate(chan->pvt->readtrans, f, 1); 01344 if (!f) 01345 f = &null_frame; 01346 } 01347 } 01348 } 01349 01350 /* Make sure we always return NULL in the future */ 01351 if (!f) { 01352 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01353 if (chan->generator) 01354 ast_deactivate_generator(chan); 01355 /* End the CDR if appropriate */ 01356 if (chan->cdr) 01357 ast_cdr_end(chan->cdr); 01358 } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) { 01359 if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) 01360 chan->dtmfq[strlen(chan->dtmfq)] = f->subclass; 01361 else 01362 ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name); 01363 f = &null_frame; 01364 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) { 01365 if (chan->_state == AST_STATE_UP) { 01366 ast_log(LOG_DEBUG, "Dropping duplicate answer!\n"); 01367 f = &null_frame; 01368 } 01369 /* Answer the CDR */ 01370 ast_setstate(chan, AST_STATE_UP); 01371 ast_cdr_answer(chan->cdr); 01372 } 01373 01374 /* Run any generator sitting on the line */ 01375 if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) { 01376 /* Mask generator data temporarily and apply. If there is a timing function, it 01377 will be calling the generator instead */ 01378 void *tmp; 01379 int res; 01380 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples); 01381 if (chan->timingfunc) { 01382 ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n"); 01383 ast_settimeout(chan, 0, NULL, NULL); 01384 } 01385 tmp = chan->generatordata; 01386 chan->generatordata = NULL; 01387 generate = chan->generator->generate; 01388 res = generate(chan, tmp, f->datalen, f->samples); 01389 chan->generatordata = tmp; 01390 if (res) { 01391 ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); 01392 ast_deactivate_generator(chan); 01393 } 01394 } else if (f && (f->frametype == AST_FRAME_CNG)) { 01395 if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) { 01396 ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n"); 01397 ast_settimeout(chan, 160, generator_force, chan); 01398 } 01399 } 01400 /* High bit prints debugging */ 01401 if (chan->fin & 0x80000000) 01402 ast_frame_dump(chan->name, f, "<<"); 01403 if ((chan->fin & 0x7fffffff) == 0x7fffffff) 01404 chan->fin &= 0x80000000; 01405 else 01406 chan->fin++; 01407 ast_mutex_unlock(&chan->lock); 01408 return f; 01409 }
| int ast_readstring | ( | struct ast_channel * | c, | |
| char * | s, | |||
| int | len, | |||
| int | timeout, | |||
| int | rtimeout, | |||
| char * | enders | |||
| ) |
Reads multiple digits.
| c | channel to read from | |
| s | string to read in to. Must be at least the size of your length | |
| len | how many digits to read (maximum) | |
| timeout | how long to timeout between digits | |
| rtimeout | timeout to wait on the first digit | |
| enders | digits to end the string Read in a digit string "s", max length "len", maximum timeout between digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout for the first digit. Returns 0 on normal return, or 1 on a timeout. In the case of a timeout, any digits that were read before the timeout will still be available in s. RETURNS 2 in full version when ctrlfd is available, NOT 1 |
Definition at line 2012 of file channel.c.
02013 { 02014 int pos=0; 02015 int to = ftimeout; 02016 int d; 02017 /* XXX Merge with full version? XXX */ 02018 /* Stop if we're a zombie or need a soft hangup */ 02019 if (c->zombie || ast_check_hangup(c)) 02020 return -1; 02021 if (!len) 02022 return -1; 02023 do { 02024 if (c->stream) { 02025 d = ast_waitstream(c, AST_DIGIT_ANY); 02026 ast_stopstream(c); 02027 usleep(1000); 02028 if (!d) 02029 d = ast_waitfordigit(c, to); 02030 } else { 02031 d = ast_waitfordigit(c, to); 02032 } 02033 if (d < 0) 02034 return -1; 02035 if (d == 0) { 02036 s[pos]='\0'; 02037 return 1; 02038 } 02039 if (!strchr(enders, d)) 02040 s[pos++] = d; 02041 if (strchr(enders, d) || (pos >= len)) { 02042 s[pos]='\0'; 02043 return 0; 02044 } 02045 to = timeout; 02046 } while(1); 02047 /* Never reached */ 02048 return 0; 02049 }
| int ast_readstring_full | ( | struct ast_channel * | c, | |
| char * | s, | |||
| int | len, | |||
| int | timeout, | |||
| int | rtimeout, | |||
| char * | enders, | |||
| int | audiofd, | |||
| int | ctrlfd | |||
| ) |
Definition at line 2051 of file channel.c.
02052 { 02053 int pos=0; 02054 int to = ftimeout; 02055 int d; 02056 /* Stop if we're a zombie or need a soft hangup */ 02057 if (c->zombie || ast_check_hangup(c)) 02058 return -1; 02059 if (!len) 02060 return -1; 02061 do { 02062 if (c->stream) { 02063 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd); 02064 ast_stopstream(c); 02065 usleep(1000); 02066 if (!d) 02067 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 02068 } else { 02069 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 02070 } 02071 if (d < 0) 02072 return -1; 02073 if (d == 0) { 02074 s[pos]='\0'; 02075 return 1; 02076 } 02077 if (d == 1) { 02078 s[pos]='\0'; 02079 return 2; 02080 } 02081 if (!strchr(enders, d)) 02082 s[pos++] = d; 02083 if (strchr(enders, d) || (pos >= len)) { 02084 s[pos]='\0'; 02085 return 0; 02086 } 02087 to = timeout; 02088 } while(1); 02089 /* Never reached */ 02090 return 0; 02091 }
| int ast_recvchar | ( | struct ast_channel * | chan, | |
| int | timeout | |||
| ) |
Definition at line 1458 of file channel.c.
01459 { 01460 int res,ourto,c; 01461 struct ast_frame *f; 01462 01463 ourto = timeout; 01464 for(;;) 01465 { 01466 if (ast_check_hangup(chan)) return -1; 01467 res = ast_waitfor(chan,ourto); 01468 if (res <= 0) /* if timeout */ 01469 { 01470 return 0; 01471 } 01472 ourto = res; 01473 f = ast_read(chan); 01474 if (f == NULL) return -1; /* if hangup */ 01475 if ((f->frametype == AST_FRAME_CONTROL) && 01476 (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */ 01477 if (f->frametype == AST_FRAME_TEXT) /* if a text frame */ 01478 { 01479 c = *((char *)f->data); /* get the data */ 01480 ast_frfree(f); 01481 return(c); 01482 } 01483 ast_frfree(f); 01484 } 01485 }
| struct ast_channel* ast_request | ( | char * | type, | |
| int | format, | |||
| void * | data | |||
| ) | [read] |
Requests a channel.
| type | type of channel to request | |
| format | requested channel format | |
| data | data to pass to the channel requester Request a channel of a given type, with data as optional information used by the low level module Returns an ast_channel on success, NULL on failure. |
Definition at line 1873 of file channel.c.
01874 { 01875 struct chanlist *chan; 01876 struct ast_channel *c = NULL; 01877 int capabilities; 01878 int fmt; 01879 int res; 01880 if (ast_mutex_lock(&chlock)) { 01881 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 01882 return NULL; 01883 } 01884 chan = backends; 01885 while(chan) { 01886 if (!strcasecmp(type, chan->type)) { 01887 capabilities = chan->capabilities; 01888 fmt = format; 01889 res = ast_translator_best_choice(&fmt, &capabilities); 01890 if (res < 0) { 01891 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format); 01892 ast_mutex_unlock(&chlock); 01893 return NULL; 01894 } 01895 ast_mutex_unlock(&chlock); 01896 if (chan->requester) 01897 c = chan->requester(type, capabilities, data); 01898 if (c) { 01899 if (c->_state == AST_STATE_DOWN) { 01900 manager_event(EVENT_FLAG_CALL, "Newchannel", 01901 "Channel: %s\r\n" 01902 "State: %s\r\n" 01903 "CallerID: %s\r\n" 01904 "Uniqueid: %s\r\n", 01905 c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid); 01906 } 01907 } 01908 return c; 01909 } 01910 chan = chan->next; 01911 } 01912 if (!chan) 01913 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type); 01914 ast_mutex_unlock(&chlock); 01915 return c; 01916 }
| struct ast_channel* ast_request_and_dial | ( | char * | type, | |
| int | format, | |||
| void * | data, | |||
| int | timeout, | |||
| int * | reason, | |||
| char * | callerid | |||
| ) | [read] |
| type | type of channel to request | |
| format | requested channel format | |
| data | data to pass to the channel requester | |
| timeout | maximum amount of time to wait for an answer | |
| why | unsuccessful (if unsuceessful) Request a channel of a given type, with data as optional information used by the low level module and attempt to place a call on it Returns an ast_channel on success or no answer, NULL on failure. Check the value of chan->_state to know if the call was answered or not. |
Definition at line 1868 of file channel.c.
01869 { 01870 return __ast_request_and_dial(type, format, data, timeout, outstate, callerid, NULL); 01871 }
| int ast_safe_sleep | ( | struct ast_channel * | chan, | |
| int | ms | |||
| ) |
Wait for a specied amount of time, looking for hangups.
| chan | channel to wait for | |
| ms | length of time in milliseconds to sleep Waits for a specified amount of time, servicing the channel as required. returns -1 on hangup, otherwise 0. |
Definition at line 544 of file channel.c.
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 }
| int ast_safe_sleep_conditional | ( | struct ast_channel * | chan, | |
| int | ms, | |||
| int(*)(void *) | cond, | |||
| void * | data | |||
| ) |
Wait for a specied amount of time, looking for hangups and a condition argument.
| chan | channel to wait for | |
| ms | length of time in milliseconds to sleep | |
| cond | a function pointer for testing continue condition | |
| data | argument to be passed to the condition test function Waits for a specified amount of time, servicing the channel as required. If cond returns 0, this function returns. returns -1 on hangup, otherwise 0. |
Definition at line 523 of file channel.c.
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 }
| int ast_senddigit | ( | struct ast_channel * | chan, | |
| char | digit | |||
| ) |
| int ast_sendtext | ( | struct ast_channel * | chan, | |
| char * | text | |||
| ) |
Sends text to a channel.
| chan | channel to act upon | |
| text | string of text to send on the channel Write text to a display on a channel Returns 0 on success, -1 on failure |
Definition at line 1487 of file channel.c.
01488 { 01489 int res = 0; 01490 /* Stop if we're a zombie or need a soft hangup */ 01491 if (chan->zombie || ast_check_hangup(chan)) 01492 return -1; 01493 CHECK_BLOCKING(chan); 01494 if (chan->pvt->send_text) 01495 res = chan->pvt->send_text(chan, text); 01496 chan->blocking = 0; 01497 return res; 01498 }
| void ast_set_callerid | ( | struct ast_channel * | chan, | |
| char * | callerid, | |||
| int | anitoo | |||
| ) |
Definition at line 2429 of file channel.c.
02430 { 02431 if (chan->callerid) 02432 free(chan->callerid); 02433 if (anitoo && chan->ani) 02434 free(chan->ani); 02435 if (callerid) { 02436 chan->callerid = strdup(callerid); 02437 if (anitoo) 02438 chan->ani = strdup(callerid); 02439 } else { 02440 chan->callerid = NULL; 02441 if (anitoo) 02442 chan->ani = NULL; 02443 } 02444 if (chan->cdr) 02445 ast_cdr_setcid(chan->cdr, chan); 02446 manager_event(EVENT_FLAG_CALL, "Newcallerid", 02447 "Channel: %s\r\n" 02448 "CallerID: %s\r\n" 02449 "Uniqueid: %s\r\n", 02450 chan->name, chan->callerid ? 02451 chan->callerid : "<Unknown>", 02452 chan->uniqueid); 02453 }
| int ast_set_read_format | ( | struct ast_channel * | chan, | |
| int | format | |||
| ) |
Sets read format on channel chan.
| chan | channel to change | |
| format | format to change to Set read format for channel to whichever component of "format" is best. Returns 0 on success, -1 on failure |
Definition at line 1724 of file channel.c.
01725 { 01726 int fmt; 01727 int native; 01728 int res; 01729 01730 ast_mutex_lock(&chan->lock); 01731 native = chan->nativeformats; 01732 fmt = fmts; 01733 /* Find a translation path from the native read format to one of the user's read formats */ 01734 res = ast_translator_best_choice(&fmt, &native); 01735 if (res < 0) { 01736 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n", 01737 ast_getformatname(chan->nativeformats), ast_getformatname(fmts)); 01738 ast_mutex_unlock(&chan->lock); 01739 return -1; 01740 } 01741 01742 /* Now we have a good choice for both. We'll write using our native format. */ 01743 chan->pvt->rawreadformat = native; 01744 /* User perspective is fmt */ 01745 chan->readformat = fmt; 01746 /* Free any read translation we have right now */ 01747 if (chan->pvt->readtrans) 01748 ast_translator_free_path(chan->pvt->readtrans); 01749 /* Build a translation path from the raw read format to the user reading format */ 01750 chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat); 01751 if (option_debug) 01752 ast_log(LOG_DEBUG, "Set channel %s to read format %s\n", 01753 chan->name, ast_getformatname(chan->readformat)); 01754 ast_mutex_unlock(&chan->lock); 01755 return 0; 01756 }
| int ast_set_write_format | ( | struct ast_channel * | chan, | |
| int | format | |||
| ) |
Sets write format on channel chan.
| chan | channel to change | |
| format | new format for writing Set write format for channel to whichever compoent of "format" is best. Returns 0 on success, -1 on failure |
Definition at line 1691 of file channel.c.
01692 { 01693 int fmt; 01694 int native; 01695 int res; 01696 01697 ast_mutex_lock(&chan->lock); 01698 native = chan->nativeformats; 01699 fmt = fmts; 01700 01701 res = ast_translator_best_choice(&native, &fmt); 01702 if (res < 0) { 01703 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n", 01704 ast_getformatname(fmts), ast_getformatname(chan->nativeformats)); 01705 ast_mutex_unlock(&chan->lock); 01706 return -1; 01707 } 01708 01709 /* Now we have a good choice for both. We'll write using our native format. */ 01710 chan->pvt->rawwriteformat = native; 01711 /* User perspective is fmt */ 01712 chan->writeformat = fmt; 01713 /* Free any write translation we have right now */ 01714 if (chan->pvt->writetrans) 01715 ast_translator_free_path(chan->pvt->writetrans); 01716 /* Build a translation path from the user write format to the raw writing format */ 01717 chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat); 01718 if (option_debug) 01719 ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat)); 01720 ast_mutex_unlock(&chan->lock); 01721 return 0; 01722 }
| int ast_settimeout | ( | struct ast_channel * | c, | |
| int | samples, | |||
| int(*)(void *data) | func, | |||
| void * | data | |||
| ) |
Definition at line 1119 of file channel.c.
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 }
| int ast_shutting_down | ( | void | ) |
| int ast_softhangup | ( | struct ast_channel * | chan, | |
| int | cause | |||
| ) |
Softly hangup up a channel.
| chan | channel to be soft-hung-up Call the protocol layer, but don't destroy the channel structure (use this if you are trying to safely hangup a channel managed by another thread. Returns 0 regardless |
Definition at line 668 of file channel.c.
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 }
| int ast_softhangup_nolock | ( | struct ast_channel * | chan, | |
| int | cause | |||
| ) |
Definition at line 653 of file channel.c.
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 }
| char* ast_state2str | ( | int | state | ) |
Gives the string form of a given state.
| state | state to get the name of Give a name to a state Pretty self explanatory. Returns the text form of the binary state given |
Definition at line 205 of file channel.c.
00206 { 00207 /* XXX Not reentrant XXX */ 00208 static char localtmp[256]; 00209 switch(state) { 00210 case AST_STATE_DOWN: 00211 return "Down"; 00212 case AST_STATE_RESERVED: 00213 return "Rsrvd"; 00214 case AST_STATE_OFFHOOK: 00215 return "OffHook"; 00216 case AST_STATE_DIALING: 00217 return "Dialing"; 00218 case AST_STATE_RING: 00219 return "Ring"; 00220 case AST_STATE_RINGING: 00221 return "Ringing"; 00222 case AST_STATE_UP: 00223 return "Up"; 00224 case AST_STATE_BUSY: 00225 return "Busy"; 00226 default: 00227 snprintf(localtmp, sizeof(localtmp), "Unknown (%d)\n", state); 00228 return localtmp; 00229 } 00230 }
| int ast_tonepair | ( | struct ast_channel * | chan, | |
| int | freq1, | |||
| int | freq2, | |||
| int | duration, | |||
| int | vol | |||
| ) |
Play a tone pair for a given amount of time
Definition at line 2890 of file channel.c.
02891 { 02892 struct ast_frame *f; 02893 int res; 02894 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol))) 02895 return res; 02896 02897 /* Give us some wiggle room */ 02898 while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) { 02899 f = ast_read(chan); 02900 if (f) 02901 ast_frfree(f); 02902 else 02903 return -1; 02904 } 02905 return 0; 02906 }
| int ast_tonepair_start | ( | struct ast_channel * | chan, | |
| int | freq1, | |||
| int | freq2, | |||
| int | duration, | |||
| int | vol | |||
| ) |
Start a tone going
Definition at line 2870 of file channel.c.
02871 { 02872 struct tonepair_def d = { 0, }; 02873 d.freq1 = freq1; 02874 d.freq2 = freq2; 02875 d.duration = duration; 02876 if (vol < 1) 02877 d.vol = 8192; 02878 else 02879 d.vol = vol; 02880 if (ast_activate_generator(chan, &tonepair, &d)) 02881 return -1; 02882 return 0; 02883 }
| void ast_tonepair_stop | ( | struct ast_channel * | chan | ) |
Stop a tone from playing
Definition at line 2885 of file channel.c.
02886 { 02887 ast_deactivate_generator(chan); 02888 }
| int ast_transfer | ( | struct ast_channel * | chan, | |
| char * | dest | |||
| ) |
Definition at line 1992 of file channel.c.
01993 { 01994 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 01995 If the remote end does not answer within the timeout, then do NOT hang up, but 01996 return anyway. */ 01997 int res = -1; 01998 /* Stop if we're a zombie or need a soft hangup */ 01999 ast_mutex_lock(&chan->lock); 02000 if (!chan->zombie && !ast_check_hangup(chan)) { 02001 if (chan->pvt->transfer) { 02002 res = chan->pvt->transfer(chan, dest); 02003 if (!res) 02004 res = 1; 02005 } else 02006 res = 0; 02007 } 02008 ast_mutex_unlock(&chan->lock); 02009 return res; 02010 }
| int ast_waitfor | ( | struct ast_channel * | chan, | |
| int | ms | |||
| ) |
Wait for input on a channel.
| chan | channel to wait on | |
| ms | length of time to wait on the channel Wait for input on a channel for a given # of milliseconds (<0 for indefinite). Returns < 0 on failure, 0 if nothing ever arrived, and the # of ms remaining otherwise |
Definition at line 1078 of file channel.c.
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 }
| struct ast_channel* ast_waitfor_n | ( | struct ast_channel ** | chan, | |
| int | n, | |||
| int * | ms | |||
| ) | [read] |
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.
01074 { 01075 return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms); 01076 }
| int ast_waitfor_n_fd | ( | int * | fds, | |
| int | n, | |||
| int * | ms, | |||
| int * | exception | |||
| ) |
Waits for input on an fd.
This version works on fd's only. Be careful with it.
Definition at line 869 of file channel.c.
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 }
| struct ast_channel* ast_waitfor_nandfds | ( | struct ast_channel ** | chan, | |
| int | n, | |||
| int * | fds, | |||
| int | nfds, | |||
| int * | exception, | |||
| int * | outfd, | |||
| int * | ms | |||
| ) | [read] |
Waits for activity on a group of channels.
| chan | an array of pointers to channels | |
| n | number of channels that are to be waited upon | |
| fds | an array of fds to wait upon | |
| nfds | the number of fds to wait upon | |
| exception | exception flag | |
| outfd | fd that had activity on it | |
| ms | how long the wait was Big momma function here. Wait for activity on any of the n channels, or any of the nfds file descriptors. Returns the channel with activity, or NULL on error or if an FD came first. If the FD came first, it will be returned in outfd, otherwise, outfd will be -1 |
Definition at line 930 of file channel.c.
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 }
| int ast_waitfordigit | ( | struct ast_channel * | c, | |
| int | ms | |||
| ) |
Waits for a digit.
| c | channel to wait for a digit on | |
| ms | how many milliseconds to wait Wait for a digit. Returns <0 on error, 0 on no entry, and the digit on success. |
Definition at line 1092 of file channel.c.
01093 { 01094 /* XXX Should I be merged with waitfordigit_full XXX */ 01095 struct ast_frame *f; 01096 int 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 }
| int ast_waitfordigit_full | ( | struct ast_channel * | c, | |
| int | ms, | |||
| int | audiofd, | |||
| int | ctrlfd | |||
| ) |
Definition at line 1136 of file channel.c.
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 errno = 0; 01148 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 01149 if ((!rchan) && (outfd < 0) && (ms)) { 01150 if (errno == 0 || errno == EINTR) 01151 continue; 01152 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 01153 return -1; 01154 } else if (outfd > -1) { 01155 /* The FD we were watching has something waiting */ 01156 return 1; 01157 } else if (rchan) { 01158 f = ast_read(c); 01159 if(!f) { 01160 return -1; 01161 } 01162 01163 switch(f->frametype) { 01164 case AST_FRAME_DTMF: 01165 res = f->subclass; 01166 ast_frfree(f); 01167 return res; 01168 case AST_FRAME_CONTROL: 01169 switch(f->subclass) { 01170 case AST_CONTROL_HANGUP: 01171 ast_frfree(f); 01172 return -1; 01173 case AST_CONTROL_RINGING: 01174 case AST_CONTROL_ANSWER: 01175 /* Unimportant */ 01176 break; 01177 default: 01178 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass); 01179 } 01180 case AST_FRAME_VOICE: 01181 /* Write audio if appropriate */ 01182 if (audiofd > -1) 01183 write(audiofd, f->data, f->datalen); 01184 } 01185 /* Ignore */ 01186 ast_frfree(f); 01187 } 01188 } 01189 return 0; // Time is up 01190 }
| int ast_write | ( | struct ast_channel * | chan, | |
| struct ast_frame * | frame | |||
| ) |
Write a frame to a channel.
| chan | destination channel of the frame | |
| frame | frame that will be written This function writes the given frame to the indicated channel. It returns 0 on success, -1 on failure. |
Definition at line 1575 of file channel.c.
01576 { 01577 int res = -1; 01578 struct ast_frame *f = NULL; 01579 /* Stop if we're a zombie or need a soft hangup */ 01580 ast_mutex_lock(&chan->lock); 01581 if (chan->zombie || ast_check_hangup(chan)) { 01582 ast_mutex_unlock(&chan->lock); 01583 return -1; 01584 } 01585 /* Handle any pending masquerades */ 01586 if (chan->masq) { 01587 if (ast_do_masquerade(chan)) { 01588 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 01589 ast_mutex_unlock(&chan->lock); 01590 return -1; 01591 } 01592 } 01593 if (chan->masqr) { 01594 ast_mutex_unlock(&chan->lock); 01595 return 0; 01596 } 01597 if (chan->generatordata) { 01598 if (chan->writeinterrupt) 01599 ast_deactivate_generator(chan); 01600 else { 01601 ast_mutex_unlock(&chan->lock); 01602 return 0; 01603 } 01604 } 01605 /* High bit prints debugging */ 01606 if (chan->fout & 0x80000000) 01607 ast_frame_dump(chan->name, fr, ">>"); 01608 CHECK_BLOCKING(chan); 01609 switch(fr->frametype) { 01610 case AST_FRAME_CONTROL: 01611 /* XXX Interpret control frames XXX */ 01612 ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n"); 01613 break; 01614 case AST_FRAME_DTMF: 01615 chan->blocking = 0; 01616 ast_mutex_unlock(&chan->lock); 01617 res = do_senddigit(chan,fr->subclass); 01618 ast_mutex_lock(&chan->lock); 01619 CHECK_BLOCKING(chan); 01620 break; 01621 case AST_FRAME_TEXT: 01622 if (chan->pvt->send_text) 01623 res = chan->pvt->send_text(chan, (char *) fr->data); 01624 else 01625 res = 0; 01626 break; 01627 case AST_FRAME_HTML: 01628 if (chan->pvt->send_html) 01629 res = chan->pvt->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen); 01630 else 01631 res = 0; 01632 break; 01633 case AST_FRAME_VIDEO: 01634 /* XXX Handle translation of video codecs one day XXX */ 01635 if (chan->pvt->write_video) 01636 res = chan->pvt->write_video(chan, fr); 01637 else 01638 res = 0; 01639 break; 01640 default: 01641 if (chan->pvt->write) { 01642 if (chan->pvt->writetrans) { 01643 f = ast_translate(chan->pvt->writetrans, fr, 0); 01644 } else 01645 f = fr; 01646 if (f) { 01647 res = chan->pvt->write(chan, f); 01648 if( chan->monitor && 01649 chan->monitor->write_stream && 01650 f && ( f->frametype == AST_FRAME_VOICE ) ) { 01651 #ifndef MONITOR_CONSTANT_DELAY 01652 int jump = chan->insmpl - chan->outsmpl - 2 * f->samples; 01653 if (jump >= 0) { 01654 if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1) 01655 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 01656 chan->outsmpl += jump + 2 * f->samples; 01657 } else 01658 chan->outsmpl += f->samples; 01659 #else 01660 int jump = chan->insmpl - chan->outsmpl; 01661 if (jump - MONITOR_DELAY >= 0) { 01662 if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1) 01663 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 01664 chan->outsmpl += jump; 01665 } else 01666 chan->outsmpl += f->samples; 01667 #endif 01668 if (ast_writestream(chan->monitor->write_stream, f) < 0) 01669 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n"); 01670 } 01671 } else 01672 res = 0; 01673 } 01674 } 01675 if (f && (f != fr)) 01676 ast_frfree(f); 01677 chan->blocking = 0; 01678 /* Consider a write failure to force a soft hangup */ 01679 if (res < 0) 01680 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01681 else { 01682 if ((chan->fout & 0x7fffffff) == 0x7fffffff) 01683 chan->fout &= 0x80000000; 01684 else 01685 chan->fout++; 01686 } 01687 ast_mutex_unlock(&chan->lock); 01688 return res; 01689 }
| int ast_write_video | ( | struct ast_channel * | chan, | |
| struct ast_frame * | frame | |||
| ) |
Write video frame to a channel.
| chan | destination channel of the frame | |
| frame | frame that will be written This function writes the given frame to the indicated channel. It returns 1 on success, 0 if not implemented, and -1 on failure. |
Definition at line 1564 of file channel.c.
01565 { 01566 int res; 01567 if (!chan->pvt->write_video) 01568 return 0; 01569 res = ast_write(chan, fr); 01570 if (!res) 01571 res = 1; 01572 return res; 01573 }
1.5.6