#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <math.h>
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/chanspy.h"
#include "asterisk/musiconhold.h"
#include "asterisk/logger.h"
#include "asterisk/say.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/translate.h"
#include "asterisk/manager.h"
#include "asterisk/chanvars.h"
#include "asterisk/linkedlists.h"
#include "asterisk/indications.h"
#include "asterisk/monitor.h"
#include "asterisk/causes.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/transcap.h"
#include "asterisk/devicestate.h"
#include "asterisk/sha1.h"
#include "asterisk/threadstorage.h"
#include "asterisk/slinfactory.h"
Go to the source code of this file.
Data Structures | |
struct | ast_cause |
struct | ast_channel_spy_list |
struct | ast_channel_whisper_buffer |
struct | ast_silence_generator |
struct | chanlist |
struct | channel_spy_trans |
struct | tonepair_def |
struct | tonepair_state |
Defines | |
#define | AST_DEFAULT_EMULATE_DTMF_DURATION 100 |
#define | AST_MIN_DTMF_DURATION 80 |
#define | AST_MIN_DTMF_GAP 45 |
#define | FORMAT "%-10.10s %-40.40s %-12.12s %-12.12s %-12.12s\n" |
#define | SPY_QUEUE_SAMPLE_LIMIT 4000 |
#define | STATE2STR_BUFSIZE 32 |
Enumerations | |
enum | spy_direction { SPY_READ, SPY_WRITE } |
Functions | |
static struct ast_frame * | __ast_read (struct ast_channel *chan, int dropaudio) |
struct ast_channel * | __ast_request_and_dial (const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh) |
int | ast_activate_generator (struct ast_channel *chan, struct ast_generator *gen, void *params) |
int | ast_active_channels (void) |
returns number of active/allocated channels | |
int | ast_answer (struct ast_channel *chan) |
Answer a ringing call. | |
void | ast_begin_shutdown (int hangup) |
Initiate system shutdown. | |
int | ast_best_codec (int fmts) |
Pick the best audio codec. | |
struct ast_channel * | ast_bridged_channel (struct ast_channel *chan) |
Find bridged channel. | |
int | ast_call (struct ast_channel *chan, char *addr, int timeout) |
Make a call. | |
void | ast_cancel_shutdown (void) |
Cancel a shutdown in progress. | |
const char * | ast_cause2str (int cause) |
Gives the string form of a given hangup cause. | |
void | ast_change_name (struct ast_channel *chan, char *newname) |
Change channel name. | |
struct ast_channel * | ast_channel_alloc (int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt,...) |
Create a new channel structure. | |
enum ast_bridge_result | 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_cmpwhentohangup (struct ast_channel *chan, time_t offset) |
Compare a offset with when to hangup channel. | |
int | ast_channel_datastore_add (struct ast_channel *chan, struct ast_datastore *datastore) |
Add a datastore to a channel. | |
struct ast_datastore * | ast_channel_datastore_alloc (const struct ast_datastore_info *info, char *uid) |
Create a channel datastore structure. | |
struct ast_datastore * | ast_channel_datastore_find (struct ast_channel *chan, const struct ast_datastore_info *info, char *uid) |
Find a datastore on a channel. | |
int | ast_channel_datastore_free (struct ast_datastore *datastore) |
Free a channel datastore structure. | |
int | ast_channel_datastore_remove (struct ast_channel *chan, struct ast_datastore *datastore) |
Remove a datastore from a channel. | |
int | ast_channel_defer_dtmf (struct ast_channel *chan) |
Set defer DTMF flag on channel. | |
void | ast_channel_free (struct ast_channel *chan) |
Free a channel structure. | |
void | ast_channel_inherit_variables (const struct ast_channel *parent, struct ast_channel *child) |
Inherits channel variable from parent to child channel. | |
int | ast_channel_make_compatible (struct ast_channel *chan, struct ast_channel *peer) |
Makes two channel formats compatible. | |
int | ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone) |
Weird function made for call transfers. | |
int | ast_channel_register (const struct ast_channel_tech *tech) |
Register a new telephony channel in Asterisk. | |
int | ast_channel_sendhtml (struct ast_channel *chan, int subclass, const char *data, int datalen) |
int | ast_channel_sendurl (struct ast_channel *chan, const char *url) |
int | ast_channel_setoption (struct ast_channel *chan, int option, void *data, int datalen, int block) |
Sets an option on a channel. | |
void | ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset) |
Set when to hangup channel. | |
int | ast_channel_spy_add (struct ast_channel *chan, struct ast_channel_spy *spy) |
Adds a spy to a channel, to begin receiving copies of the channel's audio frames. | |
void | ast_channel_spy_free (struct ast_channel_spy *spy) |
Free a spy. | |
struct ast_frame * | ast_channel_spy_read_frame (struct ast_channel_spy *spy, unsigned int samples) |
Read one (or more) frames of audio from a channel being spied upon. | |
void | ast_channel_spy_remove (struct ast_channel *chan, struct ast_channel_spy *spy) |
Remove a spy from a channel. | |
void | ast_channel_spy_stop_by_type (struct ast_channel *chan, const char *type) |
Find all spies of a particular type on a channel and stop them. | |
void | ast_channel_spy_trigger_wait (struct ast_channel_spy *spy) |
Efficiently wait until audio is available for a spy, or an exception occurs. | |
struct ast_silence_generator * | ast_channel_start_silence_generator (struct ast_channel *chan) |
Starts a silence generator on the given channel. | |
void | ast_channel_stop_silence_generator (struct ast_channel *chan, struct ast_silence_generator *state) |
Stops a previously-started silence generator on the given channel. | |
int | ast_channel_supports_html (struct ast_channel *chan) |
void | ast_channel_undefer_dtmf (struct ast_channel *chan) |
Unset defer DTMF flag on channel. | |
void | ast_channel_unregister (const struct ast_channel_tech *tech) |
Unregister a channel technology. | |
struct ast_channel * | ast_channel_walk_locked (const struct ast_channel *prev) |
Browse channels in use. | |
int | ast_channel_whisper_feed (struct ast_channel *chan, struct ast_frame *f) |
Feed an audio frame into the whisper buffer on a channel. | |
int | ast_channel_whisper_start (struct ast_channel *chan) |
Begin 'whispering' onto a channel. | |
void | ast_channel_whisper_stop (struct ast_channel *chan) |
Stop 'whispering' onto a channel. | |
void | ast_channels_init (void) |
struct ast_variable * | ast_channeltype_list (void) |
return an ast_variable list of channeltypes | |
int | ast_check_hangup (struct ast_channel *chan) |
Checks to see if a channel is needing hang up. | |
static int | ast_check_hangup_locked (struct ast_channel *chan) |
void | ast_deactivate_generator (struct ast_channel *chan) |
int | ast_do_masquerade (struct ast_channel *original) |
Masquerade a channel. | |
static enum ast_bridge_result | ast_generic_bridge (struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc, struct timeval bridge_end) |
struct ast_channel * | ast_get_channel_by_exten_locked (const char *exten, const char *context) |
Get channel by exten (and optionally context) and lock it. | |
struct ast_channel * | ast_get_channel_by_name_locked (const char *name) |
Get channel by name and lock it. | |
struct ast_channel * | ast_get_channel_by_name_prefix_locked (const char *name, const int namelen) |
Get channel by name prefix and lock it. | |
struct ast_channel_tech * | ast_get_channel_tech (const char *name) |
Get a channel technology structure by name. | |
ast_group_t | ast_get_group (const char *s) |
int | ast_hangup (struct ast_channel *chan) |
Hangup a channel. | |
int | ast_indicate (struct ast_channel *chan, int condition) |
Indicates condition of channel. | |
int | ast_indicate_data (struct ast_channel *chan, int condition, const void *data, size_t datalen) |
Indicates condition of channel, with payload. | |
void | ast_install_music_functions (int(*start_ptr)(struct ast_channel *, const char *, const char *), void(*stop_ptr)(struct ast_channel *), void(*cleanup_ptr)(struct ast_channel *)) |
int | ast_internal_timing_enabled (struct ast_channel *chan) |
Check if the channel can run in internal timing mode. | |
static | AST_LIST_HEAD_NOLOCK_STATIC (backends, chanlist) |
static | AST_LIST_HEAD_STATIC (channels, ast_channel) |
void | ast_moh_cleanup (struct ast_channel *chan) |
int | ast_moh_start (struct ast_channel *chan, const char *mclass, const char *interpclass) |
Turn on music on hold on a given channel. | |
void | ast_moh_stop (struct ast_channel *chan) |
Turn off music on hold on a given channel. | |
char * | ast_print_group (char *buf, int buflen, ast_group_t group) |
Print call group and pickup group ---. | |
int | ast_prod (struct ast_channel *chan) |
Send empty audio to prime a channel driver. | |
int | ast_queue_control (struct ast_channel *chan, enum ast_control_frame_type control) |
Queue a control frame. | |
int | ast_queue_control_data (struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen) |
Queue a control frame with payload. | |
int | ast_queue_frame (struct ast_channel *chan, struct ast_frame *fin) |
Queue an outgoing media frame. | |
int | ast_queue_hangup (struct ast_channel *chan) |
Queue a hangup frame for channel. | |
struct ast_frame * | ast_read (struct ast_channel *chan) |
Reads a frame. | |
static void | ast_read_generator_actions (struct ast_channel *chan, struct ast_frame *f) |
struct ast_frame * | ast_read_noaudio (struct ast_channel *chan) |
Reads a frame, returning AST_FRAME_NULL frame if audio. Read a frame. | |
int | ast_readstring (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders) |
int | ast_readstring_full (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd) |
int | ast_recvchar (struct ast_channel *chan, int timeout) |
Receives a text character from a channel. | |
char * | ast_recvtext (struct ast_channel *chan, int timeout) |
Receives a text string from a channel Read a string of text from a channel. | |
struct ast_channel * | ast_request (const char *type, int format, void *data, int *cause) |
Requests a channel. | |
struct ast_channel * | ast_request_and_dial (const char *type, int format, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname) |
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. | |
int | ast_safe_sleep (struct ast_channel *chan, int ms) |
Wait, look for hangups. | |
int | ast_safe_sleep_conditional (struct ast_channel *chan, int ms, int(*cond)(void *), void *data) |
Wait, look for hangups and condition arg. | |
char * | ast_safe_string_alloc (const char *fmt,...) |
printf the string into a correctly sized mallocd buffer, and return the buffer | |
int | ast_say_character_str (struct ast_channel *chan, const char *str, const char *ints, const char *lang) |
int | ast_say_digit_str (struct ast_channel *chan, const char *str, const char *ints, const char *lang) |
int | ast_say_digits (struct ast_channel *chan, int num, const char *ints, const char *lang) |
int | ast_say_digits_full (struct ast_channel *chan, int num, const char *ints, const char *lang, int audiofd, int ctrlfd) |
int | ast_say_enumeration (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options) |
int | ast_say_number (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options) |
int | ast_say_phonetic_str (struct ast_channel *chan, const char *str, const char *ints, const char *lang) |
int | ast_senddigit (struct ast_channel *chan, char digit) |
Send a DTMF digit to a channel Send a DTMF digit to a channel. | |
int | ast_senddigit_begin (struct ast_channel *chan, char digit) |
int | ast_senddigit_end (struct ast_channel *chan, char digit, unsigned int duration) |
int | ast_sendtext (struct ast_channel *chan, const char *text) |
Sends text to a channel Write text to a display on a channel. | |
void | ast_set_callerid (struct ast_channel *chan, const char *callerid, const char *calleridname, const char *ani) |
int | ast_set_read_format (struct ast_channel *chan, int fmt) |
Sets read format on channel chan Set read format for channel to whichever component of "format" is best. | |
void | ast_set_variables (struct ast_channel *chan, struct ast_variable *vars) |
adds a list of channel variables to a channel | |
int | ast_set_write_format (struct ast_channel *chan, int fmt) |
Sets write format on channel chan Set write format for channel to whichever compoent of "format" is best. | |
int | ast_setstate (struct ast_channel *chan, enum ast_channel_state state) |
Change the state of a channel. | |
int | ast_settimeout (struct ast_channel *c, int samples, int(*func)(void *data), void *data) |
int | ast_shutting_down (void) |
Returns non-zero if Asterisk is being shut down. | |
int | ast_softhangup (struct ast_channel *chan, int cause) |
Softly hangup a channel, lock. | |
int | ast_softhangup_nolock (struct ast_channel *chan, int cause) |
Softly hangup a channel, don't lock. | |
char * | ast_state2str (enum ast_channel_state state) |
Gives the string form of a given channel state. | |
int | ast_str2cause (const char *name) |
Convert a symbolic hangup cause to number. | |
AST_THREADSTORAGE (state2str_threadbuf, state2str_threadbuf_init) | |
int | ast_tonepair (struct ast_channel *chan, int freq1, int freq2, int duration, int vol) |
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_transfer (struct ast_channel *chan, char *dest) |
Transfer a call to dest, if the channel supports transfer. | |
char * | ast_transfercapability2str (int transfercapability) |
Gives the string form of a given transfer capability. | |
void | ast_uninstall_music_functions (void) |
int | ast_waitfor (struct ast_channel *c, int ms) |
Wait for input on a channel. | |
struct ast_channel * | ast_waitfor_n (struct ast_channel **c, int n, int *ms) |
Waits for input on a group of channels Wait for input on an array of channels for a given # of milliseconds. | |
int | ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception) |
Wait for x amount of time on a file descriptor to have input. | |
struct ast_channel * | ast_waitfor_nandfds (struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms) |
Wait for x amount of time on a file descriptor to have input. | |
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 cmdfd) |
Wait for a digit Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading. | |
struct ast_channel * | ast_walk_channel_by_exten_locked (const struct ast_channel *chan, const char *exten, const char *context) |
Get next channel by exten (and optionally context) and lock it. | |
struct ast_channel * | ast_walk_channel_by_name_prefix_locked (const struct ast_channel *chan, const char *name, const int namelen) |
Get next channel by name prefix and lock it. | |
int | ast_write (struct ast_channel *chan, struct ast_frame *fr) |
Write a frame to a channel This function writes the given frame to the indicated channel. | |
int | ast_write_video (struct ast_channel *chan, struct ast_frame *fr) |
Write video frame to a channel This function writes the given frame to the indicated channel. | |
static void | bridge_playfile (struct ast_channel *chan, struct ast_channel *peer, const char *sound, int remain) |
static struct ast_channel * | channel_find_locked (const struct ast_channel *prev, const char *name, const int namelen, const char *context, const char *exten) |
Helper function to find channels. | |
const char * | channelreloadreason2txt (enum channelreloadreason reason) |
Convert enum channelreloadreason to text string for manager event. | |
static void | clone_variables (struct ast_channel *original, struct ast_channel *clone) |
Clone channel variables from 'clone' channel into 'original' channel. | |
static char * | complete_channeltypes (const char *line, const char *word, int pos, int state) |
static char * | complete_channeltypes_deprecated (const char *line, const char *word, int pos, int state) |
static void | copy_data_from_queue (struct ast_channel_spy_queue *queue, short *buf, unsigned int samples) |
static void | detach_spies (struct ast_channel *chan) |
static void | free_cid (struct ast_callerid *cid) |
static void | free_translation (struct ast_channel *clone) |
static int | generator_force (void *data) |
static void | queue_frame_to_spies (struct ast_channel *chan, struct ast_frame *f, enum spy_direction dir) |
static int | set_format (struct ast_channel *chan, int fmt, int *rawformat, int *format, struct ast_trans_pvt **trans, const int direction) |
static int | show_channeltype (int fd, int argc, char *argv[]) |
static int | show_channeltype_deprecated (int fd, int argc, char *argv[]) |
static int | show_channeltypes (int fd, int argc, char *argv[]) |
static void * | silence_generator_alloc (struct ast_channel *chan, void *data) |
static int | silence_generator_generate (struct ast_channel *chan, void *data, int len, int samples) |
static void | silence_generator_release (struct ast_channel *chan, void *data) |
static void | spy_cleanup (struct ast_channel *chan) |
static void | spy_detach (struct ast_channel_spy *spy, struct ast_channel *chan) |
static void * | tonepair_alloc (struct ast_channel *chan, void *params) |
static int | tonepair_generator (struct ast_channel *chan, void *data, int len, int samples) |
static void | tonepair_release (struct ast_channel *chan, void *params) |
Variables | |
static void(* | ast_moh_cleanup_ptr )(struct ast_channel *) = NULL |
static int(* | ast_moh_start_ptr )(struct ast_channel *, const char *, const char *) = NULL |
static void(* | ast_moh_stop_ptr )(struct ast_channel *) = NULL |
struct ast_cause | causes [] |
static struct ast_cli_entry | cli_channel [] |
static struct ast_cli_entry | cli_show_channeltype_deprecated |
static struct ast_cli_entry | cli_show_channeltypes_deprecated |
unsigned long | global_fin |
unsigned long | global_fout |
static struct ast_channel_tech | null_tech |
static char | show_channeltype_usage [] |
static char | show_channeltypes_usage [] |
static int | shutting_down |
static struct ast_generator | silence_generator |
static struct ast_generator | tonepair |
static int | uniqueint |
Definition in file channel.c.
#define AST_DEFAULT_EMULATE_DTMF_DURATION 100 |
Default amount of time to use when emulating a digit as a begin and end 100ms
Definition at line 109 of file channel.c.
Referenced by __ast_read(), and ast_senddigit().
#define AST_MIN_DTMF_DURATION 80 |
Minimum allowed digit length - 80ms
Definition at line 112 of file channel.c.
Referenced by __ast_read().
#define AST_MIN_DTMF_GAP 45 |
Minimum amount of time between the end of the last digit and the beginning of a new one - 45ms
Definition at line 116 of file channel.c.
Referenced by __ast_read().
#define FORMAT "%-10.10s %-40.40s %-12.12s %-12.12s %-12.12s\n" |
#define SPY_QUEUE_SAMPLE_LIMIT 4000 |
#define STATE2STR_BUFSIZE 32 |
enum spy_direction |
static struct ast_frame* __ast_read | ( | struct ast_channel * | chan, | |
int | dropaudio | |||
) | [static, read] |
Definition at line 2177 of file channel.c.
References ast_channel::_softhangup, ast_channel::_state, ast_channel::alertpipe, ast_cdr_alloc(), ast_cdr_answer(), ast_cdr_end(), ast_cdr_init(), ast_cdr_start(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, ast_deactivate_generator(), AST_DEFAULT_EMULATE_DTMF_DURATION, ast_do_masquerade(), AST_FLAG_DEFER_DTMF, AST_FLAG_EMULATE_DTMF, AST_FLAG_END_DTMF_ONLY, AST_FLAG_EXCEPTION, AST_FLAG_IN_DTMF, AST_FLAG_OUTGOING, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frame_dump(), AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), AST_GENERATOR_FD, ast_getformatname(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_SET_NOLOCK, AST_LIST_NEXT, AST_LIST_REMOVE_HEAD, ast_log(), AST_MIN_DTMF_DURATION, AST_MIN_DTMF_GAP, AST_MONITOR_RUNNING, ast_null_frame, ast_read_generator_actions(), ast_seekstream(), ast_set_flag, ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_strlen_zero(), ast_test_flag, AST_TIMING_FD, ast_translate(), ast_writestream(), ast_channel::blocker, ast_channel::cdr, ast_frame::data, DEBUGCHAN_FLAG, ast_channel::dtmf_tv, ast_channel::dtmff, ast_channel::dtmfq, ast_channel::emulate_dtmf_digit, ast_channel::emulate_dtmf_duration, ast_channel_tech::exception, f, ast_channel::fdno, ast_channel::fds, ast_channel::fin, FRAMECOUNT_INC, ast_frame::frametype, func, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, ast_channel::insmpl, ast_frame::len, LOG_DEBUG, LOG_DTMF, LOG_NOTICE, LOG_WARNING, ast_channel::masq, ast_channel::monitor, ast_channel::nativeformats, option_debug, ast_channel::outsmpl, queue_frame_to_spies(), ast_channel_tech::read, ast_channel_monitor::read_stream, ast_channel::readtrans, ast_frame::samples, SEEK_FORCECUR, ast_channel::spies, SPY_READ, ast_channel_monitor::state, ast_frame::subclass, ast_channel::tech, ast_channel::timingdata, ast_channel::timingfd, and ast_channel::timingfunc.
Referenced by ast_read(), and ast_read_noaudio().
02178 { 02179 struct ast_frame *f = NULL; /* the return value */ 02180 int blah; 02181 int prestate; 02182 02183 /* this function is very long so make sure there is only one return 02184 * point at the end (there is only one exception to this). 02185 */ 02186 ast_channel_lock(chan); 02187 if (chan->masq) { 02188 if (ast_do_masquerade(chan)) 02189 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 02190 else 02191 f = &ast_null_frame; 02192 goto done; 02193 } 02194 02195 /* Stop if we're a zombie or need a soft hangup */ 02196 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 02197 if (chan->generator) 02198 ast_deactivate_generator(chan); 02199 goto done; 02200 } 02201 prestate = chan->_state; 02202 02203 if (!ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF | AST_FLAG_IN_DTMF) && 02204 !ast_strlen_zero(chan->dtmfq) && 02205 (ast_tvzero(chan->dtmf_tv) || ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) > AST_MIN_DTMF_GAP) ) { 02206 /* We have DTMF that has been deferred. Return it now */ 02207 chan->dtmff.subclass = chan->dtmfq[0]; 02208 /* Drop first digit from the buffer */ 02209 memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1); 02210 f = &chan->dtmff; 02211 if (ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) { 02212 ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass, chan->name); 02213 chan->dtmff.frametype = AST_FRAME_DTMF_END; 02214 } else { 02215 ast_log(LOG_DTMF, "DTMF begin emulation of '%c' with duration %d queued on %s\n", f->subclass, AST_DEFAULT_EMULATE_DTMF_DURATION, chan->name); 02216 chan->dtmff.frametype = AST_FRAME_DTMF_BEGIN; 02217 ast_set_flag(chan, AST_FLAG_EMULATE_DTMF); 02218 chan->emulate_dtmf_digit = f->subclass; 02219 chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION; 02220 } 02221 chan->dtmf_tv = ast_tvnow(); 02222 goto done; 02223 } 02224 02225 /* Read and ignore anything on the alertpipe, but read only 02226 one sizeof(blah) per frame that we send from it */ 02227 if (chan->alertpipe[0] > -1) 02228 read(chan->alertpipe[0], &blah, sizeof(blah)); 02229 02230 #ifdef HAVE_ZAPTEL 02231 if (chan->timingfd > -1 && chan->fdno == AST_TIMING_FD && ast_test_flag(chan, AST_FLAG_EXCEPTION)) { 02232 int res; 02233 02234 ast_clear_flag(chan, AST_FLAG_EXCEPTION); 02235 blah = -1; 02236 /* IF we can't get event, assume it's an expired as-per the old interface */ 02237 res = ioctl(chan->timingfd, ZT_GETEVENT, &blah); 02238 if (res) 02239 blah = ZT_EVENT_TIMER_EXPIRED; 02240 02241 if (blah == ZT_EVENT_TIMER_PING) { 02242 if (AST_LIST_EMPTY(&chan->readq) || !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) { 02243 /* Acknowledge PONG unless we need it again */ 02244 if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) { 02245 ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno)); 02246 } 02247 } 02248 } else if (blah == ZT_EVENT_TIMER_EXPIRED) { 02249 ioctl(chan->timingfd, ZT_TIMERACK, &blah); 02250 if (chan->timingfunc) { 02251 /* save a copy of func/data before unlocking the channel */ 02252 int (*func)(void *) = chan->timingfunc; 02253 void *data = chan->timingdata; 02254 ast_channel_unlock(chan); 02255 func(data); 02256 } else { 02257 blah = 0; 02258 ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah); 02259 chan->timingdata = NULL; 02260 ast_channel_unlock(chan); 02261 } 02262 /* cannot 'goto done' because the channel is already unlocked */ 02263 return &ast_null_frame; 02264 } else 02265 ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name); 02266 } else 02267 #endif 02268 if (chan->fds[AST_GENERATOR_FD] > -1 && chan->fdno == AST_GENERATOR_FD) { 02269 /* if the AST_GENERATOR_FD is set, call the generator with args 02270 * set to -1 so it can do whatever it needs to. 02271 */ 02272 void *tmp = chan->generatordata; 02273 chan->generatordata = NULL; /* reset to let ast_write get through */ 02274 chan->generator->generate(chan, tmp, -1, -1); 02275 chan->generatordata = tmp; 02276 f = &ast_null_frame; 02277 goto done; 02278 } 02279 02280 /* Check for pending read queue */ 02281 if (!AST_LIST_EMPTY(&chan->readq)) { 02282 f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list); 02283 /* Interpret hangup and return NULL */ 02284 /* XXX why not the same for frames from the channel ? */ 02285 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) { 02286 ast_frfree(f); 02287 f = NULL; 02288 } 02289 } else { 02290 chan->blocker = pthread_self(); 02291 if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) { 02292 if (chan->tech->exception) 02293 f = chan->tech->exception(chan); 02294 else { 02295 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name); 02296 f = &ast_null_frame; 02297 } 02298 /* Clear the exception flag */ 02299 ast_clear_flag(chan, AST_FLAG_EXCEPTION); 02300 } else if (chan->tech->read) 02301 f = chan->tech->read(chan); 02302 else 02303 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name); 02304 } 02305 02306 if (f) { 02307 /* if the channel driver returned more than one frame, stuff the excess 02308 into the readq for the next ast_read call (note that we can safely assume 02309 that the readq is empty, because otherwise we would not have called into 02310 the channel driver and f would be only a single frame) 02311 */ 02312 if (AST_LIST_NEXT(f, frame_list)) { 02313 AST_LIST_HEAD_SET_NOLOCK(&chan->readq, AST_LIST_NEXT(f, frame_list)); 02314 AST_LIST_NEXT(f, frame_list) = NULL; 02315 } 02316 02317 switch (f->frametype) { 02318 case AST_FRAME_CONTROL: 02319 if (f->subclass == AST_CONTROL_ANSWER) { 02320 if (!ast_test_flag(chan, AST_FLAG_OUTGOING)) { 02321 if (option_debug) 02322 ast_log(LOG_DEBUG, "Ignoring answer on an inbound call!\n"); 02323 ast_frfree(f); 02324 f = &ast_null_frame; 02325 } else if (prestate == AST_STATE_UP) { 02326 if (option_debug) 02327 ast_log(LOG_DEBUG, "Dropping duplicate answer!\n"); 02328 ast_frfree(f); 02329 f = &ast_null_frame; 02330 } else { 02331 /* Answer the CDR */ 02332 ast_setstate(chan, AST_STATE_UP); 02333 if (!chan->cdr) { /* up till now, this insertion hasn't been done. Therefore, 02334 to keep from throwing off the basic order of the universe, 02335 we will try to keep this cdr from getting posted. */ 02336 chan->cdr = ast_cdr_alloc(); 02337 ast_cdr_init(chan->cdr, chan); 02338 ast_cdr_start(chan->cdr); 02339 } 02340 02341 ast_cdr_answer(chan->cdr); 02342 } 02343 } 02344 break; 02345 case AST_FRAME_DTMF_END: 02346 ast_log(LOG_DTMF, "DTMF end '%c' received on %s, duration %ld ms\n", f->subclass, chan->name, f->len); 02347 /* Queue it up if DTMF is deffered, or if DTMF emulation is forced. 02348 * However, only let emulation be forced if the other end cares about BEGIN frames */ 02349 if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF) || 02350 (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) ) { 02351 if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) { 02352 ast_log(LOG_DTMF, "DTMF end '%c' put into dtmf queue on %s\n", f->subclass, chan->name); 02353 chan->dtmfq[strlen(chan->dtmfq)] = f->subclass; 02354 } else 02355 ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name); 02356 ast_frfree(f); 02357 f = &ast_null_frame; 02358 } else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) { 02359 if (!ast_tvzero(chan->dtmf_tv) && 02360 ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) { 02361 /* If it hasn't been long enough, defer this digit */ 02362 if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) { 02363 ast_log(LOG_DTMF, "DTMF end '%c' put into dtmf queue on %s\n", f->subclass, chan->name); 02364 chan->dtmfq[strlen(chan->dtmfq)] = f->subclass; 02365 } else 02366 ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name); 02367 ast_frfree(f); 02368 f = &ast_null_frame; 02369 } else { 02370 /* There was no begin, turn this into a begin and send the end later */ 02371 f->frametype = AST_FRAME_DTMF_BEGIN; 02372 ast_set_flag(chan, AST_FLAG_EMULATE_DTMF); 02373 chan->emulate_dtmf_digit = f->subclass; 02374 chan->dtmf_tv = ast_tvnow(); 02375 if (f->len) { 02376 if (f->len > AST_MIN_DTMF_DURATION) 02377 chan->emulate_dtmf_duration = f->len; 02378 else 02379 chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION; 02380 } else 02381 chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION; 02382 ast_log(LOG_DTMF, "DTMF begin emulation of '%c' with duration %u queued on %s\n", f->subclass, chan->emulate_dtmf_duration, chan->name); 02383 } 02384 } else { 02385 struct timeval now = ast_tvnow(); 02386 if (ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 02387 ast_log(LOG_DTMF, "DTMF end accepted with begin '%c' on %s\n", f->subclass, chan->name); 02388 ast_clear_flag(chan, AST_FLAG_IN_DTMF); 02389 if (!f->len) 02390 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 02391 } else if (!f->len) { 02392 ast_log(LOG_DTMF, "DTMF end accepted without begin '%c' on %s\n", f->subclass, chan->name); 02393 f->len = AST_MIN_DTMF_DURATION; 02394 } 02395 if (f->len < AST_MIN_DTMF_DURATION) { 02396 ast_log(LOG_DTMF, "DTMF end '%c' has duration %ld but want minimum %d, emulating on %s\n", f->subclass, f->len, AST_MIN_DTMF_DURATION, chan->name); 02397 ast_set_flag(chan, AST_FLAG_EMULATE_DTMF); 02398 chan->emulate_dtmf_digit = f->subclass; 02399 chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION - f->len; 02400 f = &ast_null_frame; 02401 } else { 02402 ast_log(LOG_DTMF, "DTMF end passthrough '%c' on %s\n", f->subclass, chan->name); 02403 chan->dtmf_tv = now; 02404 } 02405 } 02406 break; 02407 case AST_FRAME_DTMF_BEGIN: 02408 ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass, chan->name); 02409 if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY) || 02410 (!ast_tvzero(chan->dtmf_tv) && 02411 ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) ) { 02412 ast_frfree(f); 02413 f = &ast_null_frame; 02414 ast_log(LOG_DTMF, "DTMF begin ignored '%c' on %s\n", f->subclass, chan->name); 02415 } else { 02416 ast_set_flag(chan, AST_FLAG_IN_DTMF); 02417 chan->dtmf_tv = ast_tvnow(); 02418 ast_log(LOG_DTMF, "DTMF begin passthrough '%c' on %s\n", f->subclass, chan->name); 02419 } 02420 break; 02421 case AST_FRAME_NULL: 02422 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) { 02423 struct timeval now = ast_tvnow(); 02424 if (ast_tvdiff_ms(now, chan->dtmf_tv) >= chan->emulate_dtmf_duration) { 02425 chan->emulate_dtmf_duration = 0; 02426 ast_frfree(f); 02427 f = &chan->dtmff; 02428 f->frametype = AST_FRAME_DTMF_END; 02429 f->subclass = chan->emulate_dtmf_digit; 02430 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 02431 chan->dtmf_tv = now; 02432 ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF); 02433 chan->emulate_dtmf_digit = 0; 02434 ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass, chan->name); 02435 } 02436 } 02437 break; 02438 case AST_FRAME_VOICE: 02439 /* The EMULATE_DTMF flag must be cleared here as opposed to when the duration 02440 * is reached , because we want to make sure we pass at least one 02441 * voice frame through before starting the next digit, to ensure a gap 02442 * between DTMF digits. */ 02443 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !chan->emulate_dtmf_duration) { 02444 ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF); 02445 chan->emulate_dtmf_digit = 0; 02446 } 02447 02448 if (dropaudio || ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 02449 if (dropaudio) 02450 ast_read_generator_actions(chan, f); 02451 ast_frfree(f); 02452 f = &ast_null_frame; 02453 } 02454 02455 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 02456 struct timeval now = ast_tvnow(); 02457 if (ast_tvdiff_ms(now, chan->dtmf_tv) >= chan->emulate_dtmf_duration) { 02458 chan->emulate_dtmf_duration = 0; 02459 ast_frfree(f); 02460 f = &chan->dtmff; 02461 f->frametype = AST_FRAME_DTMF_END; 02462 f->subclass = chan->emulate_dtmf_digit; 02463 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 02464 chan->dtmf_tv = now; 02465 ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass, chan->name); 02466 } else { 02467 /* Drop voice frames while we're still in the middle of the digit */ 02468 ast_frfree(f); 02469 f = &ast_null_frame; 02470 } 02471 } else if ((f->frametype == AST_FRAME_VOICE) && !(f->subclass & chan->nativeformats)) { 02472 /* This frame can't be from the current native formats -- drop it on the 02473 floor */ 02474 ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", 02475 chan->name, ast_getformatname(f->subclass), ast_getformatname(chan->nativeformats)); 02476 ast_frfree(f); 02477 f = &ast_null_frame; 02478 } else if ((f->frametype == AST_FRAME_VOICE)) { 02479 if (chan->spies) 02480 queue_frame_to_spies(chan, f, SPY_READ); 02481 02482 if (chan->monitor && chan->monitor->read_stream ) { 02483 /* XXX what does this do ? */ 02484 #ifndef MONITOR_CONSTANT_DELAY 02485 int jump = chan->outsmpl - chan->insmpl - 4 * f->samples; 02486 if (jump >= 0) { 02487 jump = chan->outsmpl - chan->insmpl; 02488 if (ast_seekstream(chan->monitor->read_stream, jump, SEEK_FORCECUR) == -1) 02489 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 02490 chan->insmpl += jump + f->samples; 02491 } else 02492 chan->insmpl+= f->samples; 02493 #else 02494 int jump = chan->outsmpl - chan->insmpl; 02495 if (jump - MONITOR_DELAY >= 0) { 02496 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) 02497 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 02498 chan->insmpl += jump; 02499 } else 02500 chan->insmpl += f->samples; 02501 #endif 02502 if (chan->monitor->state == AST_MONITOR_RUNNING) { 02503 if (ast_writestream(chan->monitor->read_stream, f) < 0) 02504 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n"); 02505 } 02506 } 02507 02508 if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL) 02509 f = &ast_null_frame; 02510 02511 /* Run generator sitting on the line if timing device not available 02512 * and synchronous generation of outgoing frames is necessary */ 02513 ast_read_generator_actions(chan, f); 02514 } 02515 default: 02516 /* Just pass it on! */ 02517 break; 02518 } 02519 } else { 02520 /* Make sure we always return NULL in the future */ 02521 chan->_softhangup |= AST_SOFTHANGUP_DEV; 02522 if (chan->generator) 02523 ast_deactivate_generator(chan); 02524 /* End the CDR if appropriate */ 02525 if (chan->cdr) 02526 ast_cdr_end(chan->cdr); 02527 } 02528 02529 /* High bit prints debugging */ 02530 if (chan->fin & DEBUGCHAN_FLAG) 02531 ast_frame_dump(chan->name, f, "<<"); 02532 chan->fin = FRAMECOUNT_INC(chan->fin); 02533 02534 done: 02535 ast_channel_unlock(chan); 02536 return f; 02537 }
struct ast_channel* __ast_request_and_dial | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int | timeout, | |||
int * | outstate, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct outgoing_helper * | oh | |||
) | [read] |
Definition at line 3037 of file channel.c.
Referenced by ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_request_and_dial(), and parkandannounce_exec().
03038 { 03039 int dummy_outstate; 03040 int cause = 0; 03041 struct ast_channel *chan; 03042 int res = 0; 03043 03044 if (outstate) 03045 *outstate = 0; 03046 else 03047 outstate = &dummy_outstate; /* make outstate always a valid pointer */ 03048 03049 chan = ast_request(type, format, data, &cause); 03050 if (!chan) { 03051 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 03052 /* compute error and return */ 03053 if (cause == AST_CAUSE_BUSY) 03054 *outstate = AST_CONTROL_BUSY; 03055 else if (cause == AST_CAUSE_CONGESTION) 03056 *outstate = AST_CONTROL_CONGESTION; 03057 return NULL; 03058 } 03059 03060 if (oh) { 03061 if (oh->vars) 03062 ast_set_variables(chan, oh->vars); 03063 /* XXX why is this necessary, for the parent_channel perhaps ? */ 03064 if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) 03065 ast_set_callerid(chan, oh->cid_num, oh->cid_name, oh->cid_num); 03066 if (oh->parent_channel) 03067 ast_channel_inherit_variables(oh->parent_channel, chan); 03068 if (oh->account) 03069 ast_cdr_setaccount(chan, oh->account); 03070 } 03071 ast_set_callerid(chan, cid_num, cid_name, cid_num); 03072 03073 03074 03075 if (!chan->cdr) { /* up till now, this insertion hasn't been done. Therefore, 03076 to keep from throwing off the basic order of the universe, 03077 we will try to keep this cdr from getting posted. */ 03078 chan->cdr = ast_cdr_alloc(); 03079 ast_cdr_init(chan->cdr, chan); 03080 ast_cdr_start(chan->cdr); 03081 } 03082 if (ast_call(chan, data, 0)) { /* ast_call failed... */ 03083 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data); 03084 } else { 03085 res = 1; /* mark success in case chan->_state is already AST_STATE_UP */ 03086 while (timeout && chan->_state != AST_STATE_UP) { 03087 struct ast_frame *f; 03088 res = ast_waitfor(chan, timeout); 03089 if (res <= 0) /* error, timeout, or done */ 03090 break; 03091 if (timeout > -1) 03092 timeout = res; 03093 f = ast_read(chan); 03094 if (!f) { 03095 *outstate = AST_CONTROL_HANGUP; 03096 res = 0; 03097 break; 03098 } 03099 if (f->frametype == AST_FRAME_CONTROL) { 03100 switch (f->subclass) { 03101 case AST_CONTROL_RINGING: /* record but keep going */ 03102 *outstate = f->subclass; 03103 break; 03104 03105 case AST_CONTROL_BUSY: 03106 case AST_CONTROL_CONGESTION: 03107 case AST_CONTROL_ANSWER: 03108 *outstate = f->subclass; 03109 timeout = 0; /* trick to force exit from the while() */ 03110 break; 03111 03112 /* Ignore these */ 03113 case AST_CONTROL_PROGRESS: 03114 case AST_CONTROL_PROCEEDING: 03115 case AST_CONTROL_HOLD: 03116 case AST_CONTROL_UNHOLD: 03117 case AST_CONTROL_VIDUPDATE: 03118 case -1: /* Ignore -- just stopping indications */ 03119 break; 03120 03121 default: 03122 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass); 03123 } 03124 } 03125 ast_frfree(f); 03126 } 03127 } 03128 03129 /* Final fixups */ 03130 if (oh) { 03131 if (!ast_strlen_zero(oh->context)) 03132 ast_copy_string(chan->context, oh->context, sizeof(chan->context)); 03133 if (!ast_strlen_zero(oh->exten)) 03134 ast_copy_string(chan->exten, oh->exten, sizeof(chan->exten)); 03135 if (oh->priority) 03136 chan->priority = oh->priority; 03137 } 03138 if (chan->_state == AST_STATE_UP) 03139 *outstate = AST_CONTROL_ANSWER; 03140 03141 if (res <= 0) { 03142 if (!chan->cdr && (chan->cdr = ast_cdr_alloc())) 03143 ast_cdr_init(chan->cdr, chan); 03144 if (chan->cdr) { 03145 char tmp[256]; 03146 snprintf(tmp, sizeof(tmp), "%s/%s", type, (char *)data); 03147 ast_cdr_setapp(chan->cdr,"Dial",tmp); 03148 ast_cdr_update(chan); 03149 ast_cdr_start(chan->cdr); 03150 ast_cdr_end(chan->cdr); 03151 /* If the cause wasn't handled properly */ 03152 if (ast_cdr_disposition(chan->cdr,chan->hangupcause)) 03153 ast_cdr_failed(chan->cdr); 03154 } 03155 ast_hangup(chan); 03156 chan = NULL; 03157 } 03158 return chan; 03159 }
int ast_activate_generator | ( | struct ast_channel * | chan, | |
struct ast_generator * | gen, | |||
void * | params | |||
) |
Activate a given generator
Definition at line 1858 of file channel.c.
Referenced by app_exec(), ast_channel_start_silence_generator(), ast_linear_stream(), ast_playtones_start(), ast_tonepair_start(), channel_spy(), local_ast_moh_start(), milliwatt_exec(), and sms_exec().
01859 { 01860 int res = 0; 01861 01862 ast_channel_lock(chan); 01863 01864 if (chan->generatordata) { 01865 if (chan->generator && chan->generator->release) 01866 chan->generator->release(chan, chan->generatordata); 01867 chan->generatordata = NULL; 01868 } 01869 01870 ast_prod(chan); 01871 if (gen->alloc && !(chan->generatordata = gen->alloc(chan, params))) { 01872 res = -1; 01873 } 01874 01875 if (!res) { 01876 ast_settimeout(chan, 160, generator_force, chan); 01877 chan->generator = gen; 01878 } 01879 01880 ast_channel_unlock(chan); 01881 01882 return res; 01883 }
int ast_active_channels | ( | void | ) |
returns number of active/allocated channels
Returns number of active/allocated channels
Definition at line 462 of file channel.c.
Referenced by quit_handler().
00463 { 00464 struct ast_channel *c; 00465 int cnt = 0; 00466 AST_LIST_LOCK(&channels); 00467 AST_LIST_TRAVERSE(&channels, c, chan_list) 00468 cnt++; 00469 AST_LIST_UNLOCK(&channels); 00470 return cnt; 00471 }
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. |
Definition at line 1791 of file channel.c.
Referenced by __login_exec(), agi_exec_full(), alarmreceiver_exec(), app_exec(), ast_bridge_call(), ast_control_streamfile(), ast_pickup_call(), auth_exec(), background_detect_exec(), builtin_parkcall(), common_exec(), conf_exec(), count_exec(), dictate_exec(), directory_exec(), disa_exec(), features_answer(), handle_answer(), ices_exec(), milliwatt_exec(), park_call_exec(), park_exec(), pbx_builtin_answer(), pbx_builtin_background(), pickup_do(), playback_exec(), privacy_exec(), read_exec(), record_exec(), rpt_exec(), run_station(), sayunixtime_exec(), send_waveform_to_channel(), skel_exec(), sla_handle_dial_state_event(), sla_station_exec(), sms_exec(), speech_background(), testclient_exec(), testserver_exec(), vm_exec(), vm_execmain(), waitforsilence_exec(), zapateller_exec(), and zapras_exec().
01792 { 01793 int res = 0; 01794 ast_channel_lock(chan); 01795 /* You can't answer an outbound call */ 01796 if (ast_test_flag(chan, AST_FLAG_OUTGOING)) { 01797 ast_channel_unlock(chan); 01798 return 0; 01799 } 01800 /* Stop if we're a zombie or need a soft hangup */ 01801 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 01802 ast_channel_unlock(chan); 01803 return -1; 01804 } 01805 switch(chan->_state) { 01806 case AST_STATE_RINGING: 01807 case AST_STATE_RING: 01808 if (chan->tech->answer) 01809 res = chan->tech->answer(chan); 01810 ast_setstate(chan, AST_STATE_UP); 01811 ast_cdr_answer(chan->cdr); 01812 break; 01813 case AST_STATE_UP: 01814 ast_cdr_answer(chan->cdr); 01815 break; 01816 default: 01817 break; 01818 } 01819 ast_channel_unlock(chan); 01820 return res; 01821 }
void ast_begin_shutdown | ( | int | hangup | ) |
Initiate system shutdown.
Initiate system shutdown -- prevents new channels from being allocated. If "hangup" is non-zero, all existing channels will receive soft hangups
Definition at line 449 of file channel.c.
Referenced by quit_handler().
00450 { 00451 struct ast_channel *c; 00452 shutting_down = 1; 00453 if (hangup) { 00454 AST_LIST_LOCK(&channels); 00455 AST_LIST_TRAVERSE(&channels, c, chan_list) 00456 ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN); 00457 AST_LIST_UNLOCK(&channels); 00458 } 00459 }
int ast_best_codec | ( | int | fmts | ) |
Pick the best audio codec.
Pick the best codec
Okay, ulaw is used by all telephony equipment, so start with it
Unless of course, you're a silly European, so then prefer ALAW
G.722 is better then all below, but not as common as the above... so give ulaw and alaw priority
Okay, well, signed linear is easy to translate into other stuff
G.726 is standard ADPCM, in RFC3551 packing order
G.726 is standard ADPCM, in AAL2 packing order
ADPCM has great sound quality and is still pretty easy to translate
Okay, we're down to vocoders now, so pick GSM because it's small and easier to translate and sounds pretty good
iLBC is not too bad
Speex is free, but computationally more expensive than GSM
Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough to use it
G.729a is faster than 723 and slightly less expensive
Down to G.723.1 which is proprietary but at least designed for voice
Definition at line 674 of file channel.c.
Referenced by __login_exec(), __oh323_new(), agent_call(), ast_codec_choose(), ast_iax2_new(), builtin_atxfer(), echo_exec(), findmeexec(), gtalk_new(), handle_open_receive_channel_ack_message(), iax2_request(), local_new(), mgcp_new(), sip_new(), skinny_new(), socket_process(), and transmit_connect().
00675 { 00676 /* This just our opinion, expressed in code. We are asked to choose 00677 the best codec to use, given no information */ 00678 int x; 00679 static int prefs[] = 00680 { 00681 /*! Okay, ulaw is used by all telephony equipment, so start with it */ 00682 AST_FORMAT_ULAW, 00683 /*! Unless of course, you're a silly European, so then prefer ALAW */ 00684 AST_FORMAT_ALAW, 00685 /*! G.722 is better then all below, but not as common as the above... so give ulaw and alaw priority */ 00686 AST_FORMAT_G722, 00687 /*! Okay, well, signed linear is easy to translate into other stuff */ 00688 AST_FORMAT_SLINEAR, 00689 /*! G.726 is standard ADPCM, in RFC3551 packing order */ 00690 AST_FORMAT_G726, 00691 /*! G.726 is standard ADPCM, in AAL2 packing order */ 00692 AST_FORMAT_G726_AAL2, 00693 /*! ADPCM has great sound quality and is still pretty easy to translate */ 00694 AST_FORMAT_ADPCM, 00695 /*! Okay, we're down to vocoders now, so pick GSM because it's small and easier to 00696 translate and sounds pretty good */ 00697 AST_FORMAT_GSM, 00698 /*! iLBC is not too bad */ 00699 AST_FORMAT_ILBC, 00700 /*! Speex is free, but computationally more expensive than GSM */ 00701 AST_FORMAT_SPEEX, 00702 /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough 00703 to use it */ 00704 AST_FORMAT_LPC10, 00705 /*! G.729a is faster than 723 and slightly less expensive */ 00706 AST_FORMAT_G729A, 00707 /*! Down to G.723.1 which is proprietary but at least designed for voice */ 00708 AST_FORMAT_G723_1, 00709 }; 00710 00711 /* Strip out video */ 00712 fmts &= AST_FORMAT_AUDIO_MASK; 00713 00714 /* Find the first preferred codec in the format given */ 00715 for (x=0; x < (sizeof(prefs) / sizeof(prefs[0]) ); x++) 00716 if (fmts & prefs[x]) 00717 return prefs[x]; 00718 ast_log(LOG_WARNING, "Don't know any of 0x%x formats\n", fmts); 00719 return 0; 00720 }
struct ast_channel* ast_bridged_channel | ( | struct ast_channel * | chan | ) | [read] |
Find bridged channel.
chan | Current channel |
Definition at line 3873 of file channel.c.
Referenced by __zt_exception(), agents_show(), agents_show_online(), ast_channel_masquerade(), attempt_transfer(), cb_events(), check_bridge(), common_exec(), console_transfer(), console_transfer_deprecated(), create_jb(), export_aoc_vars(), handle_chanlist(), handle_chanlist_deprecated(), handle_hd_hf(), handle_invite_replaces(), handle_request(), handle_request_bye(), handle_request_info(), handle_request_invite(), handle_request_refer(), handle_response_invite(), handle_showchan(), handle_showchan_deprecated(), local_attended_transfer(), mgcp_hangup(), mgcp_ss(), misdn_transfer_bc(), mixmonitor_thread(), schedule_delivery(), sip_read(), socket_process(), ss_thread(), start_spying(), startmon(), zt_handle_event(), and zt_hangup().
03874 { 03875 struct ast_channel *bridged; 03876 bridged = chan->_bridge; 03877 if (bridged && bridged->tech->bridged_channel) 03878 bridged = bridged->tech->bridged_channel(chan, bridged); 03879 return bridged; 03880 }
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. |
Definition at line 3216 of file channel.c.
Referenced by __ast_request_and_dial(), agent_call(), ast_feature_request_and_dial(), attempt_reconnect(), begin_dial(), connect_link(), features_call(), findmeexec(), ring_entry(), rpt(), rpt_exec(), and wait_for_answer().
03217 { 03218 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 03219 If the remote end does not answer within the timeout, then do NOT hang up, but 03220 return anyway. */ 03221 int res = -1; 03222 /* Stop if we're a zombie or need a soft hangup */ 03223 ast_channel_lock(chan); 03224 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) { 03225 if (chan->tech->call) 03226 res = chan->tech->call(chan, addr, timeout); 03227 ast_set_flag(chan, AST_FLAG_OUTGOING); 03228 } 03229 ast_channel_unlock(chan); 03230 return res; 03231 }
void ast_cancel_shutdown | ( | void | ) |
Cancel a shutdown in progress.
Cancels an existing shutdown and returns to normal operation
Definition at line 474 of file channel.c.
Referenced by handle_abort_halt().
00475 { 00476 shutting_down = 0; 00477 }
const char* ast_cause2str | ( | int | state | ) |
Gives the string form of a given hangup cause.
Gives the string form of a given cause code
state | cause to get the description of Give a name to a cause code Returns the text form of the binary cause code given |
Definition at line 594 of file channel.c.
Referenced by __transmit_response(), ast_do_masquerade(), ast_hangup(), findmeexec(), sip_hangup(), and transmit_request_with_auth().
00595 { 00596 int x; 00597 00598 for (x=0; x < sizeof(causes) / sizeof(causes[0]); x++) { 00599 if (causes[x].cause == cause) 00600 return causes[x].desc; 00601 } 00602 00603 return "Unknown"; 00604 }
void ast_change_name | ( | struct ast_channel * | chan, | |
char * | newname | |||
) |
Change channel name.
Definition at line 3448 of file channel.c.
03449 { 03450 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", chan->name, newname, chan->uniqueid); 03451 ast_string_field_set(chan, name, newname); 03452 }
struct ast_channel* ast_channel_alloc | ( | int | needqueue, | |
int | state, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
const char * | acctcode, | |||
const char * | exten, | |||
const char * | context, | |||
const int | amaflag, | |||
const char * | name_fmt, | |||
... | ||||
) | [read] |
Create a new channel structure.
Create a channel structure.
Definition at line 728 of file channel.c.
Referenced by __oh323_new(), agent_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_masq_park_call(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), builtin_atxfer(), check_goto_on_transfer(), features_new(), gtalk_new(), iax_park(), local_new(), make_email_file(), mgcp_new(), misdn_new(), nbs_new(), oss_new(), pbx_substitute_variables_helper_full(), phone_new(), sendpage(), sip_new(), sip_park(), skinny_new(), and zt_new().
00729 { 00730 struct ast_channel *tmp; 00731 int x; 00732 int flags; 00733 struct varshead *headp; 00734 va_list ap1, ap2; 00735 00736 /* If shutting down, don't allocate any new channels */ 00737 if (shutting_down) { 00738 ast_log(LOG_WARNING, "Channel allocation failed: Refusing due to active shutdown\n"); 00739 return NULL; 00740 } 00741 00742 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) 00743 return NULL; 00744 00745 if (!(tmp->sched = sched_context_create())) { 00746 ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n"); 00747 free(tmp); 00748 return NULL; 00749 } 00750 00751 if ((ast_string_field_init(tmp, 128))) { 00752 sched_context_destroy(tmp->sched); 00753 free(tmp); 00754 return NULL; 00755 } 00756 00757 /* Don't bother initializing the last two FD here, because they 00758 will *always* be set just a few lines down (AST_TIMING_FD, 00759 AST_ALERT_FD). */ 00760 for (x = 0; x < AST_MAX_FDS - 2; x++) 00761 tmp->fds[x] = -1; 00762 00763 #ifdef HAVE_ZAPTEL 00764 tmp->timingfd = open("/dev/zap/timer", O_RDWR); 00765 if (tmp->timingfd > -1) { 00766 /* Check if timing interface supports new 00767 ping/pong scheme */ 00768 flags = 1; 00769 if (!ioctl(tmp->timingfd, ZT_TIMERPONG, &flags)) 00770 needqueue = 0; 00771 } 00772 #else 00773 tmp->timingfd = -1; 00774 #endif 00775 00776 if (needqueue) { 00777 if (pipe(tmp->alertpipe)) { 00778 ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe!\n"); 00779 ast_string_field_free_pools(tmp); 00780 free(tmp); 00781 return NULL; 00782 } else { 00783 flags = fcntl(tmp->alertpipe[0], F_GETFL); 00784 fcntl(tmp->alertpipe[0], F_SETFL, flags | O_NONBLOCK); 00785 flags = fcntl(tmp->alertpipe[1], F_GETFL); 00786 fcntl(tmp->alertpipe[1], F_SETFL, flags | O_NONBLOCK); 00787 } 00788 } else /* Make sure we've got it done right if they don't */ 00789 tmp->alertpipe[0] = tmp->alertpipe[1] = -1; 00790 00791 /* Always watch the alertpipe */ 00792 tmp->fds[AST_ALERT_FD] = tmp->alertpipe[0]; 00793 /* And timing pipe */ 00794 tmp->fds[AST_TIMING_FD] = tmp->timingfd; 00795 ast_string_field_set(tmp, name, "**Unknown**"); 00796 00797 /* Initial state */ 00798 tmp->_state = state; 00799 00800 tmp->streamid = -1; 00801 00802 tmp->fin = global_fin; 00803 tmp->fout = global_fout; 00804 00805 if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) { 00806 ast_string_field_build(tmp, uniqueid, "%li.%d", (long) time(NULL), 00807 ast_atomic_fetchadd_int(&uniqueint, 1)); 00808 } else { 00809 ast_string_field_build(tmp, uniqueid, "%s-%li.%d", ast_config_AST_SYSTEM_NAME, 00810 (long) time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1)); 00811 } 00812 00813 tmp->cid.cid_name = ast_strdup(cid_name); 00814 tmp->cid.cid_num = ast_strdup(cid_num); 00815 00816 if (!ast_strlen_zero(name_fmt)) { 00817 /* Almost every channel is calling this function, and setting the name via the ast_string_field_build() call. 00818 * And they all use slightly different formats for their name string. 00819 * This means, to set the name here, we have to accept variable args, and call the string_field_build from here. 00820 * This means, that the stringfields must have a routine that takes the va_lists directly, and 00821 * uses them to build the string, instead of forming the va_lists internally from the vararg ... list. 00822 * This new function was written so this can be accomplished. 00823 */ 00824 va_start(ap1, name_fmt); 00825 va_start(ap2, name_fmt); 00826 ast_string_field_build_va(tmp, name, name_fmt, ap1, ap2); 00827 va_end(ap1); 00828 va_end(ap2); 00829 00830 /* and now, since the channel structure is built, and has its name, let's call the 00831 * manager event generator with this Newchannel event. This is the proper and correct 00832 * place to make this call, but you sure do have to pass a lot of data into this func 00833 * to do it here! 00834 */ 00835 manager_event(EVENT_FLAG_CALL, "Newchannel", 00836 "Channel: %s\r\n" 00837 "State: %s\r\n" 00838 "CallerIDNum: %s\r\n" 00839 "CallerIDName: %s\r\n" 00840 "Uniqueid: %s\r\n", 00841 tmp->name, ast_state2str(state), 00842 S_OR(cid_num, "<unknown>"), 00843 S_OR(cid_name, "<unknown>"), 00844 tmp->uniqueid); 00845 } 00846 00847 /* Reminder for the future: under what conditions do we NOT want to track cdrs on channels? */ 00848 00849 /* These 4 variables need to be set up for the cdr_init() to work right */ 00850 if (amaflag) 00851 tmp->amaflags = amaflag; 00852 else 00853 tmp->amaflags = ast_default_amaflags; 00854 00855 if (!ast_strlen_zero(acctcode)) 00856 ast_string_field_set(tmp, accountcode, acctcode); 00857 else 00858 ast_string_field_set(tmp, accountcode, ast_default_accountcode); 00859 00860 if (!ast_strlen_zero(context)) 00861 ast_copy_string(tmp->context, context, sizeof(tmp->context)); 00862 else 00863 strcpy(tmp->context, "default"); 00864 00865 if (!ast_strlen_zero(exten)) 00866 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten)); 00867 else 00868 strcpy(tmp->exten, "s"); 00869 00870 tmp->priority = 1; 00871 00872 tmp->cdr = ast_cdr_alloc(); 00873 ast_cdr_init(tmp->cdr, tmp); 00874 ast_cdr_start(tmp->cdr); 00875 00876 headp = &tmp->varshead; 00877 AST_LIST_HEAD_INIT_NOLOCK(headp); 00878 00879 ast_mutex_init(&tmp->lock); 00880 00881 AST_LIST_HEAD_INIT_NOLOCK(&tmp->datastores); 00882 00883 ast_string_field_set(tmp, language, defaultlanguage); 00884 00885 tmp->tech = &null_tech; 00886 00887 AST_LIST_LOCK(&channels); 00888 AST_LIST_INSERT_HEAD(&channels, tmp, chan_list); 00889 AST_LIST_UNLOCK(&channels); 00890 00891 return tmp; 00892 }
enum ast_bridge_result 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.
Bridge two channels together
c0 | first channel to bridge | |
c1 | second channel to bridge | |
config | config 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 4062 of file channel.c.
Referenced by ast_bridge_call().
04064 { 04065 struct ast_channel *who = NULL; 04066 enum ast_bridge_result res = AST_BRIDGE_COMPLETE; 04067 int nativefailed=0; 04068 int firstpass; 04069 int o0nativeformats; 04070 int o1nativeformats; 04071 long time_left_ms=0; 04072 struct timeval nexteventts = { 0, }; 04073 char caller_warning = 0; 04074 char callee_warning = 0; 04075 04076 if (c0->_bridge) { 04077 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 04078 c0->name, c0->_bridge->name); 04079 return -1; 04080 } 04081 if (c1->_bridge) { 04082 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 04083 c1->name, c1->_bridge->name); 04084 return -1; 04085 } 04086 04087 /* Stop if we're a zombie or need a soft hangup */ 04088 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) || 04089 ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) 04090 return -1; 04091 04092 *fo = NULL; 04093 firstpass = config->firstpass; 04094 config->firstpass = 0; 04095 04096 if (ast_tvzero(config->start_time)) 04097 config->start_time = ast_tvnow(); 04098 time_left_ms = config->timelimit; 04099 04100 caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING); 04101 callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING); 04102 04103 if (config->start_sound && firstpass) { 04104 if (caller_warning) 04105 bridge_playfile(c0, c1, config->start_sound, time_left_ms / 1000); 04106 if (callee_warning) 04107 bridge_playfile(c1, c0, config->start_sound, time_left_ms / 1000); 04108 } 04109 04110 /* Keep track of bridge */ 04111 c0->_bridge = c1; 04112 c1->_bridge = c0; 04113 04114 /* \todo XXX here should check that cid_num is not NULL */ 04115 manager_event(EVENT_FLAG_CALL, "Link", 04116 "Channel1: %s\r\n" 04117 "Channel2: %s\r\n" 04118 "Uniqueid1: %s\r\n" 04119 "Uniqueid2: %s\r\n" 04120 "CallerID1: %s\r\n" 04121 "CallerID2: %s\r\n", 04122 c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num); 04123 04124 o0nativeformats = c0->nativeformats; 04125 o1nativeformats = c1->nativeformats; 04126 04127 if (config->feature_timer) { 04128 nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->feature_timer, 1000)); 04129 } else if (config->timelimit) { 04130 nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000)); 04131 if (caller_warning || callee_warning) 04132 nexteventts = ast_tvsub(nexteventts, ast_samp2tv(config->play_warning, 1000)); 04133 } 04134 04135 if (!c0->tech->send_digit_begin) 04136 ast_set_flag(c1, AST_FLAG_END_DTMF_ONLY); 04137 if (!c1->tech->send_digit_begin) 04138 ast_set_flag(c0, AST_FLAG_END_DTMF_ONLY); 04139 04140 for (/* ever */;;) { 04141 struct timeval now = { 0, }; 04142 int to; 04143 04144 to = -1; 04145 04146 if (!ast_tvzero(nexteventts)) { 04147 now = ast_tvnow(); 04148 to = ast_tvdiff_ms(nexteventts, now); 04149 if (to <= 0) { 04150 if (!config->timelimit) { 04151 res = AST_BRIDGE_COMPLETE; 04152 break; 04153 } 04154 to = 0; 04155 } 04156 } 04157 04158 if (config->timelimit) { 04159 time_left_ms = config->timelimit - ast_tvdiff_ms(now, config->start_time); 04160 if (time_left_ms < to) 04161 to = time_left_ms; 04162 04163 if (time_left_ms <= 0) { 04164 if (caller_warning && config->end_sound) 04165 bridge_playfile(c0, c1, config->end_sound, 0); 04166 if (callee_warning && config->end_sound) 04167 bridge_playfile(c1, c0, config->end_sound, 0); 04168 *fo = NULL; 04169 if (who) 04170 *rc = who; 04171 res = 0; 04172 break; 04173 } 04174 04175 if (!to) { 04176 if (time_left_ms >= 5000 && config->warning_sound && config->play_warning) { 04177 int t = (time_left_ms + 500) / 1000; /* round to nearest second */ 04178 if (caller_warning) 04179 bridge_playfile(c0, c1, config->warning_sound, t); 04180 if (callee_warning) 04181 bridge_playfile(c1, c0, config->warning_sound, t); 04182 } 04183 if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000))) 04184 nexteventts = ast_tvadd(nexteventts, ast_samp2tv(config->warning_freq, 1000)); 04185 else 04186 nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000)); 04187 } 04188 } 04189 04190 if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) { 04191 if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE) 04192 c0->_softhangup = 0; 04193 if (c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) 04194 c1->_softhangup = 0; 04195 c0->_bridge = c1; 04196 c1->_bridge = c0; 04197 if (option_debug) 04198 ast_log(LOG_DEBUG, "Unbridge signal received. Ending native bridge.\n"); 04199 continue; 04200 } 04201 04202 /* Stop if we're a zombie or need a soft hangup */ 04203 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) || 04204 ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) { 04205 *fo = NULL; 04206 if (who) 04207 *rc = who; 04208 res = 0; 04209 if (option_debug) 04210 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", 04211 c0->name, c1->name, 04212 ast_test_flag(c0, AST_FLAG_ZOMBIE) ? "Yes" : "No", 04213 ast_check_hangup(c0) ? "Yes" : "No", 04214 ast_test_flag(c1, AST_FLAG_ZOMBIE) ? "Yes" : "No", 04215 ast_check_hangup(c1) ? "Yes" : "No"); 04216 break; 04217 } 04218 04219 /* See if the BRIDGEPEER variable needs to be updated */ 04220 if (!ast_strlen_zero(pbx_builtin_getvar_helper(c0, "BRIDGEPEER"))) 04221 pbx_builtin_setvar_helper(c0, "BRIDGEPEER", c1->name); 04222 if (!ast_strlen_zero(pbx_builtin_getvar_helper(c1, "BRIDGEPEER"))) 04223 pbx_builtin_setvar_helper(c1, "BRIDGEPEER", c0->name); 04224 04225 if (c0->tech->bridge && 04226 (config->timelimit == 0) && 04227 (c0->tech->bridge == c1->tech->bridge) && 04228 !nativefailed && !c0->monitor && !c1->monitor && 04229 !c0->spies && !c1->spies && !ast_test_flag(&(config->features_callee),AST_FEATURE_REDIRECT) && 04230 !ast_test_flag(&(config->features_caller),AST_FEATURE_REDIRECT) ) { 04231 /* Looks like they share a bridge method and nothing else is in the way */ 04232 ast_set_flag(c0, AST_FLAG_NBRIDGE); 04233 ast_set_flag(c1, AST_FLAG_NBRIDGE); 04234 if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, to)) == AST_BRIDGE_COMPLETE) { 04235 /* \todo XXX here should check that cid_num is not NULL */ 04236 manager_event(EVENT_FLAG_CALL, "Unlink", 04237 "Channel1: %s\r\n" 04238 "Channel2: %s\r\n" 04239 "Uniqueid1: %s\r\n" 04240 "Uniqueid2: %s\r\n" 04241 "CallerID1: %s\r\n" 04242 "CallerID2: %s\r\n", 04243 c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num); 04244 if (option_debug) 04245 ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n", c0->name, c1->name); 04246 04247 ast_clear_flag(c0, AST_FLAG_NBRIDGE); 04248 ast_clear_flag(c1, AST_FLAG_NBRIDGE); 04249 04250 if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) 04251 continue; 04252 04253 c0->_bridge = NULL; 04254 c1->_bridge = NULL; 04255 04256 return res; 04257 } else { 04258 ast_clear_flag(c0, AST_FLAG_NBRIDGE); 04259 ast_clear_flag(c1, AST_FLAG_NBRIDGE); 04260 } 04261 switch (res) { 04262 case AST_BRIDGE_RETRY: 04263 continue; 04264 default: 04265 if (option_verbose > 2) 04266 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s ended\n", 04267 c0->name, c1->name); 04268 /* fallthrough */ 04269 case AST_BRIDGE_FAILED_NOWARN: 04270 nativefailed++; 04271 break; 04272 } 04273 } 04274 04275 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || 04276 (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) && 04277 !(c0->generator || c1->generator)) { 04278 if (ast_channel_make_compatible(c0, c1)) { 04279 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); 04280 /* \todo XXX here should check that cid_num is not NULL */ 04281 manager_event(EVENT_FLAG_CALL, "Unlink", 04282 "Channel1: %s\r\n" 04283 "Channel2: %s\r\n" 04284 "Uniqueid1: %s\r\n" 04285 "Uniqueid2: %s\r\n" 04286 "CallerID1: %s\r\n" 04287 "CallerID2: %s\r\n", 04288 c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num); 04289 return AST_BRIDGE_FAILED; 04290 } 04291 o0nativeformats = c0->nativeformats; 04292 o1nativeformats = c1->nativeformats; 04293 } 04294 res = ast_generic_bridge(c0, c1, config, fo, rc, nexteventts); 04295 if (res != AST_BRIDGE_RETRY) 04296 break; 04297 } 04298 04299 ast_clear_flag(c0, AST_FLAG_END_DTMF_ONLY); 04300 ast_clear_flag(c1, AST_FLAG_END_DTMF_ONLY); 04301 04302 c0->_bridge = NULL; 04303 c1->_bridge = NULL; 04304 04305 /* \todo XXX here should check that cid_num is not NULL */ 04306 manager_event(EVENT_FLAG_CALL, "Unlink", 04307 "Channel1: %s\r\n" 04308 "Channel2: %s\r\n" 04309 "Uniqueid1: %s\r\n" 04310 "Uniqueid2: %s\r\n" 04311 "CallerID1: %s\r\n" 04312 "CallerID2: %s\r\n", 04313 c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num); 04314 if (option_debug) 04315 ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n", c0->name, c1->name); 04316 04317 return res; 04318 }
int ast_channel_cmpwhentohangup | ( | struct ast_channel * | chan, | |
time_t | offset | |||
) |
Compare a offset with when to hangup channel.
Compare a offset with the settings of when to hang a channel up.
Definition at line 494 of file channel.c.
00495 { 00496 time_t whentohangup; 00497 00498 if (chan->whentohangup == 0) { 00499 return (offset == 0) ? 0 : -1; 00500 } else { 00501 if (offset == 0) /* XXX why is this special ? */ 00502 return (1); 00503 else { 00504 whentohangup = offset + time (NULL); 00505 if (chan->whentohangup < whentohangup) 00506 return (1); 00507 else if (chan->whentohangup == whentohangup) 00508 return (0); 00509 else 00510 return (-1); 00511 } 00512 } 00513 }
int ast_channel_datastore_add | ( | struct ast_channel * | chan, | |
struct ast_datastore * | datastore | |||
) |
Add a datastore to a channel.
Definition at line 1319 of file channel.c.
Referenced by speech_create().
01320 { 01321 int res = 0; 01322 01323 AST_LIST_INSERT_HEAD(&chan->datastores, datastore, entry); 01324 01325 return res; 01326 }
struct ast_datastore* ast_channel_datastore_alloc | ( | const struct ast_datastore_info * | info, | |
char * | uid | |||
) | [read] |
Create a channel datastore structure.
Definition at line 1275 of file channel.c.
Referenced by speech_create().
01276 { 01277 struct ast_datastore *datastore = NULL; 01278 01279 /* Make sure we at least have type so we can identify this */ 01280 if (info == NULL) { 01281 return NULL; 01282 } 01283 01284 /* Allocate memory for datastore and clear it */ 01285 datastore = ast_calloc(1, sizeof(*datastore)); 01286 if (datastore == NULL) { 01287 return NULL; 01288 } 01289 01290 datastore->info = info; 01291 01292 datastore->uid = ast_strdup(uid); 01293 01294 return datastore; 01295 }
struct ast_datastore* ast_channel_datastore_find | ( | struct ast_channel * | chan, | |
const struct ast_datastore_info * | info, | |||
char * | uid | |||
) | [read] |
Find a datastore on a channel.
Definition at line 1346 of file channel.c.
Referenced by find_speech(), speech_background(), and speech_destroy().
01347 { 01348 struct ast_datastore *datastore = NULL; 01349 01350 if (info == NULL) 01351 return NULL; 01352 01353 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->datastores, datastore, entry) { 01354 if (datastore->info == info) { 01355 if (uid != NULL && datastore->uid != NULL) { 01356 if (!strcasecmp(uid, datastore->uid)) { 01357 /* Matched by type AND uid */ 01358 break; 01359 } 01360 } else { 01361 /* Matched by type at least */ 01362 break; 01363 } 01364 } 01365 } 01366 AST_LIST_TRAVERSE_SAFE_END 01367 01368 return datastore; 01369 }
int ast_channel_datastore_free | ( | struct ast_datastore * | datastore | ) |
Free a channel datastore structure.
Definition at line 1297 of file channel.c.
Referenced by ast_channel_free().
01298 { 01299 int res = 0; 01300 01301 /* Using the destroy function (if present) destroy the data */ 01302 if (datastore->info->destroy != NULL && datastore->data != NULL) { 01303 datastore->info->destroy(datastore->data); 01304 datastore->data = NULL; 01305 } 01306 01307 /* Free allocated UID memory */ 01308 if (datastore->uid != NULL) { 01309 free(datastore->uid); 01310 datastore->uid = NULL; 01311 } 01312 01313 /* Finally free memory used by ourselves */ 01314 free(datastore); 01315 01316 return res; 01317 }
int ast_channel_datastore_remove | ( | struct ast_channel * | chan, | |
struct ast_datastore * | datastore | |||
) |
Remove a datastore from a channel.
Definition at line 1328 of file channel.c.
Referenced by speech_background(), and speech_destroy().
01329 { 01330 struct ast_datastore *datastore2 = NULL; 01331 int res = -1; 01332 01333 /* Find our position and remove ourselves */ 01334 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->datastores, datastore2, entry) { 01335 if (datastore2 == datastore) { 01336 AST_LIST_REMOVE_CURRENT(&chan->datastores, entry); 01337 res = 0; 01338 break; 01339 } 01340 } 01341 AST_LIST_TRAVERSE_SAFE_END 01342 01343 return res; 01344 }
int ast_channel_defer_dtmf | ( | struct ast_channel * | chan | ) |
Set defer DTMF flag on channel.
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 986 of file channel.c.
Referenced by __adsi_transmit_messages(), and find_cache().
00987 { 00988 int pre = 0; 00989 00990 if (chan) { 00991 pre = ast_test_flag(chan, AST_FLAG_DEFER_DTMF); 00992 ast_set_flag(chan, AST_FLAG_DEFER_DTMF); 00993 } 00994 return pre; 00995 }
void ast_channel_free | ( | struct ast_channel * | chan | ) |
Free a channel structure.
Definition at line 1190 of file channel.c.
Referenced by agent_cleanup(), agent_new(), ast_do_masquerade(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), local_new(), make_email_file(), pbx_substitute_variables_helper_full(), and sendpage().
01191 { 01192 int fd; 01193 struct ast_var_t *vardata; 01194 struct ast_frame *f; 01195 struct varshead *headp; 01196 struct ast_datastore *datastore = NULL; 01197 char name[AST_CHANNEL_NAME]; 01198 01199 headp=&chan->varshead; 01200 01201 AST_LIST_LOCK(&channels); 01202 if (!AST_LIST_REMOVE(&channels, chan, chan_list)) { 01203 AST_LIST_UNLOCK(&channels); 01204 ast_log(LOG_ERROR, "Unable to find channel in list to free. Assuming it has already been done.\n"); 01205 } 01206 /* Lock and unlock the channel just to be sure nobody 01207 has it locked still */ 01208 ast_channel_lock(chan); 01209 ast_channel_unlock(chan); 01210 if (chan->tech_pvt) { 01211 ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name); 01212 free(chan->tech_pvt); 01213 } 01214 01215 if (chan->sched) 01216 sched_context_destroy(chan->sched); 01217 01218 ast_copy_string(name, chan->name, sizeof(name)); 01219 01220 /* Stop monitoring */ 01221 if (chan->monitor) 01222 chan->monitor->stop( chan, 0 ); 01223 01224 /* If there is native format music-on-hold state, free it */ 01225 if (chan->music_state) 01226 ast_moh_cleanup(chan); 01227 01228 /* if someone is whispering on the channel, stop them */ 01229 if (chan->whisper) 01230 ast_channel_whisper_stop(chan); 01231 01232 /* Free translators */ 01233 if (chan->readtrans) 01234 ast_translator_free_path(chan->readtrans); 01235 if (chan->writetrans) 01236 ast_translator_free_path(chan->writetrans); 01237 if (chan->pbx) 01238 ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name); 01239 free_cid(&chan->cid); 01240 ast_mutex_destroy(&chan->lock); 01241 /* Close pipes if appropriate */ 01242 if ((fd = chan->alertpipe[0]) > -1) 01243 close(fd); 01244 if ((fd = chan->alertpipe[1]) > -1) 01245 close(fd); 01246 if ((fd = chan->timingfd) > -1) 01247 close(fd); 01248 while ((f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list))) 01249 ast_frfree(f); 01250 01251 /* Get rid of each of the data stores on the channel */ 01252 while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry))) 01253 /* Free the data store */ 01254 ast_channel_datastore_free(datastore); 01255 AST_LIST_HEAD_INIT_NOLOCK(&chan->datastores); 01256 01257 /* loop over the variables list, freeing all data and deleting list items */ 01258 /* no need to lock the list, as the channel is already locked */ 01259 01260 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 01261 ast_var_delete(vardata); 01262 01263 ast_app_group_discard(chan); 01264 01265 /* Destroy the jitterbuffer */ 01266 ast_jb_destroy(chan); 01267 01268 ast_string_field_free_pools(chan); 01269 free(chan); 01270 AST_LIST_UNLOCK(&channels); 01271 01272 ast_device_state_changed_literal(name); 01273 }
void ast_channel_inherit_variables | ( | const struct ast_channel * | parent, | |
struct ast_channel * | child | |||
) |
Inherits channel variable from parent to child channel.
parent | Parent channel | |
child | Child channel |
Definition at line 3454 of file channel.c.
Referenced by __ast_request_and_dial(), agent_call(), ast_feature_request_and_dial(), begin_dial(), findmeexec(), ring_entry(), and wait_for_answer().
03455 { 03456 struct ast_var_t *current, *newvar; 03457 const char *varname; 03458 03459 AST_LIST_TRAVERSE(&parent->varshead, current, entries) { 03460 int vartype = 0; 03461 03462 varname = ast_var_full_name(current); 03463 if (!varname) 03464 continue; 03465 03466 if (varname[0] == '_') { 03467 vartype = 1; 03468 if (varname[1] == '_') 03469 vartype = 2; 03470 } 03471 03472 switch (vartype) { 03473 case 1: 03474 newvar = ast_var_assign(&varname[1], ast_var_value(current)); 03475 if (newvar) { 03476 AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries); 03477 if (option_debug) 03478 ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n", ast_var_name(newvar)); 03479 } 03480 break; 03481 case 2: 03482 newvar = ast_var_assign(ast_var_full_name(current), ast_var_value(current)); 03483 if (newvar) { 03484 AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries); 03485 if (option_debug) 03486 ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n", ast_var_name(newvar)); 03487 } 03488 break; 03489 default: 03490 if (option_debug) 03491 ast_log(LOG_DEBUG, "Not copying variable %s.\n", ast_var_name(current)); 03492 break; 03493 } 03494 } 03495 }
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 . |
Definition at line 3323 of file channel.c.
Referenced by app_exec(), ast_channel_bridge(), check_compat(), park_exec(), try_calling(), and wait_for_answer().
03324 { 03325 int src; 03326 int dst; 03327 03328 if (chan->readformat == peer->writeformat && chan->writeformat == peer->readformat) { 03329 /* Already compatible! Moving on ... */ 03330 return 0; 03331 } 03332 03333 /* Set up translation from the chan to the peer */ 03334 src = chan->nativeformats; 03335 dst = peer->nativeformats; 03336 if (ast_translator_best_choice(&dst, &src) < 0) { 03337 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, src, peer->name, dst); 03338 return -1; 03339 } 03340 03341 /* if the best path is not 'pass through', then 03342 transcoding is needed; if desired, force transcode path 03343 to use SLINEAR between channels, but only if there is 03344 no direct conversion available */ 03345 if ((src != dst) && ast_opt_transcode_via_slin && 03346 (ast_translate_path_steps(dst, src) != 1)) 03347 dst = AST_FORMAT_SLINEAR; 03348 if (ast_set_read_format(chan, dst) < 0) { 03349 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, dst); 03350 return -1; 03351 } 03352 if (ast_set_write_format(peer, dst) < 0) { 03353 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, dst); 03354 return -1; 03355 } 03356 03357 /* Set up translation from the peer to the chan */ 03358 src = peer->nativeformats; 03359 dst = chan->nativeformats; 03360 if (ast_translator_best_choice(&dst, &src) < 0) { 03361 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, src, chan->name, dst); 03362 return -1; 03363 } 03364 03365 /* if the best path is not 'pass through', then 03366 transcoding is needed; if desired, force transcode path 03367 to use SLINEAR between channels, but only if there is 03368 no direct conversion available */ 03369 if ((src != dst) && ast_opt_transcode_via_slin && 03370 (ast_translate_path_steps(dst, src) != 1)) 03371 dst = AST_FORMAT_SLINEAR; 03372 if (ast_set_read_format(peer, dst) < 0) { 03373 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, dst); 03374 return -1; 03375 } 03376 if (ast_set_write_format(chan, dst) < 0) { 03377 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, dst); 03378 return -1; 03379 } 03380 return 0; 03381 }
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 3383 of file channel.c.
Referenced by ast_async_goto(), ast_masq_park_call(), ast_pickup_call(), attempt_transfer(), builtin_atxfer(), check_availability(), check_bridge(), check_goto_on_transfer(), handle_invite_replaces(), iax_park(), misdn_transfer_bc(), pickup_do(), and sip_park().
03384 { 03385 int res = -1; 03386 struct ast_channel *final_orig = original, *final_clone = clone; 03387 03388 ast_channel_lock(original); 03389 while (ast_channel_trylock(clone)) { 03390 ast_channel_unlock(original); 03391 usleep(1); 03392 ast_channel_lock(original); 03393 } 03394 03395 /* each of these channels may be sitting behind a channel proxy (i.e. chan_agent) 03396 and if so, we don't really want to masquerade it, but its proxy */ 03397 if (original->_bridge && (original->_bridge != ast_bridged_channel(original)) && (original->_bridge->_bridge != original)) 03398 final_orig = original->_bridge; 03399 03400 if (clone->_bridge && (clone->_bridge != ast_bridged_channel(clone)) && (clone->_bridge->_bridge != clone)) 03401 final_clone = clone->_bridge; 03402 03403 if ((final_orig != original) || (final_clone != clone)) { 03404 ast_channel_lock(final_orig); 03405 while (ast_channel_trylock(final_clone)) { 03406 ast_channel_unlock(final_orig); 03407 usleep(1); 03408 ast_channel_lock(final_orig); 03409 } 03410 ast_channel_unlock(clone); 03411 ast_channel_unlock(original); 03412 original = final_orig; 03413 clone = final_clone; 03414 } 03415 03416 if (original == clone) { 03417 ast_log(LOG_WARNING, "Can't masquerade channel '%s' into itself!\n", original->name); 03418 ast_channel_unlock(clone); 03419 ast_channel_unlock(original); 03420 return -1; 03421 } 03422 03423 if (option_debug) 03424 ast_log(LOG_DEBUG, "Planning to masquerade channel %s into the structure of %s\n", 03425 clone->name, original->name); 03426 if (original->masq) { 03427 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 03428 original->masq->name, original->name); 03429 } else if (clone->masqr) { 03430 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 03431 clone->name, clone->masqr->name); 03432 } else { 03433 original->masq = clone; 03434 clone->masqr = original; 03435 ast_queue_frame(original, &ast_null_frame); 03436 ast_queue_frame(clone, &ast_null_frame); 03437 if (option_debug) 03438 ast_log(LOG_DEBUG, "Done planning to masquerade channel %s into the structure of %s\n", clone->name, original->name); 03439 res = 0; 03440 } 03441 03442 ast_channel_unlock(clone); 03443 ast_channel_unlock(original); 03444 03445 return res; 03446 }
int ast_channel_register | ( | const struct ast_channel_tech * | tech | ) |
Register a new telephony channel in Asterisk.
Register a channel technology (a new channel driver) Called by a channel module to register the kind of channels it supports.
Definition at line 516 of file channel.c.
Referenced by load_module(), and unload_module().
00517 { 00518 struct chanlist *chan; 00519 00520 AST_LIST_LOCK(&channels); 00521 00522 AST_LIST_TRAVERSE(&backends, chan, list) { 00523 if (!strcasecmp(tech->type, chan->tech->type)) { 00524 ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", tech->type); 00525 AST_LIST_UNLOCK(&channels); 00526 return -1; 00527 } 00528 } 00529 00530 if (!(chan = ast_calloc(1, sizeof(*chan)))) { 00531 AST_LIST_UNLOCK(&channels); 00532 return -1; 00533 } 00534 chan->tech = tech; 00535 AST_LIST_INSERT_HEAD(&backends, chan, list); 00536 00537 if (option_debug) 00538 ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->tech->type, chan->tech->description); 00539 00540 if (option_verbose > 1) 00541 ast_verbose(VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->tech->type, 00542 chan->tech->description); 00543 00544 AST_LIST_UNLOCK(&channels); 00545 return 0; 00546 }
int ast_channel_sendhtml | ( | struct ast_channel * | channel, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) |
Sends HTML on given channel
Send HTML or URL on link. Returns 0 on success or -1 on failure
Definition at line 3311 of file channel.c.
Referenced by agent_sendhtml(), ast_channel_sendurl(), and wait_for_answer().
03312 { 03313 if (chan->tech->send_html) 03314 return chan->tech->send_html(chan, subclass, data, datalen); 03315 return -1; 03316 }
int ast_channel_sendurl | ( | struct ast_channel * | channel, | |
const char * | url | |||
) |
Sends a URL on a given link
Send URL on link. Returns 0 on success or -1 on failure
Definition at line 3318 of file channel.c.
Referenced by sendurl_exec(), and try_calling().
03319 { 03320 return ast_channel_sendhtml(chan, AST_HTML_URL, url, strlen(url) + 1); 03321 }
int ast_channel_setoption | ( | struct ast_channel * | channel, | |
int | option, | |||
void * | data, | |||
int | datalen, | |||
int | block | |||
) |
Sets an option on a channel.
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 4321 of file channel.c.
Referenced by ast_bridge_call(), common_exec(), conf_run(), func_channel_write(), handle_tddmode(), play_record_review(), reset_volumes(), rpt(), rpt_exec(), set_listen_volume(), set_talk_volume(), set_volume(), try_calling(), vm_forwardoptions(), and zt_hangup().
04322 { 04323 int res; 04324 04325 if (chan->tech->setoption) { 04326 res = chan->tech->setoption(chan, option, data, datalen); 04327 if (res < 0) 04328 return res; 04329 } else { 04330 errno = ENOSYS; 04331 return -1; 04332 } 04333 if (block) { 04334 /* XXX Implement blocking -- just wait for our option frame reply, discarding 04335 intermediate packets. XXX */ 04336 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 04337 return -1; 04338 } 04339 return 0; 04340 }
void ast_channel_setwhentohangup | ( | struct ast_channel * | chan, | |
time_t | offset | |||
) |
Set when to hangup channel.
Set when to hang a channel up.
Definition at line 486 of file channel.c.
Referenced by action_timeout(), and timeout_write().
00487 { 00488 chan->whentohangup = offset ? time(NULL) + offset : 0; 00489 ast_queue_frame(chan, &ast_null_frame); 00490 return; 00491 }
int ast_channel_spy_add | ( | struct ast_channel * | chan, | |
struct ast_channel_spy * | spy | |||
) |
Adds a spy to a channel, to begin receiving copies of the channel's audio frames.
chan | The channel to add the spy to. | |
spy | A pointer to ast_channel_spy structure describing how the spy is to be used. |
Definition at line 1371 of file channel.c.
Referenced by start_spying(), and startmon().
01372 { 01373 /* Link the owner channel to the spy */ 01374 spy->chan = chan; 01375 01376 if (!ast_test_flag(spy, CHANSPY_FORMAT_AUDIO)) { 01377 ast_log(LOG_WARNING, "Could not add channel spy '%s' to channel '%s', only audio format spies are supported.\n", 01378 spy->type, chan->name); 01379 return -1; 01380 } 01381 01382 if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST) && (spy->read_queue.format != AST_FORMAT_SLINEAR)) { 01383 ast_log(LOG_WARNING, "Cannot provide volume adjustment on '%s' format spies\n", 01384 ast_getformatname(spy->read_queue.format)); 01385 return -1; 01386 } 01387 01388 if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST) && (spy->write_queue.format != AST_FORMAT_SLINEAR)) { 01389 ast_log(LOG_WARNING, "Cannot provide volume adjustment on '%s' format spies\n", 01390 ast_getformatname(spy->write_queue.format)); 01391 return -1; 01392 } 01393 01394 if (ast_test_flag(spy, CHANSPY_MIXAUDIO) && 01395 ((spy->read_queue.format != AST_FORMAT_SLINEAR) || 01396 (spy->write_queue.format != AST_FORMAT_SLINEAR))) { 01397 ast_log(LOG_WARNING, "Cannot provide audio mixing on '%s'-'%s' format spies\n", 01398 ast_getformatname(spy->read_queue.format), ast_getformatname(spy->write_queue.format)); 01399 return -1; 01400 } 01401 01402 if (!chan->spies) { 01403 if (!(chan->spies = ast_calloc(1, sizeof(*chan->spies)))) { 01404 return -1; 01405 } 01406 01407 AST_LIST_HEAD_INIT_NOLOCK(&chan->spies->list); 01408 AST_LIST_INSERT_HEAD(&chan->spies->list, spy, list); 01409 } else { 01410 AST_LIST_INSERT_TAIL(&chan->spies->list, spy, list); 01411 } 01412 01413 if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) { 01414 ast_cond_init(&spy->trigger, NULL); 01415 ast_set_flag(spy, CHANSPY_TRIGGER_READ); 01416 ast_clear_flag(spy, CHANSPY_TRIGGER_WRITE); 01417 } 01418 01419 if (option_debug) 01420 ast_log(LOG_DEBUG, "Spy %s added to channel %s\n", 01421 spy->type, chan->name); 01422 01423 return 0; 01424 }
void ast_channel_spy_free | ( | struct ast_channel_spy * | spy | ) |
Free a spy.
spy | The spy to free |
Definition at line 1501 of file channel.c.
Referenced by channel_spy(), and mixmonitor_thread().
01502 { 01503 struct ast_frame *f = NULL; 01504 01505 if (spy->status == CHANSPY_DONE) 01506 return; 01507 01508 /* Switch status to done in case we get called twice */ 01509 spy->status = CHANSPY_DONE; 01510 01511 /* Drop any frames in the queue */ 01512 while ((f = AST_LIST_REMOVE_HEAD(&spy->write_queue.list, frame_list))) 01513 ast_frfree(f); 01514 while ((f = AST_LIST_REMOVE_HEAD(&spy->read_queue.list, frame_list))) 01515 ast_frfree(f); 01516 01517 /* Destroy the condition if in use */ 01518 if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) 01519 ast_cond_destroy(&spy->trigger); 01520 01521 /* Destroy our mutex since it is no longer in use */ 01522 ast_mutex_destroy(&spy->lock); 01523 01524 return; 01525 }
struct ast_frame* ast_channel_spy_read_frame | ( | struct ast_channel_spy * | spy, | |
unsigned int | samples | |||
) | [read] |
Read one (or more) frames of audio from a channel being spied upon.
spy | The spy to operate on | |
samples | The number of audio samples to read |
Note: This function performs no locking; you must hold the spy's lock before calling this function. You must not hold the channel's lock at the same time.
Definition at line 4637 of file channel.c.
Referenced by mixmonitor_thread(), and spy_generate().
04638 { 04639 struct ast_frame *result; 04640 /* buffers are allocated to hold SLINEAR, which is the largest format */ 04641 short read_buf[samples]; 04642 short write_buf[samples]; 04643 struct ast_frame *read_frame; 04644 struct ast_frame *write_frame; 04645 int need_dup; 04646 struct ast_frame stack_read_frame = { .frametype = AST_FRAME_VOICE, 04647 .subclass = spy->read_queue.format, 04648 .data = read_buf, 04649 .samples = samples, 04650 .datalen = ast_codec_get_len(spy->read_queue.format, samples), 04651 }; 04652 struct ast_frame stack_write_frame = { .frametype = AST_FRAME_VOICE, 04653 .subclass = spy->write_queue.format, 04654 .data = write_buf, 04655 .samples = samples, 04656 .datalen = ast_codec_get_len(spy->write_queue.format, samples), 04657 }; 04658 04659 /* if a flush has been requested, dump everything in whichever queue is larger */ 04660 if (ast_test_flag(spy, CHANSPY_TRIGGER_FLUSH)) { 04661 if (spy->read_queue.samples > spy->write_queue.samples) { 04662 if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST)) { 04663 AST_LIST_TRAVERSE(&spy->read_queue.list, result, frame_list) 04664 ast_frame_adjust_volume(result, spy->read_vol_adjustment); 04665 } 04666 result = AST_LIST_FIRST(&spy->read_queue.list); 04667 AST_LIST_HEAD_SET_NOLOCK(&spy->read_queue.list, NULL); 04668 spy->read_queue.samples = 0; 04669 } else { 04670 if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST)) { 04671 AST_LIST_TRAVERSE(&spy->write_queue.list, result, frame_list) 04672 ast_frame_adjust_volume(result, spy->write_vol_adjustment); 04673 } 04674 result = AST_LIST_FIRST(&spy->write_queue.list); 04675 AST_LIST_HEAD_SET_NOLOCK(&spy->write_queue.list, NULL); 04676 spy->write_queue.samples = 0; 04677 } 04678 ast_clear_flag(spy, CHANSPY_TRIGGER_FLUSH); 04679 return result; 04680 } 04681 04682 if ((spy->read_queue.samples < samples) || (spy->write_queue.samples < samples)) 04683 return NULL; 04684 04685 /* short-circuit if both head frames have exactly what we want */ 04686 if ((AST_LIST_FIRST(&spy->read_queue.list)->samples == samples) && 04687 (AST_LIST_FIRST(&spy->write_queue.list)->samples == samples)) { 04688 read_frame = AST_LIST_REMOVE_HEAD(&spy->read_queue.list, frame_list); 04689 write_frame = AST_LIST_REMOVE_HEAD(&spy->write_queue.list, frame_list); 04690 04691 spy->read_queue.samples -= samples; 04692 spy->write_queue.samples -= samples; 04693 04694 need_dup = 0; 04695 } else { 04696 copy_data_from_queue(&spy->read_queue, read_buf, samples); 04697 copy_data_from_queue(&spy->write_queue, write_buf, samples); 04698 04699 read_frame = &stack_read_frame; 04700 write_frame = &stack_write_frame; 04701 need_dup = 1; 04702 } 04703 04704 if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST)) 04705 ast_frame_adjust_volume(read_frame, spy->read_vol_adjustment); 04706 04707 if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST)) 04708 ast_frame_adjust_volume(write_frame, spy->write_vol_adjustment); 04709 04710 if (ast_test_flag(spy, CHANSPY_MIXAUDIO)) { 04711 ast_frame_slinear_sum(read_frame, write_frame); 04712 04713 if (need_dup) 04714 result = ast_frdup(read_frame); 04715 else { 04716 result = read_frame; 04717 ast_frfree(write_frame); 04718 } 04719 } else { 04720 if (need_dup) { 04721 result = ast_frdup(read_frame); 04722 AST_LIST_NEXT(result, frame_list) = ast_frdup(write_frame); 04723 } else { 04724 result = read_frame; 04725 AST_LIST_NEXT(result, frame_list) = write_frame; 04726 } 04727 } 04728 04729 return result; 04730 }
void ast_channel_spy_remove | ( | struct ast_channel * | chan, | |
struct ast_channel_spy * | spy | |||
) |
Remove a spy from a channel.
chan | The channel to remove the spy from | |
spy | The spy to be removed |
Definition at line 1491 of file channel.c.
Referenced by channel_spy().
01492 { 01493 if (!chan->spies) 01494 return; 01495 01496 AST_LIST_REMOVE(&chan->spies->list, spy, list); 01497 spy_detach(spy, chan); 01498 spy_cleanup(chan); 01499 }
void ast_channel_spy_stop_by_type | ( | struct ast_channel * | chan, | |
const char * | type | |||
) |
Find all spies of a particular type on a channel and stop them.
chan | The channel to operate on | |
type | A character string identifying the type of spies to be stopped |
Definition at line 1462 of file channel.c.
Referenced by mixmonitor_cli(), and stop_mixmonitor_exec().
01463 { 01464 struct ast_channel_spy *spy = NULL; 01465 01466 if (!chan->spies) 01467 return; 01468 01469 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->spies->list, spy, list) { 01470 if ((spy->type == type) && (spy->status == CHANSPY_RUNNING)) { 01471 AST_LIST_REMOVE_CURRENT(&chan->spies->list, list); 01472 spy_detach(spy, chan); 01473 } 01474 } 01475 AST_LIST_TRAVERSE_SAFE_END 01476 spy_cleanup(chan); 01477 }
void ast_channel_spy_trigger_wait | ( | struct ast_channel_spy * | spy | ) |
Efficiently wait until audio is available for a spy, or an exception occurs.
spy | The spy to wait on |
Definition at line 1479 of file channel.c.
Referenced by mixmonitor_thread().
01480 { 01481 struct timeval tv; 01482 struct timespec ts; 01483 01484 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000)); 01485 ts.tv_sec = tv.tv_sec; 01486 ts.tv_nsec = tv.tv_usec * 1000; 01487 01488 ast_cond_timedwait(&spy->trigger, &spy->lock, &ts); 01489 }
struct ast_silence_generator* ast_channel_start_silence_generator | ( | struct ast_channel * | chan | ) | [read] |
Starts a silence generator on the given channel.
chan | The channel to generate silence on |
The pointer returned by this function must be preserved and passed to ast_channel_stop_silence_generator when you wish to stop the silence generation.
Definition at line 4769 of file channel.c.
Referenced by __ast_play_and_record(), channel_spy(), and record_exec().
04770 { 04771 struct ast_silence_generator *state; 04772 04773 if (!(state = ast_calloc(1, sizeof(*state)))) { 04774 return NULL; 04775 } 04776 04777 state->old_write_format = chan->writeformat; 04778 04779 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 04780 ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n"); 04781 free(state); 04782 return NULL; 04783 } 04784 04785 ast_activate_generator(chan, &silence_generator, state); 04786 04787 if (option_debug) 04788 ast_log(LOG_DEBUG, "Started silence generator on '%s'\n", chan->name); 04789 04790 return state; 04791 }
void ast_channel_stop_silence_generator | ( | struct ast_channel * | chan, | |
struct ast_silence_generator * | state | |||
) |
Stops a previously-started silence generator on the given channel.
chan | The channel to operate on | |
state | The ast_silence_generator pointer return by a previous call to ast_channel_start_silence_generator. |
Definition at line 4793 of file channel.c.
Referenced by __ast_play_and_record(), channel_spy(), and record_exec().
04794 { 04795 if (!state) 04796 return; 04797 04798 ast_deactivate_generator(chan); 04799 04800 if (option_debug) 04801 ast_log(LOG_DEBUG, "Stopped silence generator on '%s'\n", chan->name); 04802 04803 if (ast_set_write_format(chan, state->old_write_format) < 0) 04804 ast_log(LOG_ERROR, "Could not return write format to its original state\n"); 04805 04806 free(state); 04807 }
int ast_channel_supports_html | ( | struct ast_channel * | channel | ) |
Checks for HTML support on a channel
Returns 0 if channel does not support HTML or non-zero if it does
Definition at line 3306 of file channel.c.
Referenced by sendurl_exec(), and try_calling().
void ast_channel_undefer_dtmf | ( | struct ast_channel * | chan | ) |
Unset defer DTMF flag on channel.
Undeos a defer
Undo defer. ast_read will return any dtmf characters that were queued
Definition at line 998 of file channel.c.
Referenced by __adsi_transmit_messages(), find_cache(), and rpt_call().
00999 { 01000 if (chan) 01001 ast_clear_flag(chan, AST_FLAG_DEFER_DTMF); 01002 }
void ast_channel_unregister | ( | const struct ast_channel_tech * | tech | ) |
Unregister a channel technology.
tech | Structure defining channel technology or "type" that was previously registered |
Definition at line 548 of file channel.c.
Referenced by __unload_module(), and unload_module().
00549 { 00550 struct chanlist *chan; 00551 00552 if (option_debug) 00553 ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", tech->type); 00554 00555 AST_LIST_LOCK(&channels); 00556 00557 AST_LIST_TRAVERSE_SAFE_BEGIN(&backends, chan, list) { 00558 if (chan->tech == tech) { 00559 AST_LIST_REMOVE_CURRENT(&backends, list); 00560 free(chan); 00561 if (option_verbose > 1) 00562 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", tech->type); 00563 break; 00564 } 00565 } 00566 AST_LIST_TRAVERSE_SAFE_END 00567 00568 AST_LIST_UNLOCK(&channels); 00569 }
struct ast_channel* ast_channel_walk_locked | ( | const struct ast_channel * | prev | ) | [read] |
Browse channels in use.
Browse channels in use Browse the channels currently in use.
Definition at line 1111 of file channel.c.
Referenced by action_status(), ast_complete_channels(), ast_pickup_call(), complete_ch_helper(), conf_exec(), handle_chanlist(), handle_chanlist_deprecated(), handle_core_set_debug_channel(), handle_debugchan_deprecated(), handle_nodebugchan_deprecated(), moh_on_off(), next_channel(), pickup_by_exten(), pickup_by_mark(), and softhangup_exec().
01112 { 01113 return channel_find_locked(prev, NULL, 0, NULL, NULL); 01114 }
int ast_channel_whisper_feed | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) |
Feed an audio frame into the whisper buffer on a channel.
chan | The channel to whisper onto | |
f | The frame to to whisper onto chan |
Definition at line 5007 of file channel.c.
Referenced by channel_spy().
05008 { 05009 if (!chan->whisper) 05010 return -1; 05011 05012 ast_mutex_lock(&chan->whisper->lock); 05013 ast_slinfactory_feed(&chan->whisper->sf, f); 05014 ast_mutex_unlock(&chan->whisper->lock); 05015 05016 return 0; 05017 }
int ast_channel_whisper_start | ( | struct ast_channel * | chan | ) |
Begin 'whispering' onto a channel.
chan | The channel to whisper onto |
Note: This function performs no locking; you must hold the channel's lock before calling this function.
Definition at line 4992 of file channel.c.
Referenced by channel_spy().
04993 { 04994 if (chan->whisper) 04995 return -1; 04996 04997 if (!(chan->whisper = ast_calloc(1, sizeof(*chan->whisper)))) 04998 return -1; 04999 05000 ast_mutex_init(&chan->whisper->lock); 05001 ast_slinfactory_init(&chan->whisper->sf); 05002 ast_set_flag(chan, AST_FLAG_WHISPER); 05003 05004 return 0; 05005 }
void ast_channel_whisper_stop | ( | struct ast_channel * | chan | ) |
Stop 'whispering' onto a channel.
chan | The channel to whisper onto |
Definition at line 5019 of file channel.c.
Referenced by ast_channel_free(), ast_do_masquerade(), and channel_spy().
05020 { 05021 if (!chan->whisper) 05022 return; 05023 05024 ast_clear_flag(chan, AST_FLAG_WHISPER); 05025 if (chan->whisper->path) 05026 ast_translator_free_path(chan->whisper->path); 05027 if (chan->whisper->original_format && chan->writeformat == AST_FORMAT_SLINEAR) 05028 ast_set_write_format(chan, chan->whisper->original_format); 05029 ast_slinfactory_destroy(&chan->whisper->sf); 05030 ast_mutex_destroy(&chan->whisper->lock); 05031 free(chan->whisper); 05032 chan->whisper = NULL; 05033 }
void ast_channels_init | ( | void | ) |
Provided by channel.c
Definition at line 4570 of file channel.c.
Referenced by main().
04571 { 04572 ast_cli_register_multiple(cli_channel, sizeof(cli_channel) / sizeof(struct ast_cli_entry)); 04573 }
struct ast_variable* ast_channeltype_list | ( | void | ) | [read] |
return an ast_variable list of channeltypes
Definition at line 182 of file channel.c.
00183 { 00184 struct chanlist *cl; 00185 struct ast_variable *var=NULL, *prev = NULL; 00186 AST_LIST_TRAVERSE(&backends, cl, list) { 00187 if (prev) { 00188 if ((prev->next = ast_variable_new(cl->tech->type, cl->tech->description))) 00189 prev = prev->next; 00190 } else { 00191 var = ast_variable_new(cl->tech->type, cl->tech->description); 00192 prev = var; 00193 } 00194 } 00195 return var; 00196 }
int ast_check_hangup | ( | struct ast_channel * | chan | ) |
Checks to see if a channel is needing hang up.
Check to see if a channel is needing hang up.
Definition at line 404 of file channel.c.
Referenced by __ast_read(), action_redirect(), app_exec(), ast_answer(), ast_call(), ast_channel_bridge(), ast_check_hangup_locked(), ast_feature_request_and_dial(), ast_indicate_data(), ast_readstring_full(), ast_recvtext(), ast_sendtext(), ast_transfer(), ast_udptl_bridge(), ast_waitfordigit_full(), ast_write(), bridge_native_loop(), bridge_p2p_loop(), builtin_atxfer(), channel_spy(), common_exec(), conf_run(), deadagi_exec(), handle_sendimage(), iax2_bridge(), pbx_exec(), rpt(), rpt_exec(), wait_for_answer(), zt_sendtext(), and zt_setoption().
00405 { 00406 if (chan->_softhangup) /* yes if soft hangup flag set */ 00407 return 1; 00408 if (!chan->tech_pvt) /* yes if no technology private data */ 00409 return 1; 00410 if (!chan->whentohangup) /* no if no hangup scheduled */ 00411 return 0; 00412 if (chan->whentohangup > time(NULL)) /* no if hangup time has not come yet. */ 00413 return 0; 00414 chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; /* record event */ 00415 return 1; 00416 }
static int ast_check_hangup_locked | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 418 of file channel.c.
References ast_channel_lock, ast_channel_unlock, and ast_check_hangup().
Referenced by ast_channel_bridge().
00419 { 00420 int res; 00421 ast_channel_lock(chan); 00422 res = ast_check_hangup(chan); 00423 ast_channel_unlock(chan); 00424 return res; 00425 }
void ast_deactivate_generator | ( | struct ast_channel * | chan | ) |
Deactive an active generator
Definition at line 1823 of file channel.c.
Referenced by __ast_read(), app_exec(), ast_channel_stop_silence_generator(), ast_openstream_full(), ast_playtones_stop(), ast_quiet_chan(), ast_read_generator_actions(), ast_tonepair_stop(), ast_write(), cb_events(), channel_spy(), generator_force(), local_ast_moh_stop(), milliwatt_exec(), moh_on_off(), and wait_for_answer().
01824 { 01825 ast_channel_lock(chan); 01826 if (chan->generatordata) { 01827 if (chan->generator && chan->generator->release) 01828 chan->generator->release(chan, chan->generatordata); 01829 chan->generatordata = NULL; 01830 chan->generator = NULL; 01831 chan->fds[AST_GENERATOR_FD] = -1; 01832 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 01833 ast_settimeout(chan, 0, NULL, NULL); 01834 } 01835 ast_channel_unlock(chan); 01836 }
int ast_do_masquerade | ( | struct ast_channel * | original | ) |
Masquerade a channel.
Start masquerading a channel XXX This is a seriously wacked out operation. We're essentially putting the guts of the clone channel into the original channel. Start by killing off the original channel's backend. I'm not sure we're going to keep this function, because while the features are nice, the cost is very high in terms of pure nastiness. XXX.
Definition at line 3529 of file channel.c.
Referenced by __ast_read(), ast_async_goto(), ast_hangup(), ast_waitfor_nandfds(), ast_write(), iax_park(), sip_park(), and sip_park_thread().
03530 { 03531 int x,i; 03532 int res=0; 03533 int origstate; 03534 struct ast_frame *cur; 03535 const struct ast_channel_tech *t; 03536 void *t_pvt; 03537 struct ast_callerid tmpcid; 03538 struct ast_channel *clone = original->masq; 03539 struct ast_channel_spy_list *spy_list = NULL; 03540 struct ast_channel_spy *spy = NULL; 03541 struct ast_cdr *cdr; 03542 int rformat = original->readformat; 03543 int wformat = original->writeformat; 03544 char newn[100]; 03545 char orig[100]; 03546 char masqn[100]; 03547 char zombn[100]; 03548 03549 if (option_debug > 3) 03550 ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n", 03551 clone->name, clone->_state, original->name, original->_state); 03552 03553 /* XXX This is a seriously wacked out operation. We're essentially putting the guts of 03554 the clone channel into the original channel. Start by killing off the original 03555 channel's backend. I'm not sure we're going to keep this function, because 03556 while the features are nice, the cost is very high in terms of pure nastiness. XXX */ 03557 03558 /* We need the clone's lock, too */ 03559 ast_channel_lock(clone); 03560 03561 if (option_debug > 1) 03562 ast_log(LOG_DEBUG, "Got clone lock for masquerade on '%s' at %p\n", clone->name, &clone->lock); 03563 03564 /* Having remembered the original read/write formats, we turn off any translation on either 03565 one */ 03566 free_translation(clone); 03567 free_translation(original); 03568 03569 03570 /* Unlink the masquerade */ 03571 original->masq = NULL; 03572 clone->masqr = NULL; 03573 03574 /* Save the original name */ 03575 ast_copy_string(orig, original->name, sizeof(orig)); 03576 /* Save the new name */ 03577 ast_copy_string(newn, clone->name, sizeof(newn)); 03578 /* Create the masq name */ 03579 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn); 03580 03581 /* Copy the name from the clone channel */ 03582 ast_string_field_set(original, name, newn); 03583 03584 /* Mangle the name of the clone channel */ 03585 ast_string_field_set(clone, name, masqn); 03586 03587 /* Notify any managers of the change, first the masq then the other */ 03588 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid); 03589 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid); 03590 03591 /* Swap the technologies */ 03592 t = original->tech; 03593 original->tech = clone->tech; 03594 clone->tech = t; 03595 03596 /* Swap the cdrs */ 03597 cdr = original->cdr; 03598 original->cdr = clone->cdr; 03599 clone->cdr = cdr; 03600 03601 t_pvt = original->tech_pvt; 03602 original->tech_pvt = clone->tech_pvt; 03603 clone->tech_pvt = t_pvt; 03604 03605 /* Swap the readq's */ 03606 cur = AST_LIST_FIRST(&original->readq); 03607 AST_LIST_HEAD_SET_NOLOCK(&original->readq, AST_LIST_FIRST(&clone->readq)); 03608 AST_LIST_HEAD_SET_NOLOCK(&clone->readq, cur); 03609 03610 /* Swap the alertpipes */ 03611 for (i = 0; i < 2; i++) { 03612 x = original->alertpipe[i]; 03613 original->alertpipe[i] = clone->alertpipe[i]; 03614 clone->alertpipe[i] = x; 03615 } 03616 03617 /* Swap the raw formats */ 03618 x = original->rawreadformat; 03619 original->rawreadformat = clone->rawreadformat; 03620 clone->rawreadformat = x; 03621 x = original->rawwriteformat; 03622 original->rawwriteformat = clone->rawwriteformat; 03623 clone->rawwriteformat = x; 03624 03625 /* Swap the spies */ 03626 spy_list = original->spies; 03627 original->spies = clone->spies; 03628 clone->spies = spy_list; 03629 03630 /* Update channel on respective spy lists if present */ 03631 if (original->spies) { 03632 AST_LIST_TRAVERSE(&original->spies->list, spy, list) { 03633 ast_mutex_lock(&spy->lock); 03634 spy->chan = original; 03635 ast_mutex_unlock(&spy->lock); 03636 } 03637 } 03638 if (clone->spies) { 03639 AST_LIST_TRAVERSE(&clone->spies->list, spy, list) { 03640 ast_mutex_lock(&spy->lock); 03641 spy->chan = clone; 03642 ast_mutex_unlock(&spy->lock); 03643 } 03644 } 03645 03646 /* Save any pending frames on both sides. Start by counting 03647 * how many we're going to need... */ 03648 x = 0; 03649 if (original->alertpipe[1] > -1) { 03650 AST_LIST_TRAVERSE(&clone->readq, cur, frame_list) 03651 x++; 03652 } 03653 03654 /* If we had any, prepend them to the ones already in the queue, and 03655 * load up the alertpipe */ 03656 if (AST_LIST_FIRST(&clone->readq)) { 03657 AST_LIST_INSERT_TAIL(&clone->readq, AST_LIST_FIRST(&original->readq), frame_list); 03658 AST_LIST_HEAD_SET_NOLOCK(&original->readq, AST_LIST_FIRST(&clone->readq)); 03659 AST_LIST_HEAD_SET_NOLOCK(&clone->readq, NULL); 03660 for (i = 0; i < x; i++) 03661 write(original->alertpipe[1], &x, sizeof(x)); 03662 } 03663 03664 clone->_softhangup = AST_SOFTHANGUP_DEV; 03665 03666 03667 /* And of course, so does our current state. Note we need not 03668 call ast_setstate since the event manager doesn't really consider 03669 these separate. We do this early so that the clone has the proper 03670 state of the original channel. */ 03671 origstate = original->_state; 03672 original->_state = clone->_state; 03673 clone->_state = origstate; 03674 03675 if (clone->tech->fixup){ 03676 res = clone->tech->fixup(original, clone); 03677 if (res) 03678 ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name); 03679 } 03680 03681 /* Start by disconnecting the original's physical side */ 03682 if (clone->tech->hangup) 03683 res = clone->tech->hangup(clone); 03684 if (res) { 03685 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n"); 03686 ast_channel_unlock(clone); 03687 return -1; 03688 } 03689 03690 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig); 03691 /* Mangle the name of the clone channel */ 03692 ast_string_field_set(clone, name, zombn); 03693 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid); 03694 03695 /* Update the type. */ 03696 t_pvt = original->monitor; 03697 original->monitor = clone->monitor; 03698 clone->monitor = t_pvt; 03699 03700 /* Keep the same language. */ 03701 ast_string_field_set(original, language, clone->language); 03702 /* Copy the FD's other than the generator fd */ 03703 for (x = 0; x < AST_MAX_FDS; x++) { 03704 if (x != AST_GENERATOR_FD) 03705 original->fds[x] = clone->fds[x]; 03706 } 03707 03708 ast_app_group_update(clone, original); 03709 03710 /* move any whisperer over */ 03711 ast_channel_whisper_stop(original); 03712 if (ast_test_flag(clone, AST_FLAG_WHISPER)) { 03713 original->whisper = clone->whisper; 03714 ast_set_flag(original, AST_FLAG_WHISPER); 03715 clone->whisper = NULL; 03716 ast_clear_flag(clone, AST_FLAG_WHISPER); 03717 } 03718 03719 /* Move data stores over */ 03720 if (AST_LIST_FIRST(&clone->datastores)) 03721 AST_LIST_INSERT_TAIL(&original->datastores, AST_LIST_FIRST(&clone->datastores), entry); 03722 AST_LIST_HEAD_INIT_NOLOCK(&clone->datastores); 03723 03724 clone_variables(original, clone); 03725 /* Presense of ADSI capable CPE follows clone */ 03726 original->adsicpe = clone->adsicpe; 03727 /* Bridge remains the same */ 03728 /* CDR fields remain the same */ 03729 /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */ 03730 /* Application and data remain the same */ 03731 /* Clone exception becomes real one, as with fdno */ 03732 ast_copy_flags(original, clone, AST_FLAG_EXCEPTION); 03733 original->fdno = clone->fdno; 03734 /* Schedule context remains the same */ 03735 /* Stream stuff stays the same */ 03736 /* Keep the original state. The fixup code will need to work with it most likely */ 03737 03738 /* Just swap the whole structures, nevermind the allocations, they'll work themselves 03739 out. */ 03740 tmpcid = original->cid; 03741 original->cid = clone->cid; 03742 clone->cid = tmpcid; 03743 03744 /* Restore original timing file descriptor */ 03745 original->fds[AST_TIMING_FD] = original->timingfd; 03746 03747 /* Our native formats are different now */ 03748 original->nativeformats = clone->nativeformats; 03749 03750 /* Context, extension, priority, app data, jump table, remain the same */ 03751 /* pvt switches. pbx stays the same, as does next */ 03752 03753 /* Set the write format */ 03754 ast_set_write_format(original, wformat); 03755 03756 /* Set the read format */ 03757 ast_set_read_format(original, rformat); 03758 03759 /* Copy the music class */ 03760 ast_string_field_set(original, musicclass, clone->musicclass); 03761 03762 if (option_debug) 03763 ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat); 03764 03765 /* Okay. Last thing is to let the channel driver know about all this mess, so he 03766 can fix up everything as best as possible */ 03767 if (original->tech->fixup) { 03768 res = original->tech->fixup(clone, original); 03769 if (res) { 03770 ast_log(LOG_WARNING, "Channel for type '%s' could not fixup channel %s\n", 03771 original->tech->type, original->name); 03772 ast_channel_unlock(clone); 03773 return -1; 03774 } 03775 } else 03776 ast_log(LOG_WARNING, "Channel type '%s' does not have a fixup routine (for %s)! Bad things may happen.\n", 03777 original->tech->type, original->name); 03778 03779 /* Now, at this point, the "clone" channel is totally F'd up. We mark it as 03780 a zombie so nothing tries to touch it. If it's already been marked as a 03781 zombie, then free it now (since it already is considered invalid). */ 03782 if (ast_test_flag(clone, AST_FLAG_ZOMBIE)) { 03783 if (option_debug) 03784 ast_log(LOG_DEBUG, "Destroying channel clone '%s'\n", clone->name); 03785 ast_channel_unlock(clone); 03786 manager_event(EVENT_FLAG_CALL, "Hangup", 03787 "Channel: %s\r\n" 03788 "Uniqueid: %s\r\n" 03789 "Cause: %d\r\n" 03790 "Cause-txt: %s\r\n", 03791 clone->name, 03792 clone->uniqueid, 03793 clone->hangupcause, 03794 ast_cause2str(clone->hangupcause) 03795 ); 03796 ast_channel_free(clone); 03797 } else { 03798 if (option_debug) 03799 ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name); 03800 ast_set_flag(clone, AST_FLAG_ZOMBIE); 03801 ast_queue_frame(clone, &ast_null_frame); 03802 ast_channel_unlock(clone); 03803 } 03804 03805 /* Signal any blocker */ 03806 if (ast_test_flag(original, AST_FLAG_BLOCKING)) 03807 pthread_kill(original->blocker, SIGURG); 03808 if (option_debug) 03809 ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n", original->name, original->_state); 03810 return 0; 03811 }
static enum ast_bridge_result ast_generic_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
struct ast_bridge_config * | config, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc, | |||
struct timeval | bridge_end | |||
) | [static] |
Definition at line 3916 of file channel.c.
References ast_channel::_bridge, ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate_data(), ast_jb_do_usecheck(), ast_jb_get_and_deliver(), ast_jb_get_when_to_wakeup(), ast_jb_put(), ast_log(), ast_read(), AST_SOFTHANGUP_UNBRIDGE, ast_waitfor_n(), ast_write(), ast_frame::data, ast_frame::datalen, f, ast_bridge_config::flags, ast_frame::frametype, LOG_DEBUG, ast_channel::nativeformats, option_debug, ast_frame::subclass, ast_channel::tech_pvt, and ast_bridge_config::timelimit.
Referenced by ast_channel_bridge().
03919 { 03920 /* Copy voice back and forth between the two channels. */ 03921 struct ast_channel *cs[3]; 03922 struct ast_frame *f; 03923 enum ast_bridge_result res = AST_BRIDGE_COMPLETE; 03924 int o0nativeformats; 03925 int o1nativeformats; 03926 int watch_c0_dtmf; 03927 int watch_c1_dtmf; 03928 void *pvt0, *pvt1; 03929 /* Indicates whether a frame was queued into a jitterbuffer */ 03930 int frame_put_in_jb = 0; 03931 int jb_in_use; 03932 int to; 03933 03934 cs[0] = c0; 03935 cs[1] = c1; 03936 pvt0 = c0->tech_pvt; 03937 pvt1 = c1->tech_pvt; 03938 o0nativeformats = c0->nativeformats; 03939 o1nativeformats = c1->nativeformats; 03940 watch_c0_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_0; 03941 watch_c1_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_1; 03942 03943 /* Check the need of a jitterbuffer for each channel */ 03944 jb_in_use = ast_jb_do_usecheck(c0, c1); 03945 03946 for (;;) { 03947 struct ast_channel *who, *other; 03948 03949 if ((c0->tech_pvt != pvt0) || (c1->tech_pvt != pvt1) || 03950 (o0nativeformats != c0->nativeformats) || 03951 (o1nativeformats != c1->nativeformats)) { 03952 /* Check for Masquerade, codec changes, etc */ 03953 res = AST_BRIDGE_RETRY; 03954 break; 03955 } 03956 if (bridge_end.tv_sec) { 03957 to = ast_tvdiff_ms(bridge_end, ast_tvnow()); 03958 if (to <= 0) { 03959 if (config->timelimit) 03960 res = AST_BRIDGE_RETRY; 03961 else 03962 res = AST_BRIDGE_COMPLETE; 03963 break; 03964 } 03965 } else 03966 to = -1; 03967 /* Calculate the appropriate max sleep interval - in general, this is the time, 03968 left to the closest jb delivery moment */ 03969 if (jb_in_use) 03970 to = ast_jb_get_when_to_wakeup(c0, c1, to); 03971 who = ast_waitfor_n(cs, 2, &to); 03972 if (!who) { 03973 /* No frame received within the specified timeout - check if we have to deliver now */ 03974 if (jb_in_use) 03975 ast_jb_get_and_deliver(c0, c1); 03976 if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) { 03977 if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE) 03978 c0->_softhangup = 0; 03979 if (c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) 03980 c1->_softhangup = 0; 03981 c0->_bridge = c1; 03982 c1->_bridge = c0; 03983 } 03984 continue; 03985 } 03986 f = ast_read(who); 03987 if (!f) { 03988 *fo = NULL; 03989 *rc = who; 03990 if (option_debug) 03991 ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name); 03992 break; 03993 } 03994 03995 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 03996 /* Try add the frame info the who's bridged channel jitterbuff */ 03997 if (jb_in_use) 03998 frame_put_in_jb = !ast_jb_put(other, f); 03999 04000 if ((f->frametype == AST_FRAME_CONTROL) && !(config->flags & AST_BRIDGE_IGNORE_SIGS)) { 04001 int bridge_exit = 0; 04002 04003 switch (f->subclass) { 04004 case AST_CONTROL_HOLD: 04005 case AST_CONTROL_UNHOLD: 04006 case AST_CONTROL_VIDUPDATE: 04007 ast_indicate_data(other, f->subclass, f->data, f->datalen); 04008 break; 04009 default: 04010 *fo = f; 04011 *rc = who; 04012 bridge_exit = 1; 04013 if (option_debug) 04014 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name); 04015 break; 04016 } 04017 if (bridge_exit) 04018 break; 04019 } 04020 if ((f->frametype == AST_FRAME_VOICE) || 04021 (f->frametype == AST_FRAME_DTMF_BEGIN) || 04022 (f->frametype == AST_FRAME_DTMF) || 04023 (f->frametype == AST_FRAME_VIDEO) || 04024 (f->frametype == AST_FRAME_IMAGE) || 04025 (f->frametype == AST_FRAME_HTML) || 04026 (f->frametype == AST_FRAME_MODEM) || 04027 (f->frametype == AST_FRAME_TEXT)) { 04028 /* monitored dtmf causes exit from bridge */ 04029 int monitored_source = (who == c0) ? watch_c0_dtmf : watch_c1_dtmf; 04030 04031 if (monitored_source && 04032 (f->frametype == AST_FRAME_DTMF_END || 04033 f->frametype == AST_FRAME_DTMF_BEGIN)) { 04034 *fo = f; 04035 *rc = who; 04036 if (option_debug) 04037 ast_log(LOG_DEBUG, "Got DTMF %s on channel (%s)\n", 04038 f->frametype == AST_FRAME_DTMF_END ? "end" : "begin", 04039 who->name); 04040 break; 04041 } 04042 /* Write immediately frames, not passed through jb */ 04043 if (!frame_put_in_jb) 04044 ast_write(other, f); 04045 04046 /* Check if we have to deliver now */ 04047 if (jb_in_use) 04048 ast_jb_get_and_deliver(c0, c1); 04049 } 04050 /* XXX do we want to pass on also frames not matched above ? */ 04051 ast_frfree(f); 04052 04053 /* Swap who gets priority */ 04054 cs[2] = cs[0]; 04055 cs[0] = cs[1]; 04056 cs[1] = cs[2]; 04057 } 04058 return res; 04059 }
struct ast_channel* ast_get_channel_by_exten_locked | ( | const char * | exten, | |
const char * | context | |||
) | [read] |
Get channel by exten (and optionally context) and lock it.
Definition at line 1136 of file channel.c.
01137 { 01138 return channel_find_locked(NULL, NULL, 0, context, exten); 01139 }
struct ast_channel* ast_get_channel_by_name_locked | ( | const char * | name | ) | [read] |
Get channel by name and lock it.
Get channel by name (locks channel).
Definition at line 1117 of file channel.c.
Referenced by action_getvar(), action_hangup(), action_redirect(), action_setcdruserfield(), action_setvar(), action_status(), action_timeout(), ast_async_goto_by_name(), asyncgoto_exec(), change_monitor_action(), do_pause_or_unpause(), get_zap_channel_locked(), handle_channelstatus(), handle_core_set_debug_channel(), handle_debugchan_deprecated(), handle_getvariablefull(), handle_hangup(), handle_nodebugchan_deprecated(), handle_showchan(), handle_showchan_deprecated(), handle_softhangup(), manager_park(), manager_play_dtmf(), pbx_builtin_importvar(), start_monitor_action(), and stop_monitor_action().
01118 { 01119 return channel_find_locked(NULL, name, 0, NULL, NULL); 01120 }
struct ast_channel* ast_get_channel_by_name_prefix_locked | ( | const char * | name, | |
const int | namelen | |||
) | [read] |
Get channel by name prefix and lock it.
Get channel by name prefix (locks channel).
Definition at line 1123 of file channel.c.
Referenced by ast_parse_device_state(), common_exec(), and mixmonitor_cli().
01124 { 01125 return channel_find_locked(NULL, name, namelen, NULL, NULL); 01126 }
struct ast_channel_tech* ast_get_channel_tech | ( | const char * | name | ) | [read] |
Get a channel technology structure by name.
name | name of technology to find |
Definition at line 571 of file channel.c.
Referenced by ast_device_state().
00572 { 00573 struct chanlist *chanls; 00574 const struct ast_channel_tech *ret = NULL; 00575 00576 if (AST_LIST_LOCK(&channels)) { 00577 ast_log(LOG_WARNING, "Unable to lock channel tech list\n"); 00578 return NULL; 00579 } 00580 00581 AST_LIST_TRAVERSE(&backends, chanls, list) { 00582 if (!strcasecmp(name, chanls->tech->type)) { 00583 ret = chanls->tech; 00584 break; 00585 } 00586 } 00587 00588 AST_LIST_UNLOCK(&channels); 00589 00590 return ret; 00591 }
ast_group_t ast_get_group | ( | const char * | s | ) |
Definition at line 4494 of file channel.c.
Referenced by _parse(), build_device(), build_gateway(), build_peer(), build_user(), func_channel_write(), process_zap(), and read_agent_config().
04495 { 04496 char *piece; 04497 char *c; 04498 int start=0, finish=0, x; 04499 ast_group_t group = 0; 04500 04501 c = ast_strdupa(s); 04502 04503 while ((piece = strsep(&c, ","))) { 04504 if (sscanf(piece, "%d-%d", &start, &finish) == 2) { 04505 /* Range */ 04506 } else if (sscanf(piece, "%d", &start)) { 04507 /* Just one */ 04508 finish = start; 04509 } else { 04510 ast_log(LOG_ERROR, "Syntax error parsing group configuration '%s' at '%s'. Ignoring.\n", s, piece); 04511 continue; 04512 } 04513 for (x = start; x <= finish; x++) { 04514 if ((x > 63) || (x < 0)) { 04515 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 63)\n", x); 04516 } else 04517 group |= ((ast_group_t) 1 << x); 04518 } 04519 } 04520 return group; 04521 }
int ast_hangup | ( | struct ast_channel * | chan | ) |
Hangup a channel.
Hang up a channel.
Definition at line 1703 of file channel.c.
Referenced by __ast_pbx_run(), __ast_request_and_dial(), __oh323_new(), agent_hangup(), agent_read(), alsa_new(), app_exec(), ast_async_goto(), ast_bridge_call_thread(), ast_dial_destroy(), ast_dial_hangup(), ast_feature_request_and_dial(), ast_iax2_new(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_pbx_run_app(), async_wait(), begin_dial(), build_conf(), builtin_atxfer(), chanavail_exec(), check_compat(), check_goto_on_transfer(), clear_caller(), conf_free(), conf_run(), connect_link(), do_hang(), do_parking_thread(), features_hangup(), findmeexec(), gtalk_new(), handle_enbloc_call_message(), handle_frame(), handle_frame_ownerless(), handle_hd_hf(), handle_init_event(), handle_invite_replaces(), handle_offhook_message(), handle_request_invite(), handle_soft_key_event_message(), handle_stimulus_message(), hangup_chan(), hangupcalls(), hanguptree(), iax2_request(), iax_park(), iax_park_thread(), local_attended_transfer(), local_hangup(), mgcp_new(), mgcp_ss(), monitor_dial(), nbs_new(), oss_new(), park_exec(), parkandannounce_exec(), phone_new(), rpt(), rpt_call(), rpt_exec(), rpt_tele_thread(), sip_new(), sip_park(), sip_park_thread(), skinny_new(), skinny_ss(), ss_thread(), try_calling(), wait_for_answer(), wait_for_winner(), zt_handle_event(), and zt_new().
01704 { 01705 int res = 0; 01706 struct ast_cdr *cdr = NULL; 01707 01708 /* Don't actually hang up a channel that will masquerade as someone else, or 01709 if someone is going to masquerade as us */ 01710 ast_channel_lock(chan); 01711 01712 detach_spies(chan); /* get rid of spies */ 01713 01714 if (chan->masq) { 01715 if (ast_do_masquerade(chan)) 01716 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 01717 } 01718 01719 if (chan->masq) { 01720 ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name); 01721 ast_channel_unlock(chan); 01722 return 0; 01723 } 01724 /* If this channel is one which will be masqueraded into something, 01725 mark it as a zombie already, so we know to free it later */ 01726 if (chan->masqr) { 01727 ast_set_flag(chan, AST_FLAG_ZOMBIE); 01728 ast_channel_unlock(chan); 01729 return 0; 01730 } 01731 free_translation(chan); 01732 /* Close audio stream */ 01733 if (chan->stream) { 01734 ast_closestream(chan->stream); 01735 chan->stream = NULL; 01736 } 01737 /* Close video stream */ 01738 if (chan->vstream) { 01739 ast_closestream(chan->vstream); 01740 chan->vstream = NULL; 01741 } 01742 if (chan->sched) { 01743 sched_context_destroy(chan->sched); 01744 chan->sched = NULL; 01745 } 01746 01747 if (chan->generatordata) /* Clear any tone stuff remaining */ 01748 chan->generator->release(chan, chan->generatordata); 01749 chan->generatordata = NULL; 01750 chan->generator = NULL; 01751 if (chan->cdr) { /* End the CDR if it hasn't already */ 01752 ast_cdr_end(chan->cdr); 01753 cdr = chan->cdr; 01754 chan->cdr = NULL; 01755 } 01756 if (ast_test_flag(chan, AST_FLAG_BLOCKING)) { 01757 ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd " 01758 "is blocked by thread %ld in procedure %s! Expect a failure\n", 01759 (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc); 01760 CRASH; 01761 } 01762 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE)) { 01763 if (option_debug) 01764 ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name); 01765 if (chan->tech->hangup) 01766 res = chan->tech->hangup(chan); 01767 } else { 01768 if (option_debug) 01769 ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name); 01770 } 01771 01772 ast_channel_unlock(chan); 01773 manager_event(EVENT_FLAG_CALL, "Hangup", 01774 "Channel: %s\r\n" 01775 "Uniqueid: %s\r\n" 01776 "Cause: %d\r\n" 01777 "Cause-txt: %s\r\n", 01778 chan->name, 01779 chan->uniqueid, 01780 chan->hangupcause, 01781 ast_cause2str(chan->hangupcause) 01782 ); 01783 ast_channel_free(chan); 01784 01785 if (cdr) 01786 ast_cdr_detach(cdr); 01787 01788 return res; 01789 }
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 |
Definition at line 2557 of file channel.c.
Referenced by __ast_play_and_record(), agent_new(), ast_bridge_call(), ast_dtmf_stream(), ast_feature_request_and_dial(), attempt_transfer(), builtin_atxfer(), builtin_blindtransfer(), conf_run(), disa_exec(), do_parking_thread(), features_indicate(), finishup(), function_remote(), handle_frame(), handle_recordfile(), mgcp_ss(), monitor_dial(), park_exec(), pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_progress(), pbx_builtin_ringing(), pbx_builtin_waitexten(), queue_exec(), record_exec(), rpt(), rpt_exec(), send_waveform_to_channel(), skinny_ss(), sla_handle_hold_event(), sla_station_exec(), sla_trunk_exec(), and wait_for_answer().
02558 { 02559 return ast_indicate_data(chan, condition, NULL, 0); 02560 }
int ast_indicate_data | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) |
Indicates condition of channel, with payload.
chan | channel to change the indication | |
condition | which condition to indicate on the channel | |
data | pointer to payload data | |
datalen | size of payload data |
Definition at line 2562 of file channel.c.
Referenced by __login_exec(), agent_hangup(), ast_bridge_call(), ast_generic_bridge(), ast_indicate(), ast_park_call(), bridge_native_loop(), bridge_p2p_loop(), do_parking_thread(), pbx_builtin_waitexten(), and wait_for_answer().
02563 { 02564 int res = -1; 02565 02566 ast_channel_lock(chan); 02567 /* Stop if we're a zombie or need a soft hangup */ 02568 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 02569 ast_channel_unlock(chan); 02570 return -1; 02571 } 02572 if (chan->tech->indicate) 02573 res = chan->tech->indicate(chan, condition, data, datalen); 02574 ast_channel_unlock(chan); 02575 if (!chan->tech->indicate || res) { 02576 /* 02577 * Device does not support (that) indication, lets fake 02578 * it by doing our own tone generation. (PM2002) 02579 */ 02580 if (condition < 0) 02581 ast_playtones_stop(chan); 02582 else { 02583 const struct tone_zone_sound *ts = NULL; 02584 switch (condition) { 02585 case AST_CONTROL_RINGING: 02586 ts = ast_get_indication_tone(chan->zone, "ring"); 02587 break; 02588 case AST_CONTROL_BUSY: 02589 ts = ast_get_indication_tone(chan->zone, "busy"); 02590 break; 02591 case AST_CONTROL_CONGESTION: 02592 ts = ast_get_indication_tone(chan->zone, "congestion"); 02593 break; 02594 } 02595 if (ts && ts->data[0]) { 02596 if (option_debug) 02597 ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition); 02598 ast_playtones_start(chan,0,ts->data, 1); 02599 res = 0; 02600 } else if (condition == AST_CONTROL_PROGRESS) { 02601 /* ast_playtones_stop(chan); */ 02602 } else if (condition == AST_CONTROL_PROCEEDING) { 02603 /* Do nothing, really */ 02604 } else if (condition == AST_CONTROL_HOLD) { 02605 /* Do nothing.... */ 02606 } else if (condition == AST_CONTROL_UNHOLD) { 02607 /* Do nothing.... */ 02608 } else if (condition == AST_CONTROL_VIDUPDATE) { 02609 /* Do nothing.... */ 02610 } else { 02611 /* not handled */ 02612 ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name); 02613 res = -1; 02614 } 02615 } 02616 } 02617 return res; 02618 }
void ast_install_music_functions | ( | int(*)(struct ast_channel *, const char *, const char *) | start_ptr, | |
void(*)(struct ast_channel *) | stop_ptr, | |||
void(*)(struct ast_channel *) | cleanup_ptr | |||
) |
Definition at line 4527 of file channel.c.
Referenced by load_module(), and reload().
04530 { 04531 ast_moh_start_ptr = start_ptr; 04532 ast_moh_stop_ptr = stop_ptr; 04533 ast_moh_cleanup_ptr = cleanup_ptr; 04534 }
int ast_internal_timing_enabled | ( | struct ast_channel * | chan | ) |
Check if the channel can run in internal timing mode.
chan | The channel to check |
Definition at line 2539 of file channel.c.
Referenced by add_sdp(), and ast_read_generator_actions().
02540 { 02541 int ret = ast_opt_internal_timing && chan->timingfd > -1; 02542 if (option_debug > 4) 02543 ast_log(LOG_DEBUG, "Internal timing is %s (option_internal_timing=%d chan->timingfd=%d)\n", ret? "enabled": "disabled", ast_opt_internal_timing, chan->timingfd); 02544 return ret; 02545 }
static AST_LIST_HEAD_NOLOCK_STATIC | ( | backends | , | |
chanlist | ||||
) | [static] |
the list of registered channel types
static AST_LIST_HEAD_STATIC | ( | channels | , | |
ast_channel | ||||
) | [static] |
the list of channels we have. Note that the lock for this list is used for both the channels list and the backends list.
void ast_moh_cleanup | ( | struct ast_channel * | chan | ) |
Definition at line 4564 of file channel.c.
Referenced by ast_channel_free().
04565 { 04566 if (ast_moh_cleanup_ptr) 04567 ast_moh_cleanup_ptr(chan); 04568 }
int ast_moh_start | ( | struct ast_channel * | chan, | |
const char * | mclass, | |||
const char * | interpclass | |||
) |
Turn on music on hold on a given channel.
chan | The channel structure that will get music on hold | |
mclass | The class to use if the musicclass is not currently set on the channel structure. | |
interpclass | The class to use if the musicclass is not currently set on the channel structure or in the mclass argument. |
0 | success | |
non-zero | failure |
Definition at line 4544 of file channel.c.
Referenced by alsa_indicate(), app_exec(), cb_events(), conf_run(), feature_exec_app(), gtalk_indicate(), handle_setmusic(), iax2_indicate(), local_indicate(), mgcp_indicate(), misdn_indication(), moh0_exec(), moh1_exec(), moh3_exec(), oh323_indicate(), oss_indicate(), phone_indicate(), queue_exec(), retrydial_exec(), say_periodic_announcement(), say_position(), sip_indicate(), skinny_indicate(), and zt_indicate().
04545 { 04546 if (ast_moh_start_ptr) 04547 return ast_moh_start_ptr(chan, mclass, interpclass); 04548 04549 if (option_verbose > 2) { 04550 ast_verbose(VERBOSE_PREFIX_3 "Music class %s requested but no musiconhold loaded.\n", 04551 mclass ? mclass : (interpclass ? interpclass : "default")); 04552 } 04553 04554 return 0; 04555 }
void ast_moh_stop | ( | struct ast_channel * | chan | ) |
Turn off music on hold on a given channel.
Turn off music on hold on a given channel
Definition at line 4558 of file channel.c.
Referenced by alsa_indicate(), app_exec(), cb_events(), conf_run(), feature_exec_app(), gtalk_indicate(), handle_setmusic(), iax2_indicate(), local_indicate(), mgcp_indicate(), misdn_indication(), misdn_transfer_bc(), moh0_exec(), moh1_exec(), moh4_exec(), oh323_indicate(), oss_indicate(), phone_indicate(), queue_exec(), retrydial_exec(), say_periodic_announcement(), say_position(), sip_indicate(), skinny_indicate(), try_calling(), and zt_indicate().
04559 { 04560 if (ast_moh_stop_ptr) 04561 ast_moh_stop_ptr(chan); 04562 }
char* ast_print_group | ( | char * | buf, | |
int | buflen, | |||
ast_group_t | group | |||
) |
Print call group and pickup group ---.
print call- and pickup groups into buffer
Definition at line 4576 of file channel.c.
Referenced by _sip_show_peer(), func_channel_read(), misdn_cfg_get_config_string(), print_group(), read_config(), and serialize_showchan().
04577 { 04578 unsigned int i; 04579 int first=1; 04580 char num[3]; 04581 04582 buf[0] = '\0'; 04583 04584 if (!group) /* Return empty string if no group */ 04585 return buf; 04586 04587 for (i = 0; i <= 63; i++) { /* Max group is 63 */ 04588 if (group & ((ast_group_t) 1 << i)) { 04589 if (!first) { 04590 strncat(buf, ", ", buflen); 04591 } else { 04592 first=0; 04593 } 04594 snprintf(num, sizeof(num), "%u", i); 04595 strncat(buf, num, buflen); 04596 } 04597 } 04598 return buf; 04599 }
int ast_prod | ( | struct ast_channel * | chan | ) |
Send empty audio to prime a channel driver.
Definition at line 2740 of file channel.c.
Referenced by ast_activate_generator().
02741 { 02742 struct ast_frame a = { AST_FRAME_VOICE }; 02743 char nothing[128]; 02744 02745 /* Send an empty audio frame to get things moving */ 02746 if (chan->_state != AST_STATE_UP) { 02747 if (option_debug) 02748 ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name); 02749 a.subclass = chan->rawwriteformat; 02750 a.data = nothing + AST_FRIENDLY_OFFSET; 02751 a.src = "ast_prod"; 02752 if (ast_write(chan, &a)) 02753 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name); 02754 } 02755 return 0; 02756 }
int ast_queue_control | ( | struct ast_channel * | chan, | |
enum ast_control_frame_type | control | |||
) |
Queue a control frame.
Queue a control frame with payload.
Definition at line 963 of file channel.c.
Referenced by __oh323_update_info(), __zt_exception(), ast_pickup_call(), attempt_transfer(), auto_congest(), cb_events(), gtalk_is_answered(), gtalk_ringing_ack(), handle_hd_hf(), handle_offhook_message(), handle_request(), handle_request_bye(), handle_request_info(), handle_request_refer(), handle_response(), handle_response_invite(), handle_response_refer(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_call(), nbs_call(), phone_call(), pickup_do(), process_sdp(), receive_digit(), send_cause2ast(), setup_rtp_connection(), skinny_call(), skinny_unhold(), socket_process(), ss_thread(), update_state(), zt_handle_event(), and zt_hangup().
00964 { 00965 struct ast_frame f = { AST_FRAME_CONTROL, }; 00966 00967 f.subclass = control; 00968 00969 return ast_queue_frame(chan, &f); 00970 }
int ast_queue_control_data | ( | struct ast_channel * | chan, | |
enum ast_control_frame_type | control, | |||
const void * | data, | |||
size_t | datalen | |||
) |
Queue a control frame with payload.
chan | channel to queue frame onto | |
control | type of control frame | |
data | pointer to payload data to be included in frame | |
datalen | number of bytes of payload data |
Definition at line 973 of file channel.c.
Referenced by process_sdp(), skinny_hold(), socket_process(), zt_handle_event(), and zt_hangup().
00975 { 00976 struct ast_frame f = { AST_FRAME_CONTROL, }; 00977 00978 f.subclass = control; 00979 f.data = (void *) data; 00980 f.datalen = datalen; 00981 00982 return ast_queue_frame(chan, &f); 00983 }
int ast_queue_frame | ( | struct ast_channel * | chan, | |
struct ast_frame * | fin | |||
) |
Queue an outgoing media frame.
Queue an outgoing frame.
Definition at line 895 of file channel.c.
Referenced by __oh323_rtp_create(), __oh323_update_info(), agent_new(), alsa_call(), ast_channel_masquerade(), ast_channel_setwhentohangup(), ast_do_masquerade(), ast_dsp_process(), ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), ast_softhangup_nolock(), cb_events(), console_answer(), console_answer_deprecated(), console_dial(), console_dial_deprecated(), console_flash(), console_flash_deprecated(), console_sendtext(), console_sendtext_deprecated(), dictate_exec(), do_immediate_setup(), gtalk_handle_dtmf(), handle_keypad_button_message(), handle_request_info(), handle_request_invite(), handle_response_invite(), iax2_queue_frame(), local_queue_frame(), mgcp_queue_frame(), oh323_simulate_dtmf_end(), oss_call(), process_sdp(), receive_digit(), receive_message(), rpt_call(), wakeup_sub(), and zap_queue_frame().
00896 { 00897 struct ast_frame *f; 00898 struct ast_frame *cur; 00899 int blah = 1; 00900 int qlen = 0; 00901 00902 /* Build us a copy and free the original one */ 00903 if (!(f = ast_frdup(fin))) { 00904 ast_log(LOG_WARNING, "Unable to duplicate frame\n"); 00905 return -1; 00906 } 00907 ast_channel_lock(chan); 00908 00909 /* See if the last frame on the queue is a hangup, if so don't queue anything */ 00910 if ((cur = AST_LIST_LAST(&chan->readq)) && (cur->frametype == AST_FRAME_CONTROL) && (cur->subclass == AST_CONTROL_HANGUP)) { 00911 ast_frfree(f); 00912 ast_channel_unlock(chan); 00913 return 0; 00914 } 00915 00916 /* Count how many frames exist on the queue */ 00917 AST_LIST_TRAVERSE(&chan->readq, cur, frame_list) { 00918 qlen++; 00919 } 00920 00921 /* Allow up to 96 voice frames outstanding, and up to 128 total frames */ 00922 if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen > 128)) { 00923 if (fin->frametype != AST_FRAME_VOICE) { 00924 ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name); 00925 CRASH; 00926 } else { 00927 if (option_debug) 00928 ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name); 00929 ast_frfree(f); 00930 ast_channel_unlock(chan); 00931 return 0; 00932 } 00933 } 00934 AST_LIST_INSERT_TAIL(&chan->readq, f, frame_list); 00935 if (chan->alertpipe[1] > -1) { 00936 if (write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) 00937 ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n", 00938 chan->name, f->frametype, f->subclass, qlen, strerror(errno)); 00939 #ifdef HAVE_ZAPTEL 00940 } else if (chan->timingfd > -1) { 00941 ioctl(chan->timingfd, ZT_TIMERPING, &blah); 00942 #endif 00943 } else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) { 00944 pthread_kill(chan->blocker, SIGURG); 00945 } 00946 ast_channel_unlock(chan); 00947 return 0; 00948 }
int ast_queue_hangup | ( | struct ast_channel * | chan | ) |
Queue a hangup frame for channel.
Queue a hangup frame.
Definition at line 951 of file channel.c.
Referenced by __oh323_update_info(), __sip_autodestruct(), cleanup_connection(), console_hangup(), console_hangup_deprecated(), gtalk_hangup_farend(), handle_onhook_message(), handle_request_bye(), handle_request_cancel(), handle_response(), handle_response_invite(), handle_soft_key_event_message(), hangup_chan(), hangup_connection(), iax2_destroy(), iax2_predestroy(), mgcp_queue_hangup(), misdn_answer(), retrans_pkt(), and zt_handle_event().
00952 { 00953 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP }; 00954 /* Yeah, let's not change a lock-critical value without locking */ 00955 if (!ast_channel_trylock(chan)) { 00956 chan->_softhangup |= AST_SOFTHANGUP_DEV; 00957 ast_channel_unlock(chan); 00958 } 00959 return ast_queue_frame(chan, &f); 00960 }
struct ast_frame* ast_read | ( | struct ast_channel * | chan | ) | [read] |
Reads a frame.
chan | channel to read a frame from Read a frame. |
Definition at line 2547 of file channel.c.
Referenced by __adsi_transmit_messages(), __ast_play_and_record(), __ast_request_and_dial(), adsi_careful_send(), agent_ack_sleep(), agent_read(), app_exec(), ast_feature_request_and_dial(), ast_generic_bridge(), ast_masq_park_call(), ast_recvtext(), ast_safe_sleep_conditional(), ast_tonepair(), ast_udptl_bridge(), ast_waitfordigit_full(), async_wait(), autoservice_run(), background_detect_exec(), bridge_native_loop(), bridge_p2p_loop(), builtin_atxfer(), channel_spy(), check_goto_on_transfer(), conf_exec(), conf_flush(), conf_run(), dictate_exec(), disa_exec(), do_parking_thread(), do_waiting(), echo_exec(), features_read(), find_cache(), handle_invite_replaces(), handle_recordfile(), iax2_bridge(), iax_park_thread(), ices_exec(), isAnsweringMachine(), measurenoise(), misdn_bridge(), monitor_dial(), mp3_exec(), NBScat_exec(), receive_dtmf_digits(), record_exec(), recordthread(), rpt(), rpt_exec(), run_agi(), send_tone_burst(), send_waveform_to_channel(), sendurl_exec(), sms_exec(), speech_background(), ss_thread(), wait_for_answer(), wait_for_hangup(), wait_for_winner(), waitforring_exec(), waitstream_core(), and zt_bridge().
02548 { 02549 return __ast_read(chan, 0); 02550 }
static void ast_read_generator_actions | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 2147 of file channel.c.
References ast_deactivate_generator(), AST_FRAME_CNG, ast_internal_timing_enabled(), ast_log(), ast_settimeout(), ast_frame::datalen, ast_frame::frametype, ast_generator::generate, ast_channel::generator, generator_force(), ast_channel::generatordata, LOG_DEBUG, option_debug, ast_frame::samples, ast_channel::timingfd, and ast_channel::timingfunc.
Referenced by __ast_read().
02148 { 02149 if (chan->generatordata && !ast_internal_timing_enabled(chan)) { 02150 void *tmp = chan->generatordata; 02151 int res; 02152 02153 if (chan->timingfunc) { 02154 if (option_debug > 1) 02155 ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n"); 02156 ast_settimeout(chan, 0, NULL, NULL); 02157 } 02158 02159 chan->generatordata = NULL; /* reset, to let writes go through */ 02160 res = chan->generator->generate(chan, tmp, f->datalen, f->samples); 02161 chan->generatordata = tmp; 02162 if (res) { 02163 if (option_debug > 1) 02164 ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); 02165 ast_deactivate_generator(chan); 02166 } 02167 02168 } else if (f->frametype == AST_FRAME_CNG) { 02169 if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) { 02170 if (option_debug > 1) 02171 ast_log(LOG_DEBUG, "Generator got CNG, switching to timed mode\n"); 02172 ast_settimeout(chan, 160, generator_force, chan); 02173 } 02174 } 02175 }
struct ast_frame* ast_read_noaudio | ( | struct ast_channel * | chan | ) | [read] |
Reads a frame, returning AST_FRAME_NULL frame if audio. Read a frame.
chan | channel to read a frame from |
Definition at line 2552 of file channel.c.
Referenced by conf_run().
02553 { 02554 return __ast_read(chan, 1); 02555 }
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 3258 of file channel.c.
Referenced by __adsi_transmit_messages(), ast_adsi_begin_download(), ast_adsi_get_cpeinfo(), ast_adsi_load_session(), ast_app_getdata(), dialout(), do_directory(), forward_message(), privacy_exec(), vm_authenticate(), vm_newuser(), and vm_options().
03259 { 03260 return ast_readstring_full(c, s, len, timeout, ftimeout, enders, -1, -1); 03261 }
int ast_readstring_full | ( | struct ast_channel * | c, | |
char * | s, | |||
int | len, | |||
int | timeout, | |||
int | ftimeout, | |||
char * | enders, | |||
int | audiofd, | |||
int | ctrlfd | |||
) |
Definition at line 3263 of file channel.c.
Referenced by ast_app_getdata_full(), and ast_readstring().
03264 { 03265 int pos = 0; /* index in the buffer where we accumulate digits */ 03266 int to = ftimeout; 03267 03268 /* Stop if we're a zombie or need a soft hangup */ 03269 if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c)) 03270 return -1; 03271 if (!len) 03272 return -1; 03273 for (;;) { 03274 int d; 03275 if (c->stream) { 03276 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd); 03277 ast_stopstream(c); 03278 usleep(1000); 03279 if (!d) 03280 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 03281 } else { 03282 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 03283 } 03284 if (d < 0) 03285 return -1; 03286 if (d == 0) { 03287 s[pos]='\0'; 03288 return 1; 03289 } 03290 if (d == 1) { 03291 s[pos]='\0'; 03292 return 2; 03293 } 03294 if (!strchr(enders, d)) 03295 s[pos++] = d; 03296 if (strchr(enders, d) || (pos >= len)) { 03297 s[pos]='\0'; 03298 return 0; 03299 } 03300 to = timeout; 03301 } 03302 /* Never reached */ 03303 return 0; 03304 }
int ast_recvchar | ( | struct ast_channel * | chan, | |
int | timeout | |||
) |
Receives a text character from a channel.
chan | channel to act upon | |
timeout | timeout in milliseconds (0 for infinite wait) Read a char of text from a channel Returns 0 on success, -1 on failure |
Definition at line 2620 of file channel.c.
Referenced by handle_recvchar().
02621 { 02622 int c; 02623 char *buf = ast_recvtext(chan, timeout); 02624 if (buf == NULL) 02625 return -1; /* error or timeout */ 02626 c = *(unsigned char *)buf; 02627 free(buf); 02628 return c; 02629 }
char* ast_recvtext | ( | struct ast_channel * | chan, | |
int | timeout | |||
) |
Receives a text string from a channel Read a string of text from a channel.
chan | channel to act upon | |
timeout | timeout in milliseconds (0 for infinite wait) |
Definition at line 2631 of file channel.c.
Referenced by ast_recvchar(), and handle_recvtext().
02632 { 02633 int res, done = 0; 02634 char *buf = NULL; 02635 02636 while (!done) { 02637 struct ast_frame *f; 02638 if (ast_check_hangup(chan)) 02639 break; 02640 res = ast_waitfor(chan, timeout); 02641 if (res <= 0) /* timeout or error */ 02642 break; 02643 timeout = res; /* update timeout */ 02644 f = ast_read(chan); 02645 if (f == NULL) 02646 break; /* no frame */ 02647 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) 02648 done = 1; /* force a break */ 02649 else if (f->frametype == AST_FRAME_TEXT) { /* what we want */ 02650 buf = ast_strndup((char *) f->data, f->datalen); /* dup and break */ 02651 done = 1; 02652 } 02653 ast_frfree(f); 02654 } 02655 return buf; 02656 }
struct ast_channel* ast_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | status | |||
) | [read] |
Requests a channel.
type | type of channel to request | |
format | requested channel format (codec) | |
data | data to pass to the channel requester | |
status | status Request a channel of a given type, with data as optional information used by the low level module |
Definition at line 3166 of file channel.c.
Referenced by __ast_request_and_dial(), agent_request(), ast_feature_request_and_dial(), attempt_reconnect(), begin_dial(), build_conf(), chanavail_exec(), conf_run(), connect_link(), features_alloc(), findmeexec(), ring_entry(), rpt(), rpt_call(), rpt_exec(), rpt_tele_thread(), and wait_for_answer().
03167 { 03168 struct chanlist *chan; 03169 struct ast_channel *c; 03170 int capabilities; 03171 int fmt; 03172 int res; 03173 int foo; 03174 int videoformat = format & AST_FORMAT_VIDEO_MASK; 03175 03176 if (!cause) 03177 cause = &foo; 03178 *cause = AST_CAUSE_NOTDEFINED; 03179 03180 if (AST_LIST_LOCK(&channels)) { 03181 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 03182 return NULL; 03183 } 03184 03185 AST_LIST_TRAVERSE(&backends, chan, list) { 03186 if (strcasecmp(type, chan->tech->type)) 03187 continue; 03188 03189 capabilities = chan->tech->capabilities; 03190 fmt = format & AST_FORMAT_AUDIO_MASK; 03191 res = ast_translator_best_choice(&fmt, &capabilities); 03192 if (res < 0) { 03193 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->tech->capabilities, format); 03194 *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 03195 AST_LIST_UNLOCK(&channels); 03196 return NULL; 03197 } 03198 AST_LIST_UNLOCK(&channels); 03199 if (!chan->tech->requester) 03200 return NULL; 03201 03202 if (!(c = chan->tech->requester(type, capabilities | videoformat, data, cause))) 03203 return NULL; 03204 03205 /* no need to generate a Newchannel event here; it is done in the channel_alloc call */ 03206 return c; 03207 } 03208 03209 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type); 03210 *cause = AST_CAUSE_NOSUCHDRIVER; 03211 AST_LIST_UNLOCK(&channels); 03212 03213 return NULL; 03214 }
struct ast_channel* ast_request_and_dial | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int | timeout, | |||
int * | reason, | |||
const char * | cidnum, | |||
const char * | cidname | |||
) | [read] |
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.
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 | |
reason | why unsuccessful (if unsuceessful) | |
cidnum | Caller-ID Number | |
cidname | Caller-ID Name |
Definition at line 3161 of file channel.c.
Referenced by ast_pbx_outgoing_exten().
03162 { 03163 return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL); 03164 }
int ast_safe_sleep | ( | struct ast_channel * | chan, | |
int | ms | |||
) |
Wait, look for hangups.
Wait for a specied amount of time, looking for hangups.
Definition at line 1170 of file channel.c.
Referenced by __login_exec(), alarmreceiver_exec(), ast_adsi_transmit_message_full(), ast_dtmf_stream(), ast_senddigit(), builtin_parkcall(), dictate_exec(), flash_exec(), function_ilink(), mgcp_ss(), milliwatt_exec(), moh0_exec(), moh1_exec(), park_call_exec(), pbx_builtin_answer(), pbx_builtin_wait(), play_tone_pair(), playtone(), privacy_exec(), receive_ademco_contact_id(), rpt_call(), rpt_exec(), rpt_tele_thread(), send_morse(), send_tone_telemetry(), skinny_ss(), ss_thread(), testclient_exec(), testserver_exec(), try_calling(), wait_for_hangup(), wait_interval(), and zapateller_exec().
01171 { 01172 return ast_safe_sleep_conditional(chan, ms, NULL, NULL); 01173 }
int ast_safe_sleep_conditional | ( | struct ast_channel * | chan, | |
int | ms, | |||
int(*)(void *) | cond, | |||
void * | data | |||
) |
Wait, look for hangups and condition arg.
Wait for a specied amount of time, looking for hangups and a condition argument.
Definition at line 1149 of file channel.c.
Referenced by __login_exec(), and ast_safe_sleep().
01150 { 01151 struct ast_frame *f; 01152 01153 while (ms > 0) { 01154 if (cond && ((*cond)(data) == 0)) 01155 return 0; 01156 ms = ast_waitfor(chan, ms); 01157 if (ms < 0) 01158 return -1; 01159 if (ms > 0) { 01160 f = ast_read(chan); 01161 if (!f) 01162 return -1; 01163 ast_frfree(f); 01164 } 01165 } 01166 return 0; 01167 }
char* ast_safe_string_alloc | ( | const char * | fmt, | |
... | ||||
) |
printf the string into a correctly sized mallocd buffer, and return the buffer
return a mallocd string with the result of sprintf of the fmt and following args
Definition at line 428 of file channel.c.
Referenced by features_new(), and zt_new().
00429 { 00430 char *b2, buf[1]; 00431 int len; 00432 va_list args; 00433 00434 va_start(args, fmt); 00435 len = vsnprintf(buf, 1, fmt, args); 00436 va_end(args); 00437 00438 if (!(b2 = ast_malloc(len + 1))) 00439 return NULL; 00440 00441 va_start(args, fmt); 00442 vsnprintf(b2, len + 1, fmt, args); 00443 va_end(args); 00444 00445 return b2; 00446 }
int ast_say_character_str | ( | struct ast_channel * | chan, | |
const char * | str, | |||
const char * | ints, | |||
const char * | lang | |||
) |
Definition at line 4971 of file channel.c.
Referenced by common_exec(), pbx_builtin_saycharacters(), play_mailbox_owner(), rpt_exec(), rpt_tele_thread(), and saycharstr().
04973 { 04974 return ast_say_character_str_full(chan, str, ints, lang, -1, -1); 04975 }
int ast_say_digit_str | ( | struct ast_channel * | chan, | |
const char * | str, | |||
const char * | ints, | |||
const char * | lang | |||
) |
Definition at line 4965 of file channel.c.
Referenced by invent_message(), mgcp_ss(), pbx_builtin_saydigits(), play_message_callerid(), and ss_thread().
04967 { 04968 return ast_say_digit_str_full(chan, str, ints, lang, -1, -1); 04969 }
int ast_say_digits | ( | struct ast_channel * | chan, | |
int | num, | |||
const char * | ints, | |||
const char * | lang | |||
) |
Definition at line 4959 of file channel.c.
Referenced by ast_park_call(), common_exec(), conf_exec(), parkandannounce_exec(), and rpt_tele_thread().
04961 { 04962 return ast_say_digits_full(chan, num, ints, lang, -1, -1); 04963 }
int ast_say_digits_full | ( | struct ast_channel * | chan, | |
int | num, | |||
const char * | ints, | |||
const char * | lang, | |||
int | audiofd, | |||
int | ctrlfd | |||
) |
Definition at line 4983 of file channel.c.
Referenced by __say_init(), ast_say_digits(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_number_full_cz(), ast_say_number_full_da(), ast_say_number_full_de(), ast_say_number_full_en(), ast_say_number_full_en_GB(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_ge(), ast_say_number_full_he(), ast_say_number_full_it(), ast_say_number_full_nl(), ast_say_number_full_no(), ast_say_number_full_pt(), ast_say_number_full_ru(), ast_say_number_full_se(), and ast_say_number_full_tw().
04985 { 04986 char buf[256]; 04987 04988 snprintf(buf, sizeof(buf), "%d", num); 04989 return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd); 04990 }
int ast_say_enumeration | ( | struct ast_channel * | chan, | |
int | num, | |||
const char * | ints, | |||
const char * | language, | |||
const char * | options | |||
) |
Definition at line 4953 of file channel.c.
Referenced by ast_say_date_da(), ast_say_date_de(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), and ast_say_date_with_format_pl().
04955 { 04956 return ast_say_enumeration_full(chan, num, ints, language, options, -1, -1); 04957 }
int ast_say_number | ( | struct ast_channel * | chan, | |
int | num, | |||
const char * | ints, | |||
const char * | language, | |||
const char * | options | |||
) |
Definition at line 4947 of file channel.c.
Referenced by ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_ge(), ast_say_date_gr(), ast_say_date_nl(), ast_say_date_pt(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_it(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_ge(), ast_say_datetime_from_now_pt(), ast_say_datetime_pt(), ast_say_datetime_tw(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_ge(), ast_say_time_gr(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_tw(), bridge_playfile(), conf_exec(), conf_run(), count_exec(), dictate_exec(), get_folder(), gr_say_number_female(), pbx_builtin_saynumber(), play_message(), play_message_duration(), rpt_tele_thread(), say_and_wait(), say_position(), saynum(), try_calling(), vm_intro_gr(), vm_intro_pt(), and vm_intro_pt_BR().
04949 { 04950 return ast_say_number_full(chan, num, ints, language, options, -1, -1); 04951 }
int ast_say_phonetic_str | ( | struct ast_channel * | chan, | |
const char * | str, | |||
const char * | ints, | |||
const char * | lang | |||
) |
Definition at line 4977 of file channel.c.
Referenced by pbx_builtin_sayphonetic().
04979 { 04980 return ast_say_phonetic_str_full(chan, str, ints, lang, -1, -1); 04981 }
int ast_senddigit | ( | struct ast_channel * | chan, | |
char | digit | |||
) |
Send a DTMF digit to a channel Send a DTMF digit to a channel.
chan | channel to act upon | |
digit | the DTMF digit to send, encoded in ASCII |
Definition at line 2730 of file channel.c.
Referenced by ast_dtmf_stream(), do_dtmf_phone(), manager_play_dtmf(), and rpt_call().
02731 { 02732 if (chan->tech->send_digit_begin) { 02733 ast_senddigit_begin(chan, digit); 02734 ast_safe_sleep(chan, AST_DEFAULT_EMULATE_DTMF_DURATION); 02735 } 02736 02737 return ast_senddigit_end(chan, digit, AST_DEFAULT_EMULATE_DTMF_DURATION); 02738 }
int ast_senddigit_begin | ( | struct ast_channel * | chan, | |
char | digit | |||
) |
Definition at line 2671 of file channel.c.
Referenced by agent_digit_begin(), ast_senddigit(), ast_write(), and features_digit_begin().
02672 { 02673 /* Device does not support DTMF tones, lets fake 02674 * it by doing our own generation. */ 02675 static const char* dtmf_tones[] = { 02676 "941+1336", /* 0 */ 02677 "697+1209", /* 1 */ 02678 "697+1336", /* 2 */ 02679 "697+1477", /* 3 */ 02680 "770+1209", /* 4 */ 02681 "770+1336", /* 5 */ 02682 "770+1477", /* 6 */ 02683 "852+1209", /* 7 */ 02684 "852+1336", /* 8 */ 02685 "852+1477", /* 9 */ 02686 "697+1633", /* A */ 02687 "770+1633", /* B */ 02688 "852+1633", /* C */ 02689 "941+1633", /* D */ 02690 "941+1209", /* * */ 02691 "941+1477" /* # */ 02692 }; 02693 02694 if (!chan->tech->send_digit_begin) 02695 return 0; 02696 02697 if (!chan->tech->send_digit_begin(chan, digit)) 02698 return 0; 02699 02700 if (digit >= '0' && digit <='9') 02701 ast_playtones_start(chan, 0, dtmf_tones[digit-'0'], 0); 02702 else if (digit >= 'A' && digit <= 'D') 02703 ast_playtones_start(chan, 0, dtmf_tones[digit-'A'+10], 0); 02704 else if (digit == '*') 02705 ast_playtones_start(chan, 0, dtmf_tones[14], 0); 02706 else if (digit == '#') 02707 ast_playtones_start(chan, 0, dtmf_tones[15], 0); 02708 else { 02709 /* not handled */ 02710 if (option_debug) 02711 ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, chan->name); 02712 } 02713 02714 return 0; 02715 }
int ast_senddigit_end | ( | struct ast_channel * | chan, | |
char | digit, | |||
unsigned int | duration | |||
) |
Definition at line 2717 of file channel.c.
Referenced by agent_digit_end(), ast_senddigit(), ast_write(), and features_digit_end().
02718 { 02719 int res = -1; 02720 02721 if (chan->tech->send_digit_end) 02722 res = chan->tech->send_digit_end(chan, digit, duration); 02723 02724 if (res && chan->generator) 02725 ast_playtones_stop(chan); 02726 02727 return 0; 02728 }
int ast_sendtext | ( | struct ast_channel * | chan, | |
const char * | text | |||
) |
Sends text to a channel Write text to a display on a channel.
chan | channel to act upon | |
text | string of text to send on the channel |
Definition at line 2658 of file channel.c.
Referenced by agent_sendtext(), handle_sendtext(), and sendtext_exec().
02659 { 02660 int res = 0; 02661 /* Stop if we're a zombie or need a soft hangup */ 02662 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) 02663 return -1; 02664 CHECK_BLOCKING(chan); 02665 if (chan->tech->send_text) 02666 res = chan->tech->send_text(chan, text); 02667 ast_clear_flag(chan, AST_FLAG_BLOCKING); 02668 return res; 02669 }
void ast_set_callerid | ( | struct ast_channel * | chan, | |
const char * | callerid, | |||
const char * | calleridname, | |||
const char * | ani | |||
) |
Definition at line 3813 of file channel.c.
Referenced by __ast_request_and_dial(), agent_call(), ast_feature_request_and_dial(), callerid_write(), disa_exec(), findmeexec(), handle_setcallerid(), lookupcidname_exec(), mgcp_ss(), privacy_exec(), read_config(), rpt_exec(), setcallerid_exec(), skinny_newcall(), ss_thread(), wait_for_answer(), and zt_read().
03814 { 03815 if (callerid) { 03816 if (chan->cid.cid_num) 03817 free(chan->cid.cid_num); 03818 chan->cid.cid_num = ast_strdup(callerid); 03819 } 03820 if (calleridname) { 03821 if (chan->cid.cid_name) 03822 free(chan->cid.cid_name); 03823 chan->cid.cid_name = ast_strdup(calleridname); 03824 } 03825 if (ani) { 03826 if (chan->cid.cid_ani) 03827 free(chan->cid.cid_ani); 03828 chan->cid.cid_ani = ast_strdup(ani); 03829 } 03830 if (chan->cdr) 03831 ast_cdr_setcid(chan->cdr, chan); 03832 manager_event(EVENT_FLAG_CALL, "Newcallerid", 03833 "Channel: %s\r\n" 03834 "CallerID: %s\r\n" 03835 "CallerIDName: %s\r\n" 03836 "Uniqueid: %s\r\n" 03837 "CID-CallingPres: %d (%s)\r\n", 03838 chan->name, 03839 S_OR(chan->cid.cid_num, "<Unknown>"), 03840 S_OR(chan->cid.cid_name, "<Unknown>"), 03841 chan->uniqueid, 03842 chan->cid.cid_pres, 03843 ast_describe_caller_presentation(chan->cid.cid_pres) 03844 ); 03845 }
int ast_set_read_format | ( | struct ast_channel * | chan, | |
int | format | |||
) |
Sets read format on channel chan Set read format for channel to whichever component of "format" is best.
chan | channel to change | |
format | format to change to |
Definition at line 3025 of file channel.c.
Referenced by __ast_play_and_record(), __login_exec(), __oh323_update_info(), agent_call(), alarmreceiver_exec(), ast_adsi_transmit_message_full(), ast_channel_make_compatible(), ast_do_masquerade(), attempt_reconnect(), background_detect_exec(), build_conf(), conf_run(), connect_link(), dictate_exec(), disa_exec(), do_waiting(), eagi_exec(), echo_exec(), gtalk_rtp_read(), handle_recordfile(), ices_exec(), isAnsweringMachine(), measurenoise(), mgcp_rtp_read(), milliwatt_exec(), oh323_rtp_read(), process_sdp(), record_exec(), rpt(), rpt_exec(), setup_rtp_connection(), sip_rtp_read(), skinny_rtp_read(), sms_exec(), socket_process(), speech_background(), and update_features().
03026 { 03027 return set_format(chan, fmt, &chan->rawreadformat, &chan->readformat, 03028 &chan->readtrans, 0); 03029 }
void ast_set_variables | ( | struct ast_channel * | chan, | |
struct ast_variable * | vars | |||
) |
adds a list of channel variables to a channel
chan | the channel | |
vars | a linked list of variables |
Definition at line 4601 of file channel.c.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
04602 { 04603 struct ast_variable *cur; 04604 04605 for (cur = vars; cur; cur = cur->next) 04606 pbx_builtin_setvar_helper(chan, cur->name, cur->value); 04607 }
int ast_set_write_format | ( | struct ast_channel * | chan, | |
int | format | |||
) |
Sets write format on channel chan Set write format for channel to whichever compoent of "format" is best.
chan | channel to change | |
format | new format for writing |
Definition at line 3031 of file channel.c.
Referenced by __login_exec(), __oh323_update_info(), agent_call(), alarmreceiver_exec(), ast_adsi_transmit_message_full(), ast_channel_make_compatible(), ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_channel_whisper_stop(), ast_do_masquerade(), ast_openstream_full(), ast_stopstream(), ast_write(), attempt_reconnect(), build_conf(), channel_spy(), chanspy_exec(), conf_run(), connect_link(), disa_exec(), echo_exec(), extenspy_exec(), gtalk_rtp_read(), linear_alloc(), linear_release(), mgcp_rtp_read(), milliwatt_exec(), moh_alloc(), moh_files_release(), moh_release(), mp3_exec(), NBScat_exec(), oh323_rtp_read(), playtones_alloc(), playtones_release(), process_sdp(), rpt(), rpt_exec(), send_waveform_to_channel(), setup_rtp_connection(), sip_rtp_read(), skinny_rtp_read(), sms_exec(), socket_process(), tonepair_alloc(), tonepair_release(), and update_features().
03032 { 03033 return set_format(chan, fmt, &chan->rawwriteformat, &chan->writeformat, 03034 &chan->writetrans, 1); 03035 }
int ast_setstate | ( | struct ast_channel * | chan, | |
enum ast_channel_state | state | |||
) |
Change the state of a channel.
Definition at line 3847 of file channel.c.
Referenced by __ast_read(), __oh323_update_info(), __zt_exception(), agent_call(), alsa_answer(), ast_answer(), cb_events(), check_availability(), gtalk_call(), gtalk_newcall(), handle_invite_replaces(), handle_offhook_message(), handle_request_invite(), handle_response_invite(), handle_soft_key_event_message(), handle_stimulus_message(), iax2_call(), mgcp_answer(), mgcp_call(), mgcp_ss(), misdn_call(), misdn_indication(), nbs_call(), nbs_hangup(), oh323_answer(), oss_answer(), pbx_builtin_busy(), pbx_builtin_congestion(), phone_answer(), phone_call(), phone_exception(), phone_hangup(), phone_write(), release_chan(), sip_answer(), skinny_answer(), skinny_call(), skinny_newcall(), ss_thread(), update_state(), zt_answer(), zt_call(), zt_handle_event(), zt_indicate(), and zt_read().
03848 { 03849 int oldstate = chan->_state; 03850 03851 if (oldstate == state) 03852 return 0; 03853 03854 chan->_state = state; 03855 ast_device_state_changed_literal(chan->name); 03856 /* setstate used to conditionally report Newchannel; this is no more */ 03857 manager_event(EVENT_FLAG_CALL, 03858 "Newstate", 03859 "Channel: %s\r\n" 03860 "State: %s\r\n" 03861 "CallerID: %s\r\n" 03862 "CallerIDName: %s\r\n" 03863 "Uniqueid: %s\r\n", 03864 chan->name, ast_state2str(chan->_state), 03865 S_OR(chan->cid.cid_num, "<unknown>"), 03866 S_OR(chan->cid.cid_name, "<unknown>"), 03867 chan->uniqueid); 03868 03869 return 0; 03870 }
int ast_settimeout | ( | struct ast_channel * | c, | |
int | samples, | |||
int(*)(void *data) | func, | |||
void * | data | |||
) |
Definition at line 2062 of file channel.c.
Referenced by ast_activate_generator(), ast_closestream(), ast_deactivate_generator(), ast_read_generator_actions(), and ast_readaudio_callback().
02063 { 02064 int res = -1; 02065 #ifdef HAVE_ZAPTEL 02066 if (c->timingfd > -1) { 02067 if (!func) { 02068 samples = 0; 02069 data = 0; 02070 } 02071 if (option_debug) 02072 ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples); 02073 res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples); 02074 c->timingfunc = func; 02075 c->timingdata = data; 02076 } 02077 #endif 02078 return res; 02079 }
int ast_shutting_down | ( | void | ) |
Returns non-zero if Asterisk is being shut down.
Returns non-zero if Asterisk is being shut down
Definition at line 480 of file channel.c.
00481 { 00482 return shutting_down; 00483 }
int ast_softhangup | ( | struct ast_channel * | chan, | |
int | cause | |||
) |
Softly hangup a channel, lock.
Softly hangup up a channel.
Definition at line 1558 of file channel.c.
Referenced by __ast_module_user_hangup_all(), __ast_pbx_run(), __login_exec(), __unload_module(), action_hangup(), agent_hangup(), agent_logoff(), ast_begin_shutdown(), connect_link(), function_ilink(), handle_hangup(), handle_link_data(), handle_softhangup(), manager_park(), read_agent_config(), rpt(), rpt_call(), rpt_do_restart(), sla_handle_hold_event(), softhangup_exec(), start_spying(), startmon(), unload_module(), and zt_handle_event().
01559 { 01560 int res; 01561 ast_channel_lock(chan); 01562 res = ast_softhangup_nolock(chan, cause); 01563 ast_channel_unlock(chan); 01564 return res; 01565 }
int ast_softhangup_nolock | ( | struct ast_channel * | chan, | |
int | cause | |||
) |
Softly hangup a channel, don't lock.
Softly hangup up a channel (no channel lock).
Definition at line 1544 of file channel.c.
Referenced by ast_async_goto(), ast_softhangup(), attempt_transfer(), do_monitor(), oh323_indicate(), sip_indicate(), and skinny_indicate().
01545 { 01546 if (option_debug) 01547 ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name); 01548 /* Inform channel driver that we need to be hung up, if it cares */ 01549 chan->_softhangup |= cause; 01550 ast_queue_frame(chan, &ast_null_frame); 01551 /* Interrupt any poll call or such */ 01552 if (ast_test_flag(chan, AST_FLAG_BLOCKING)) 01553 pthread_kill(chan->blocker, SIGURG); 01554 return 0; 01555 }
char* ast_state2str | ( | enum | ast_channel_state | ) |
Gives the string form of a given channel state.
Gives the string form of a given channel state
ast_channel_state | state to get the name of Give a name to a state Returns the text form of the binary state given |
Definition at line 619 of file channel.c.
Referenced by action_status(), agent_hangup(), ast_channel_alloc(), ast_setstate(), attempt_transfer(), func_channel_read(), handle_chanlist(), handle_chanlist_deprecated(), handle_invite_replaces(), handle_showchan(), handle_showchan_deprecated(), local_attended_transfer(), mgcp_new(), serialize_showchan(), and sip_hangup().
00620 { 00621 char *buf; 00622 00623 switch(state) { 00624 case AST_STATE_DOWN: 00625 return "Down"; 00626 case AST_STATE_RESERVED: 00627 return "Rsrvd"; 00628 case AST_STATE_OFFHOOK: 00629 return "OffHook"; 00630 case AST_STATE_DIALING: 00631 return "Dialing"; 00632 case AST_STATE_RING: 00633 return "Ring"; 00634 case AST_STATE_RINGING: 00635 return "Ringing"; 00636 case AST_STATE_UP: 00637 return "Up"; 00638 case AST_STATE_BUSY: 00639 return "Busy"; 00640 case AST_STATE_DIALING_OFFHOOK: 00641 return "Dialing Offhook"; 00642 case AST_STATE_PRERING: 00643 return "Pre-ring"; 00644 default: 00645 if (!(buf = ast_threadstorage_get(&state2str_threadbuf, STATE2STR_BUFSIZE))) 00646 return "Unknown"; 00647 snprintf(buf, STATE2STR_BUFSIZE, "Unknown (%d)", state); 00648 return buf; 00649 } 00650 }
int ast_str2cause | ( | const char * | name | ) |
Convert a symbolic hangup cause to number.
Convert the string form of a cause code to a number
name | string form of the cause Returns the cause code |
Definition at line 607 of file channel.c.
Referenced by pbx_builtin_hangup().
00608 { 00609 int x; 00610 00611 for (x = 0; x < sizeof(causes) / sizeof(causes[0]); x++) 00612 if (strncasecmp(causes[x].name, name, strlen(causes[x].name)) == 0) 00613 return causes[x].cause; 00614 00615 return -1; 00616 }
AST_THREADSTORAGE | ( | state2str_threadbuf | , | |
state2str_threadbuf_init | ||||
) |
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 4476 of file channel.c.
Referenced by zapateller_exec().
04477 { 04478 int res; 04479 04480 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol))) 04481 return res; 04482 04483 /* Give us some wiggle room */ 04484 while (chan->generatordata && ast_waitfor(chan, 100) >= 0) { 04485 struct ast_frame *f = ast_read(chan); 04486 if (f) 04487 ast_frfree(f); 04488 else 04489 return -1; 04490 } 04491 return 0; 04492 }
int ast_tonepair_start | ( | struct ast_channel * | chan, | |
int | freq1, | |||
int | freq2, | |||
int | duration, | |||
int | vol | |||
) |
Start a tone going
Definition at line 4458 of file channel.c.
Referenced by ast_tonepair(), play_dialtone(), play_tone_pair(), rpt_tele_thread(), and sendnoise().
04459 { 04460 struct tonepair_def d = { 0, }; 04461 04462 d.freq1 = freq1; 04463 d.freq2 = freq2; 04464 d.duration = duration; 04465 d.vol = (vol < 1) ? 8192 : vol; /* force invalid to 8192 */ 04466 if (ast_activate_generator(chan, &tonepair, &d)) 04467 return -1; 04468 return 0; 04469 }
void ast_tonepair_stop | ( | struct ast_channel * | chan | ) |
Stop a tone from playing
Definition at line 4471 of file channel.c.
Referenced by sendnoise().
04472 { 04473 ast_deactivate_generator(chan); 04474 }
int ast_transfer | ( | struct ast_channel * | chan, | |
char * | dest | |||
) |
Transfer a call to dest, if the channel supports transfer.
Transfer a channel (if supported). Returns -1 on error, 0 if not supported and 1 if supported and requested.
Called by:
Definition at line 3240 of file channel.c.
Referenced by transfer_exec().
03241 { 03242 int res = -1; 03243 03244 /* Stop if we're a zombie or need a soft hangup */ 03245 ast_channel_lock(chan); 03246 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) { 03247 if (chan->tech->transfer) { 03248 res = chan->tech->transfer(chan, dest); 03249 if (!res) 03250 res = 1; 03251 } else 03252 res = 0; 03253 } 03254 ast_channel_unlock(chan); 03255 return res; 03256 }
char* ast_transfercapability2str | ( | int | transfercapability | ) | const |
Gives the string form of a given transfer capability.
Gives the string form of a given transfer capability
transfercapability | transfercapabilty to get the name of Give a name to a transfercapbility See above Returns the text form of the binary transfer capbility |
Definition at line 653 of file channel.c.
Referenced by cb_events(), misdn_call(), oh323_call(), zt_call(), and zt_new().
00654 { 00655 switch(transfercapability) { 00656 case AST_TRANS_CAP_SPEECH: 00657 return "SPEECH"; 00658 case AST_TRANS_CAP_DIGITAL: 00659 return "DIGITAL"; 00660 case AST_TRANS_CAP_RESTRICTED_DIGITAL: 00661 return "RESTRICTED_DIGITAL"; 00662 case AST_TRANS_CAP_3_1K_AUDIO: 00663 return "3K1AUDIO"; 00664 case AST_TRANS_CAP_DIGITAL_W_TONES: 00665 return "DIGITAL_W_TONES"; 00666 case AST_TRANS_CAP_VIDEO: 00667 return "VIDEO"; 00668 default: 00669 return "UNKNOWN"; 00670 } 00671 }
void ast_uninstall_music_functions | ( | void | ) |
Definition at line 4536 of file channel.c.
04537 { 04538 ast_moh_start_ptr = NULL; 04539 ast_moh_stop_ptr = NULL; 04540 ast_moh_cleanup_ptr = NULL; 04541 }
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). |
Definition at line 2046 of file channel.c.
Referenced by __adsi_transmit_messages(), __ast_play_and_record(), __ast_request_and_dial(), adsi_careful_send(), agent_ack_sleep(), ast_dtmf_stream(), ast_recvtext(), ast_safe_sleep_conditional(), ast_tonepair(), async_wait(), background_detect_exec(), channel_spy(), conf_exec(), conf_flush(), dictate_exec(), disa_exec(), do_waiting(), echo_exec(), handle_recordfile(), ices_exec(), isAnsweringMachine(), measurenoise(), mp3_exec(), NBScat_exec(), receive_dtmf_digits(), record_exec(), recordthread(), send_tone_burst(), send_waveform_to_channel(), sendurl_exec(), sms_exec(), speech_background(), ss_thread(), wait_for_hangup(), waitforring_exec(), and waitstream_core().
02047 { 02048 int oldms = ms; /* -1 if no timeout */ 02049 02050 ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms); 02051 if ((ms < 0) && (oldms < 0)) 02052 ms = 0; 02053 return ms; 02054 }
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.
chan | an array of pointers to channels | |
n | number of channels that are to be waited upon | |
ms | time "ms" is modified in-place, if applicable |
Definition at line 2041 of file channel.c.
Referenced by ast_feature_request_and_dial(), ast_generic_bridge(), ast_udptl_bridge(), autoservice_run(), bridge_native_loop(), bridge_p2p_loop(), iax2_bridge(), misdn_bridge(), monitor_dial(), rpt(), rpt_exec(), wait_for_answer(), wait_for_winner(), and zt_bridge().
02042 { 02043 return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms); 02044 }
int ast_waitfor_n_fd | ( | int * | fds, | |
int | n, | |||
int * | ms, | |||
int * | exception | |||
) |
Wait for x amount of time on a file descriptor to have input.
Waits for input on an fd This version works on fd's only. Be careful with it.
Definition at line 1886 of file channel.c.
Referenced by dundi_lookup_internal(), and dundi_precache_internal().
01887 { 01888 int winner = -1; 01889 ast_waitfor_nandfds(NULL, 0, fds, n, exception, &winner, ms); 01890 return winner; 01891 }
struct ast_channel* ast_waitfor_nandfds | ( | struct ast_channel ** | c, | |
int | n, | |||
int * | fds, | |||
int | nfds, | |||
int * | exception, | |||
int * | outfd, | |||
int * | ms | |||
) | [read] |
Wait for x amount of time on a file descriptor to have input.
Waits for activity on a group of channels.
Definition at line 1894 of file channel.c.
Referenced by app_exec(), ast_waitfor(), ast_waitfor_n(), ast_waitfor_n_fd(), ast_waitfordigit_full(), conf_run(), find_cache(), run_agi(), and waitstream_core().
01896 { 01897 struct timeval start = { 0 , 0 }; 01898 struct pollfd *pfds; 01899 int res; 01900 long rms; 01901 int x, y, max; 01902 int sz; 01903 time_t now = 0; 01904 long whentohangup = 0, diff; 01905 struct ast_channel *winner = NULL; 01906 struct fdmap { 01907 int chan; 01908 int fdno; 01909 } *fdmap; 01910 01911 sz = n * AST_MAX_FDS + nfds; 01912 pfds = alloca(sizeof(*pfds) * sz); 01913 fdmap = alloca(sizeof(*fdmap) * sz); 01914 01915 if (outfd) 01916 *outfd = -99999; 01917 if (exception) 01918 *exception = 0; 01919 01920 /* Perform any pending masquerades */ 01921 for (x=0; x < n; x++) { 01922 ast_channel_lock(c[x]); 01923 if (c[x]->masq) { 01924 if (ast_do_masquerade(c[x])) { 01925 ast_log(LOG_WARNING, "Masquerade failed\n"); 01926 *ms = -1; 01927 ast_channel_unlock(c[x]); 01928 return NULL; 01929 } 01930 } 01931 if (c[x]->whentohangup) { 01932 if (!whentohangup) 01933 time(&now); 01934 diff = c[x]->whentohangup - now; 01935 if (diff < 1) { 01936 /* Should already be hungup */ 01937 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 01938 ast_channel_unlock(c[x]); 01939 return c[x]; 01940 } 01941 if (!whentohangup || (diff < whentohangup)) 01942 whentohangup = diff; 01943 } 01944 ast_channel_unlock(c[x]); 01945 } 01946 /* Wait full interval */ 01947 rms = *ms; 01948 if (whentohangup) { 01949 rms = whentohangup * 1000; /* timeout in milliseconds */ 01950 if (*ms >= 0 && *ms < rms) /* original *ms still smaller */ 01951 rms = *ms; 01952 } 01953 /* 01954 * Build the pollfd array, putting the channels' fds first, 01955 * followed by individual fds. Order is important because 01956 * individual fd's must have priority over channel fds. 01957 */ 01958 max = 0; 01959 for (x=0; x<n; x++) { 01960 for (y=0; y<AST_MAX_FDS; y++) { 01961 fdmap[max].fdno = y; /* fd y is linked to this pfds */ 01962 fdmap[max].chan = x; /* channel x is linked to this pfds */ 01963 max += ast_add_fd(&pfds[max], c[x]->fds[y]); 01964 } 01965 CHECK_BLOCKING(c[x]); 01966 } 01967 /* Add the individual fds */ 01968 for (x=0; x<nfds; x++) { 01969 fdmap[max].chan = -1; 01970 max += ast_add_fd(&pfds[max], fds[x]); 01971 } 01972 01973 if (*ms > 0) 01974 start = ast_tvnow(); 01975 01976 if (sizeof(int) == 4) { /* XXX fix timeout > 600000 on linux x86-32 */ 01977 do { 01978 int kbrms = rms; 01979 if (kbrms > 600000) 01980 kbrms = 600000; 01981 res = poll(pfds, max, kbrms); 01982 if (!res) 01983 rms -= kbrms; 01984 } while (!res && (rms > 0)); 01985 } else { 01986 res = poll(pfds, max, rms); 01987 } 01988 for (x=0; x<n; x++) 01989 ast_clear_flag(c[x], AST_FLAG_BLOCKING); 01990 if (res < 0) { /* Simulate a timeout if we were interrupted */ 01991 if (errno != EINTR) 01992 *ms = -1; 01993 return NULL; 01994 } 01995 if (whentohangup) { /* if we have a timeout, check who expired */ 01996 time(&now); 01997 for (x=0; x<n; x++) { 01998 if (c[x]->whentohangup && now >= c[x]->whentohangup) { 01999 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 02000 if (winner == NULL) 02001 winner = c[x]; 02002 } 02003 } 02004 } 02005 if (res == 0) { /* no fd ready, reset timeout and done */ 02006 *ms = 0; /* XXX use 0 since we may not have an exact timeout. */ 02007 return winner; 02008 } 02009 /* 02010 * Then check if any channel or fd has a pending event. 02011 * Remember to check channels first and fds last, as they 02012 * must have priority on setting 'winner' 02013 */ 02014 for (x = 0; x < max; x++) { 02015 res = pfds[x].revents; 02016 if (res == 0) 02017 continue; 02018 if (fdmap[x].chan >= 0) { /* this is a channel */ 02019 winner = c[fdmap[x].chan]; /* override previous winners */ 02020 if (res & POLLPRI) 02021 ast_set_flag(winner, AST_FLAG_EXCEPTION); 02022 else 02023 ast_clear_flag(winner, AST_FLAG_EXCEPTION); 02024 winner->fdno = fdmap[x].fdno; 02025 } else { /* this is an fd */ 02026 if (outfd) 02027 *outfd = pfds[x].fd; 02028 if (exception) 02029 *exception = (res & POLLPRI) ? -1 : 0; 02030 winner = NULL; 02031 } 02032 } 02033 if (*ms > 0) { 02034 *ms -= ast_tvdiff_ms(ast_tvnow(), start); 02035 if (*ms < 0) 02036 *ms = 0; 02037 } 02038 return winner; 02039 }
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 |
Definition at line 2057 of file channel.c.
Referenced by _while_exec(), advanced_options(), ast_adsi_get_cpeid(), ast_adsi_get_cpeinfo(), ast_adsi_print(), ast_adsi_read_encoded_dtmf(), ast_adsi_transmit_message_full(), ast_app_dtget(), ast_control_streamfile(), ast_record_review(), builtin_atxfer(), collect_digits(), common_exec(), cpeid_exec(), dialout(), directory_exec(), forward_message(), get_folder(), ivr_dispatch(), mgcp_ss(), my_getsigstr(), pbx_builtin_waitexten(), play_mailbox_owner(), play_record_review(), read_exec(), read_newoption(), retrydial_exec(), sendnoise(), ss_thread(), testclient_exec(), testserver_exec(), vm_execmain(), vm_forwardoptions(), vm_instructions(), vm_options(), vm_tempgreeting(), wait_a_bit(), and wait_our_turn().
02058 { 02059 return ast_waitfordigit_full(c, ms, -1, -1); 02060 }
int ast_waitfordigit_full | ( | struct ast_channel * | c, | |
int | ms, | |||
int | audiofd, | |||
int | ctrlfd | |||
) |
Wait for a digit Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading.
c | channel to wait for a digit on | |
ms | how many milliseconds to wait | |
audiofd | audio file descriptor to write to if audio frames are received | |
ctrlfd | control file descriptor to monitor for reading |
Definition at line 2081 of file channel.c.
Referenced by ast_readstring_full(), ast_waitfordigit(), handle_getoption(), and handle_waitfordigit().
02082 { 02083 int begin_digit = 0; 02084 02085 /* Stop if we're a zombie or need a soft hangup */ 02086 if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c)) 02087 return -1; 02088 /* Wait for a digit, no more than ms milliseconds total. */ 02089 while (ms) { 02090 struct ast_channel *rchan; 02091 int outfd; 02092 02093 errno = 0; 02094 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 02095 if (!rchan && outfd < 0 && ms) { 02096 if (errno == 0 || errno == EINTR) 02097 continue; 02098 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 02099 return -1; 02100 } else if (outfd > -1) { 02101 /* The FD we were watching has something waiting */ 02102 return 1; 02103 } else if (rchan) { 02104 int res; 02105 struct ast_frame *f = ast_read(c); 02106 if (!f) 02107 return -1; 02108 02109 switch(f->frametype) { 02110 case AST_FRAME_DTMF_BEGIN: 02111 begin_digit = f->subclass; 02112 break; 02113 case AST_FRAME_DTMF_END: 02114 if (begin_digit != f->subclass) 02115 break; 02116 res = f->subclass; 02117 ast_frfree(f); 02118 return res; 02119 case AST_FRAME_CONTROL: 02120 switch(f->subclass) { 02121 case AST_CONTROL_HANGUP: 02122 ast_frfree(f); 02123 return -1; 02124 case AST_CONTROL_RINGING: 02125 case AST_CONTROL_ANSWER: 02126 /* Unimportant */ 02127 break; 02128 default: 02129 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass); 02130 break; 02131 } 02132 break; 02133 case AST_FRAME_VOICE: 02134 /* Write audio if appropriate */ 02135 if (audiofd > -1) 02136 write(audiofd, f->data, f->datalen); 02137 default: 02138 /* Ignore */ 02139 break; 02140 } 02141 ast_frfree(f); 02142 } 02143 } 02144 return 0; /* Time is up */ 02145 }
struct ast_channel* ast_walk_channel_by_exten_locked | ( | const struct ast_channel * | chan, | |
const char * | exten, | |||
const char * | context | |||
) | [read] |
Get next channel by exten (and optionally context) and lock it.
Definition at line 1142 of file channel.c.
Referenced by next_channel().
01144 { 01145 return channel_find_locked(chan, NULL, 0, context, exten); 01146 }
struct ast_channel* ast_walk_channel_by_name_prefix_locked | ( | const struct ast_channel * | chan, | |
const char * | name, | |||
const int | namelen | |||
) | [read] |
Get next channel by name prefix and lock it.
Get channel by name prefix (locks channel).
Definition at line 1129 of file channel.c.
Referenced by next_channel().
01131 { 01132 return channel_find_locked(chan, name, namelen, NULL, NULL); 01133 }
int ast_write | ( | struct ast_channel * | chan, | |
struct ast_frame * | frame | |||
) |
Write a frame to a channel This function writes the given frame to the indicated channel.
chan | destination channel of the frame | |
frame | frame that will be written |
Definition at line 2769 of file channel.c.
Referenced by adsi_careful_send(), agent_write(), ast_generic_bridge(), ast_prod(), ast_readaudio_callback(), ast_readvideo_callback(), ast_udptl_bridge(), ast_write_video(), bridge_native_loop(), bridge_p2p_loop(), conf_queue_dtmf(), conf_run(), dictate_exec(), echo_exec(), features_write(), function_ilink(), gen_generate(), handle_link_data(), iax2_bridge(), jb_get_and_deliver(), linear_generator(), milliwatt_generate(), misdn_bridge(), moh_files_generator(), moh_generate(), mp3_exec(), NBScat_exec(), playtones_generator(), rpt(), rpt_exec(), send_link_dtmf(), send_tone_burst(), send_waveform_to_channel(), silence_generator_generate(), sms_generate(), spy_generate(), tonepair_generator(), wait_for_answer(), and zt_bridge().
02770 { 02771 int res = -1; 02772 struct ast_frame *f = NULL; 02773 02774 /* Stop if we're a zombie or need a soft hangup */ 02775 ast_channel_lock(chan); 02776 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) 02777 goto done; 02778 02779 /* Handle any pending masquerades */ 02780 if (chan->masq && ast_do_masquerade(chan)) { 02781 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 02782 goto done; 02783 } 02784 if (chan->masqr) { 02785 res = 0; /* XXX explain, why 0 ? */ 02786 goto done; 02787 } 02788 if (chan->generatordata) { 02789 if (ast_test_flag(chan, AST_FLAG_WRITE_INT)) 02790 ast_deactivate_generator(chan); 02791 else { 02792 if (fr->frametype == AST_FRAME_DTMF_END) { 02793 /* There is a generator running while we're in the middle of a digit. 02794 * It's probably inband DTMF, so go ahead and pass it so it can 02795 * stop the generator */ 02796 ast_clear_flag(chan, AST_FLAG_BLOCKING); 02797 ast_channel_unlock(chan); 02798 res = ast_senddigit_end(chan, fr->subclass, fr->len); 02799 ast_channel_lock(chan); 02800 CHECK_BLOCKING(chan); 02801 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_UNHOLD) { 02802 /* This is a side case where Echo is basically being called and the person put themselves on hold and took themselves off hold */ 02803 res = (chan->tech->indicate == NULL) ? 0 : 02804 chan->tech->indicate(chan, fr->subclass, fr->data, fr->datalen); 02805 } 02806 res = 0; /* XXX explain, why 0 ? */ 02807 goto done; 02808 } 02809 } 02810 /* High bit prints debugging */ 02811 if (chan->fout & DEBUGCHAN_FLAG) 02812 ast_frame_dump(chan->name, fr, ">>"); 02813 CHECK_BLOCKING(chan); 02814 switch(fr->frametype) { 02815 case AST_FRAME_CONTROL: 02816 res = (chan->tech->indicate == NULL) ? 0 : 02817 chan->tech->indicate(chan, fr->subclass, fr->data, fr->datalen); 02818 break; 02819 case AST_FRAME_DTMF_BEGIN: 02820 ast_clear_flag(chan, AST_FLAG_BLOCKING); 02821 ast_channel_unlock(chan); 02822 res = ast_senddigit_begin(chan, fr->subclass); 02823 ast_channel_lock(chan); 02824 CHECK_BLOCKING(chan); 02825 break; 02826 case AST_FRAME_DTMF_END: 02827 ast_clear_flag(chan, AST_FLAG_BLOCKING); 02828 ast_channel_unlock(chan); 02829 res = ast_senddigit_end(chan, fr->subclass, fr->len); 02830 ast_channel_lock(chan); 02831 CHECK_BLOCKING(chan); 02832 break; 02833 case AST_FRAME_TEXT: 02834 res = (chan->tech->send_text == NULL) ? 0 : 02835 chan->tech->send_text(chan, (char *) fr->data); 02836 break; 02837 case AST_FRAME_HTML: 02838 res = (chan->tech->send_html == NULL) ? 0 : 02839 chan->tech->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen); 02840 break; 02841 case AST_FRAME_VIDEO: 02842 /* XXX Handle translation of video codecs one day XXX */ 02843 res = (chan->tech->write_video == NULL) ? 0 : 02844 chan->tech->write_video(chan, fr); 02845 break; 02846 case AST_FRAME_MODEM: 02847 res = (chan->tech->write == NULL) ? 0 : 02848 chan->tech->write(chan, fr); 02849 break; 02850 case AST_FRAME_VOICE: 02851 if (chan->tech->write == NULL) 02852 break; /*! \todo XXX should return 0 maybe ? */ 02853 02854 /* If someone is whispering on this channel then we must ensure that we are always getting signed linear frames */ 02855 if (ast_test_flag(chan, AST_FLAG_WHISPER)) { 02856 if (fr->subclass == AST_FORMAT_SLINEAR) 02857 f = fr; 02858 else { 02859 ast_mutex_lock(&chan->whisper->lock); 02860 if (chan->writeformat != AST_FORMAT_SLINEAR) { 02861 /* Rebuild the translation path and set our write format back to signed linear */ 02862 chan->whisper->original_format = chan->writeformat; 02863 ast_set_write_format(chan, AST_FORMAT_SLINEAR); 02864 if (chan->whisper->path) 02865 ast_translator_free_path(chan->whisper->path); 02866 chan->whisper->path = ast_translator_build_path(AST_FORMAT_SLINEAR, chan->whisper->original_format); 02867 } 02868 /* Translate frame using the above translation path */ 02869 f = (chan->whisper->path) ? ast_translate(chan->whisper->path, fr, 0) : fr; 02870 ast_mutex_unlock(&chan->whisper->lock); 02871 } 02872 } else { 02873 /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */ 02874 if (fr->subclass == chan->rawwriteformat) 02875 f = fr; 02876 else 02877 f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr; 02878 } 02879 02880 /* If we have no frame of audio, then we have to bail out */ 02881 if (f == NULL) { 02882 res = 0; 02883 break; 02884 } 02885 02886 /* If spies are on the channel then queue the frame out to them */ 02887 if (chan->spies) 02888 queue_frame_to_spies(chan, f, SPY_WRITE); 02889 02890 /* If Monitor is running on this channel, then we have to write frames out there too */ 02891 if (chan->monitor && chan->monitor->write_stream) { 02892 /* XXX must explain this code */ 02893 #ifndef MONITOR_CONSTANT_DELAY 02894 int jump = chan->insmpl - chan->outsmpl - 4 * f->samples; 02895 if (jump >= 0) { 02896 jump = chan->insmpl - chan->outsmpl; 02897 if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1) 02898 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 02899 chan->outsmpl += jump + f->samples; 02900 } else 02901 chan->outsmpl += f->samples; 02902 #else 02903 int jump = chan->insmpl - chan->outsmpl; 02904 if (jump - MONITOR_DELAY >= 0) { 02905 if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1) 02906 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 02907 chan->outsmpl += jump; 02908 } else 02909 chan->outsmpl += f->samples; 02910 #endif 02911 if (chan->monitor->state == AST_MONITOR_RUNNING) { 02912 if (ast_writestream(chan->monitor->write_stream, f) < 0) 02913 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n"); 02914 } 02915 } 02916 02917 /* Finally the good part! Write this out to the channel */ 02918 if (ast_test_flag(chan, AST_FLAG_WHISPER)) { 02919 /* frame is assumed to be in SLINEAR, since that is 02920 required for whisper mode */ 02921 ast_frame_adjust_volume(f, -2); 02922 if (ast_slinfactory_available(&chan->whisper->sf) >= f->samples) { 02923 short buf[f->samples]; 02924 struct ast_frame whisper = { 02925 .frametype = AST_FRAME_VOICE, 02926 .subclass = AST_FORMAT_SLINEAR, 02927 .data = buf, 02928 .datalen = sizeof(buf), 02929 .samples = f->samples, 02930 }; 02931 02932 ast_mutex_lock(&chan->whisper->lock); 02933 if (ast_slinfactory_read(&chan->whisper->sf, buf, f->samples)) 02934 ast_frame_slinear_sum(f, &whisper); 02935 ast_mutex_unlock(&chan->whisper->lock); 02936 } 02937 /* and now put it through the regular translator */ 02938 f = (chan->writetrans) ? ast_translate(chan->writetrans, f, 0) : f; 02939 } 02940 if (f) 02941 res = chan->tech->write(chan, f); 02942 else 02943 res = 0; 02944 break; 02945 case AST_FRAME_NULL: 02946 case AST_FRAME_IAX: 02947 /* Ignore these */ 02948 res = 0; 02949 break; 02950 default: 02951 /* At this point, fr is the incoming frame and f is NULL. Channels do 02952 * not expect to get NULL as a frame pointer and will segfault. Hence, 02953 * we output the original frame passed in. */ 02954 res = chan->tech->write(chan, fr); 02955 break; 02956 } 02957 02958 if (f && f != fr) 02959 ast_frfree(f); 02960 ast_clear_flag(chan, AST_FLAG_BLOCKING); 02961 /* Consider a write failure to force a soft hangup */ 02962 if (res < 0) 02963 chan->_softhangup |= AST_SOFTHANGUP_DEV; 02964 else { 02965 chan->fout = FRAMECOUNT_INC(chan->fout); 02966 } 02967 done: 02968 ast_channel_unlock(chan); 02969 return res; 02970 }
int ast_write_video | ( | struct ast_channel * | chan, | |
struct ast_frame * | frame | |||
) |
Write video frame to a channel This function writes the given frame to the indicated channel.
chan | destination channel of the frame | |
frame | frame that will be written |
Definition at line 2758 of file channel.c.
02759 { 02760 int res; 02761 if (!chan->tech->write_video) 02762 return 0; 02763 res = ast_write(chan, fr); 02764 if (!res) 02765 res = 1; 02766 return res; 02767 }
static void bridge_playfile | ( | struct ast_channel * | chan, | |
struct ast_channel * | peer, | |||
const char * | sound, | |||
int | remain | |||
) | [static] |
Definition at line 3882 of file channel.c.
References ast_autoservice_start(), ast_autoservice_stop(), AST_DIGIT_ANY, ast_say_number(), and ast_stream_and_wait().
Referenced by ast_channel_bridge().
03883 { 03884 int min = 0, sec = 0, check; 03885 03886 check = ast_autoservice_start(peer); 03887 if (check) 03888 return; 03889 03890 if (remain > 0) { 03891 if (remain / 60 > 1) { 03892 min = remain / 60; 03893 sec = remain % 60; 03894 } else { 03895 sec = remain; 03896 } 03897 } 03898 03899 if (!strcmp(sound,"timeleft")) { /* Queue support */ 03900 ast_stream_and_wait(chan, "vm-youhave", chan->language, ""); 03901 if (min) { 03902 ast_say_number(chan, min, AST_DIGIT_ANY, chan->language, NULL); 03903 ast_stream_and_wait(chan, "queue-minutes", chan->language, ""); 03904 } 03905 if (sec) { 03906 ast_say_number(chan, sec, AST_DIGIT_ANY, chan->language, NULL); 03907 ast_stream_and_wait(chan, "queue-seconds", chan->language, ""); 03908 } 03909 } else { 03910 ast_stream_and_wait(chan, sound, chan->language, ""); 03911 } 03912 03913 ast_autoservice_stop(peer); 03914 }
static struct ast_channel* channel_find_locked | ( | const struct ast_channel * | prev, | |
const char * | name, | |||
const int | namelen, | |||
const char * | context, | |||
const char * | exten | |||
) | [static, read] |
Helper function to find channels.
It supports these modes:
prev != NULL : get channel next in list after prev name != NULL : get channel with matching name name != NULL && namelen != 0 : get channel whose name starts with prefix exten != NULL : get channel whose exten or macroexten matches context != NULL && exten != NULL : get channel whose context or macrocontext
It returns with the channel's lock held. If getting the individual lock fails, unlock and retry quickly up to 10 times, then give up.
XXX also note that accessing fields (e.g. c->name in ast_log()) can only be done with the lock held or someone could delete the object while we work on it. This causes some ugliness in the code. Note that removing the first ast_log() may be harmful, as it would shorten the retry period and possibly cause failures. We should definitely go for a better scheme that is deadlock-free.
Definition at line 1028 of file channel.c.
References ast_channel_trylock, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_channel::context, ast_channel::exten, LOG_DEBUG, ast_channel::macrocontext, ast_channel::macroexten, and option_debug.
Referenced by ast_channel_walk_locked(), ast_get_channel_by_exten_locked(), ast_get_channel_by_name_locked(), ast_get_channel_by_name_prefix_locked(), ast_walk_channel_by_exten_locked(), and ast_walk_channel_by_name_prefix_locked().
01031 { 01032 const char *msg = prev ? "deadlock" : "initial deadlock"; 01033 int retries; 01034 struct ast_channel *c; 01035 const struct ast_channel *_prev = prev; 01036 01037 for (retries = 0; retries < 10; retries++) { 01038 int done; 01039 AST_LIST_LOCK(&channels); 01040 AST_LIST_TRAVERSE(&channels, c, chan_list) { 01041 prev = _prev; 01042 if (prev) { /* look for next item */ 01043 if (c != prev) /* not this one */ 01044 continue; 01045 /* found, prepare to return c->next */ 01046 if ((c = AST_LIST_NEXT(c, chan_list)) == NULL) break; 01047 /* If prev was the last item on the channel list, then we just 01048 * want to return NULL, instead of trying to deref NULL in the 01049 * next section. 01050 */ 01051 prev = NULL; 01052 /* We want prev to be NULL in case we end up doing more searching through 01053 * the channel list to find the channel (ie: name searching). If we didn't 01054 * set this to NULL the logic would just blow up 01055 * XXX Need a better explanation for this ... 01056 */ 01057 } 01058 if (name) { /* want match by name */ 01059 if ((!namelen && strcasecmp(c->name, name)) || 01060 (namelen && strncasecmp(c->name, name, namelen))) 01061 continue; /* name match failed */ 01062 } else if (exten) { 01063 if (context && strcasecmp(c->context, context) && 01064 strcasecmp(c->macrocontext, context)) 01065 continue; /* context match failed */ 01066 if (strcasecmp(c->exten, exten) && 01067 strcasecmp(c->macroexten, exten)) 01068 continue; /* exten match failed */ 01069 } 01070 /* if we get here, c points to the desired record */ 01071 break; 01072 } 01073 /* exit if chan not found or mutex acquired successfully */ 01074 /* this is slightly unsafe, as we _should_ hold the lock to access c->name */ 01075 done = c == NULL || ast_channel_trylock(c) == 0; 01076 if (!done) { 01077 if (option_debug) 01078 ast_log(LOG_DEBUG, "Avoiding %s for channel '%p'\n", msg, c); 01079 if (retries == 9) { 01080 /* We are about to fail due to a deadlock, so report this 01081 * while we still have the list lock. 01082 */ 01083 if (option_debug) 01084 ast_log(LOG_DEBUG, "Failure, could not lock '%p' after %d retries!\n", c, retries); 01085 /* As we have deadlocked, we will skip this channel and 01086 * see if there is another match. 01087 * NOTE: No point doing this for a full-name match, 01088 * as there can be no more matches. 01089 */ 01090 if (!(name && !namelen)) { 01091 prev = c; 01092 retries = -1; 01093 } 01094 } 01095 } 01096 AST_LIST_UNLOCK(&channels); 01097 if (done) 01098 return c; 01099 /* If we reach this point we basically tried to lock a channel and failed. Instead of 01100 * starting from the beginning of the list we can restore our saved pointer to the previous 01101 * channel and start from there. 01102 */ 01103 prev = _prev; 01104 usleep(1); /* give other threads a chance before retrying */ 01105 } 01106 01107 return NULL; 01108 }
const char* channelreloadreason2txt | ( | enum channelreloadreason | reason | ) |
Convert enum channelreloadreason to text string for manager event.
\ brief Convert channel reloadreason (ENUM) to text string for manager event
Definition at line 4811 of file channel.c.
Referenced by reload_config().
04812 { 04813 switch (reason) { 04814 case CHANNEL_MODULE_LOAD: 04815 return "LOAD (Channel module load)"; 04816 04817 case CHANNEL_MODULE_RELOAD: 04818 return "RELOAD (Channel module reload)"; 04819 04820 case CHANNEL_CLI_RELOAD: 04821 return "CLIRELOAD (Channel module reload by CLI command)"; 04822 04823 default: 04824 return "MANAGERRELOAD (Channel module reload by manager)"; 04825 } 04826 };
static void clone_variables | ( | struct ast_channel * | original, | |
struct ast_channel * | clone | |||
) | [static] |
Clone channel variables from 'clone' channel into 'original' channel.
All variables except those related to app_groupcount are cloned. Variables are actually _removed_ from 'clone' channel, presumably because it will subsequently be destroyed.
Definition at line 3506 of file channel.c.
References AST_LIST_APPEND_LIST, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_var_assign(), ast_var_t::name, ast_var_t::value, and ast_channel::varshead.
Referenced by ast_do_masquerade().
03507 { 03508 struct ast_var_t *current, *newvar; 03509 /* Append variables from clone channel into original channel */ 03510 /* XXX Is this always correct? We have to in order to keep MACROS working XXX */ 03511 if (AST_LIST_FIRST(&clone->varshead)) 03512 AST_LIST_APPEND_LIST(&original->varshead, &clone->varshead, entries); 03513 AST_LIST_HEAD_INIT_NOLOCK(&clone->varshead); 03514 03515 /* then, dup the varshead list into the clone */ 03516 03517 AST_LIST_TRAVERSE(&original->varshead, current, entries) { 03518 newvar = ast_var_assign(current->name, current->value); 03519 if (newvar) 03520 AST_LIST_INSERT_TAIL(&clone->varshead, newvar, entries); 03521 } 03522 }
static char* complete_channeltypes | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 353 of file channel.c.
References AST_LIST_TRAVERSE, strdup, chanlist::tech, and ast_channel_tech::type.
00354 { 00355 struct chanlist *cl; 00356 int which = 0; 00357 int wordlen; 00358 char *ret = NULL; 00359 00360 if (pos != 3) 00361 return NULL; 00362 00363 wordlen = strlen(word); 00364 00365 AST_LIST_TRAVERSE(&backends, cl, list) { 00366 if (!strncasecmp(word, cl->tech->type, wordlen) && ++which > state) { 00367 ret = strdup(cl->tech->type); 00368 break; 00369 } 00370 } 00371 00372 return ret; 00373 }
static char* complete_channeltypes_deprecated | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 331 of file channel.c.
References AST_LIST_TRAVERSE, strdup, chanlist::tech, and ast_channel_tech::type.
00332 { 00333 struct chanlist *cl; 00334 int which = 0; 00335 int wordlen; 00336 char *ret = NULL; 00337 00338 if (pos != 2) 00339 return NULL; 00340 00341 wordlen = strlen(word); 00342 00343 AST_LIST_TRAVERSE(&backends, cl, list) { 00344 if (!strncasecmp(word, cl->tech->type, wordlen) && ++which > state) { 00345 ret = strdup(cl->tech->type); 00346 break; 00347 } 00348 } 00349 00350 return ret; 00351 }
static void copy_data_from_queue | ( | struct ast_channel_spy_queue * | queue, | |
short * | buf, | |||
unsigned int | samples | |||
) | [static] |
Definition at line 4609 of file channel.c.
References ast_codec_get_len(), ast_frfree(), AST_LIST_FIRST, AST_LIST_REMOVE_HEAD, ast_log(), ast_frame::data, ast_frame::datalen, f, ast_channel_spy_queue::format, LOG_ERROR, ast_frame::offset, ast_channel_spy_queue::samples, and ast_frame::samples.
Referenced by ast_channel_spy_read_frame().
04610 { 04611 struct ast_frame *f; 04612 int tocopy; 04613 int bytestocopy; 04614 04615 while (samples) { 04616 if (!(f = AST_LIST_FIRST(&queue->list))) { 04617 ast_log(LOG_ERROR, "Ran out of frames before buffer filled!\n"); 04618 break; 04619 } 04620 04621 tocopy = (f->samples > samples) ? samples : f->samples; 04622 bytestocopy = ast_codec_get_len(queue->format, tocopy); 04623 memcpy(buf, f->data, bytestocopy); 04624 samples -= tocopy; 04625 buf += tocopy; 04626 f->samples -= tocopy; 04627 f->data += bytestocopy; 04628 f->datalen -= bytestocopy; 04629 f->offset += bytestocopy; 04630 queue->samples -= tocopy; 04631 04632 if (!f->samples) 04633 ast_frfree(AST_LIST_REMOVE_HEAD(&queue->list, frame_list)); 04634 } 04635 }
static void detach_spies | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 1527 of file channel.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_channel::spies, spy_cleanup(), and spy_detach().
Referenced by ast_hangup().
01528 { 01529 struct ast_channel_spy *spy = NULL; 01530 01531 if (!chan->spies) 01532 return; 01533 01534 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->spies->list, spy, list) { 01535 AST_LIST_REMOVE_CURRENT(&chan->spies->list, list); 01536 spy_detach(spy, chan); 01537 } 01538 AST_LIST_TRAVERSE_SAFE_END 01539 01540 spy_cleanup(chan); 01541 }
static void free_cid | ( | struct ast_callerid * | cid | ) | [static] |
Definition at line 1175 of file channel.c.
References ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_rdnis, and free.
Referenced by ast_channel_free().
01176 { 01177 if (cid->cid_dnid) 01178 free(cid->cid_dnid); 01179 if (cid->cid_num) 01180 free(cid->cid_num); 01181 if (cid->cid_name) 01182 free(cid->cid_name); 01183 if (cid->cid_ani) 01184 free(cid->cid_ani); 01185 if (cid->cid_rdnis) 01186 free(cid->cid_rdnis); 01187 }
static void free_translation | ( | struct ast_channel * | clone | ) | [static] |
Definition at line 1690 of file channel.c.
References ast_translator_free_path(), ast_channel::nativeformats, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readtrans, and ast_channel::writetrans.
Referenced by ast_do_masquerade(), and ast_hangup().
01691 { 01692 if (clone->writetrans) 01693 ast_translator_free_path(clone->writetrans); 01694 if (clone->readtrans) 01695 ast_translator_free_path(clone->readtrans); 01696 clone->writetrans = NULL; 01697 clone->readtrans = NULL; 01698 clone->rawwriteformat = clone->nativeformats; 01699 clone->rawreadformat = clone->nativeformats; 01700 }
static int generator_force | ( | void * | data | ) | [static] |
Definition at line 1838 of file channel.c.
References ast_deactivate_generator(), ast_log(), ast_generator::generate, ast_channel::generator, ast_channel::generatordata, LOG_DEBUG, and option_debug.
Referenced by ast_activate_generator(), and ast_read_generator_actions().
01839 { 01840 /* Called if generator doesn't have data */ 01841 void *tmp; 01842 int res; 01843 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples); 01844 struct ast_channel *chan = data; 01845 tmp = chan->generatordata; 01846 chan->generatordata = NULL; 01847 generate = chan->generator->generate; 01848 res = generate(chan, tmp, 0, 160); 01849 chan->generatordata = tmp; 01850 if (res) { 01851 if (option_debug) 01852 ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); 01853 ast_deactivate_generator(chan); 01854 } 01855 return 0; 01856 }
static void queue_frame_to_spies | ( | struct ast_channel * | chan, | |
struct ast_frame * | f, | |||
enum spy_direction | dir | |||
) | [static] |
Definition at line 1574 of file channel.c.
References ast_clear_flag, ast_cond_signal(), AST_FORMAT_SLINEAR, ast_frdup(), ast_frfree(), ast_getformatname(), AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_test_flag, ast_translate(), ast_translator_build_path(), ast_translator_free_path(), CHANSPY_RUNNING, CHANSPY_TRIGGER_FLUSH, CHANSPY_TRIGGER_MODE, CHANSPY_TRIGGER_NONE, CHANSPY_TRIGGER_READ, CHANSPY_TRIGGER_WRITE, ast_channel_spy_queue::format, channel_spy_trans::last_format, ast_channel_spy::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, option_debug, channel_spy_trans::path, ast_channel_spy::read_queue, ast_channel_spy_list::read_translator, ast_frame::samples, ast_channel_spy_queue::samples, ast_channel::spies, SPY_QUEUE_SAMPLE_LIMIT, SPY_READ, SPY_WRITE, ast_channel_spy::status, ast_frame::subclass, ast_channel_spy::trigger, ast_channel_spy::type, ast_channel_spy::write_queue, and ast_channel_spy_list::write_translator.
Referenced by __ast_read(), and ast_write().
01575 { 01576 struct ast_frame *translated_frame = NULL; 01577 struct ast_channel_spy *spy; 01578 struct channel_spy_trans *trans; 01579 01580 trans = (dir == SPY_READ) ? &chan->spies->read_translator : &chan->spies->write_translator; 01581 01582 AST_LIST_TRAVERSE(&chan->spies->list, spy, list) { 01583 struct ast_channel_spy_queue *queue; 01584 struct ast_frame *duped_fr; 01585 01586 if (spy->status != CHANSPY_RUNNING) 01587 continue; 01588 01589 ast_mutex_lock(&spy->lock); 01590 01591 queue = (dir == SPY_READ) ? &spy->read_queue : &spy->write_queue; 01592 01593 if ((queue->format == AST_FORMAT_SLINEAR) && (f->subclass != AST_FORMAT_SLINEAR)) { 01594 if (!translated_frame) { 01595 if (trans->path && (trans->last_format != f->subclass)) { 01596 ast_translator_free_path(trans->path); 01597 trans->path = NULL; 01598 } 01599 if (!trans->path) { 01600 if (option_debug) 01601 ast_log(LOG_DEBUG, "Building translator from %s to SLINEAR for spies on channel %s\n", 01602 ast_getformatname(f->subclass), chan->name); 01603 if ((trans->path = ast_translator_build_path(AST_FORMAT_SLINEAR, f->subclass)) == NULL) { 01604 ast_log(LOG_WARNING, "Cannot build a path from %s to %s\n", 01605 ast_getformatname(f->subclass), ast_getformatname(AST_FORMAT_SLINEAR)); 01606 ast_mutex_unlock(&spy->lock); 01607 continue; 01608 } else { 01609 trans->last_format = f->subclass; 01610 } 01611 } 01612 if (!(translated_frame = ast_translate(trans->path, f, 0))) { 01613 ast_log(LOG_ERROR, "Translation to %s failed, dropping frame for spies\n", 01614 ast_getformatname(AST_FORMAT_SLINEAR)); 01615 ast_mutex_unlock(&spy->lock); 01616 break; 01617 } 01618 } 01619 duped_fr = ast_frdup(translated_frame); 01620 } else if (f->subclass != queue->format) { 01621 ast_log(LOG_WARNING, "Spy '%s' on channel '%s' wants format '%s', but frame is '%s', dropping\n", 01622 spy->type, chan->name, 01623 ast_getformatname(queue->format), ast_getformatname(f->subclass)); 01624 ast_mutex_unlock(&spy->lock); 01625 continue; 01626 } else 01627 duped_fr = ast_frdup(f); 01628 01629 AST_LIST_INSERT_TAIL(&queue->list, duped_fr, frame_list); 01630 01631 queue->samples += f->samples; 01632 01633 if (queue->samples > SPY_QUEUE_SAMPLE_LIMIT) { 01634 if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) { 01635 switch (ast_test_flag(spy, CHANSPY_TRIGGER_MODE)) { 01636 case CHANSPY_TRIGGER_READ: 01637 if (dir == SPY_WRITE) { 01638 ast_set_flag(spy, CHANSPY_TRIGGER_WRITE); 01639 ast_clear_flag(spy, CHANSPY_TRIGGER_READ); 01640 if (option_debug) 01641 ast_log(LOG_DEBUG, "Switching spy '%s' on '%s' to write-trigger mode\n", 01642 spy->type, chan->name); 01643 } 01644 break; 01645 case CHANSPY_TRIGGER_WRITE: 01646 if (dir == SPY_READ) { 01647 ast_set_flag(spy, CHANSPY_TRIGGER_READ); 01648 ast_clear_flag(spy, CHANSPY_TRIGGER_WRITE); 01649 if (option_debug) 01650 ast_log(LOG_DEBUG, "Switching spy '%s' on '%s' to read-trigger mode\n", 01651 spy->type, chan->name); 01652 } 01653 break; 01654 } 01655 if (option_debug) 01656 ast_log(LOG_DEBUG, "Triggering queue flush for spy '%s' on '%s'\n", 01657 spy->type, chan->name); 01658 ast_set_flag(spy, CHANSPY_TRIGGER_FLUSH); 01659 ast_cond_signal(&spy->trigger); 01660 } else { 01661 if (option_debug) 01662 ast_log(LOG_DEBUG, "Spy '%s' on channel '%s' %s queue too long, dropping frames\n", 01663 spy->type, chan->name, (dir == SPY_READ) ? "read" : "write"); 01664 while (queue->samples > SPY_QUEUE_SAMPLE_LIMIT) { 01665 struct ast_frame *drop = AST_LIST_REMOVE_HEAD(&queue->list, frame_list); 01666 queue->samples -= drop->samples; 01667 ast_frfree(drop); 01668 } 01669 } 01670 } else { 01671 switch (ast_test_flag(spy, CHANSPY_TRIGGER_MODE)) { 01672 case CHANSPY_TRIGGER_READ: 01673 if (dir == SPY_READ) 01674 ast_cond_signal(&spy->trigger); 01675 break; 01676 case CHANSPY_TRIGGER_WRITE: 01677 if (dir == SPY_WRITE) 01678 ast_cond_signal(&spy->trigger); 01679 break; 01680 } 01681 } 01682 01683 ast_mutex_unlock(&spy->lock); 01684 } 01685 01686 if (translated_frame) 01687 ast_frfree(translated_frame); 01688 }
static int set_format | ( | struct ast_channel * | chan, | |
int | fmt, | |||
int * | rawformat, | |||
int * | format, | |||
struct ast_trans_pvt ** | trans, | |||
const int | direction | |||
) | [static] |
Definition at line 2972 of file channel.c.
References ast_channel_lock, ast_channel_unlock, AST_FORMAT_AUDIO_MASK, ast_getformatname(), ast_log(), ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), LOG_DEBUG, LOG_WARNING, ast_channel::nativeformats, and option_debug.
Referenced by ast_set_read_format(), and ast_set_write_format().
02974 { 02975 int native; 02976 int res; 02977 02978 /* Make sure we only consider audio */ 02979 fmt &= AST_FORMAT_AUDIO_MASK; 02980 02981 native = chan->nativeformats; 02982 /* Find a translation path from the native format to one of the desired formats */ 02983 if (!direction) 02984 /* reading */ 02985 res = ast_translator_best_choice(&fmt, &native); 02986 else 02987 /* writing */ 02988 res = ast_translator_best_choice(&native, &fmt); 02989 02990 if (res < 0) { 02991 ast_log(LOG_WARNING, "Unable to find a codec translation path from %s to %s\n", 02992 ast_getformatname(native), ast_getformatname(fmt)); 02993 return -1; 02994 } 02995 02996 /* Now we have a good choice for both. */ 02997 ast_channel_lock(chan); 02998 02999 if ((*rawformat == native) && (*format == fmt) && ((*rawformat == *format) || (*trans))) { 03000 /* the channel is already in these formats, so nothing to do */ 03001 ast_channel_unlock(chan); 03002 return 0; 03003 } 03004 03005 *rawformat = native; 03006 /* User perspective is fmt */ 03007 *format = fmt; 03008 /* Free any read translation we have right now */ 03009 if (*trans) 03010 ast_translator_free_path(*trans); 03011 /* Build a translation path from the raw format to the desired format */ 03012 if (!direction) 03013 /* reading */ 03014 *trans = ast_translator_build_path(*format, *rawformat); 03015 else 03016 /* writing */ 03017 *trans = ast_translator_build_path(*rawformat, *format); 03018 ast_channel_unlock(chan); 03019 if (option_debug) 03020 ast_log(LOG_DEBUG, "Set channel %s to %s format %s\n", chan->name, 03021 direction ? "write" : "read", ast_getformatname(fmt)); 03022 return 0; 03023 }
static int show_channeltype | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 278 of file channel.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_channel_tech::capabilities, ast_channel_tech::devicestate, ast_channel_tech::indicate, LOG_WARNING, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel_tech::send_digit_begin, ast_channel_tech::send_digit_end, ast_channel_tech::send_html, ast_channel_tech::send_image, ast_channel_tech::send_text, chanlist::tech, ast_channel_tech::transfer, and ast_channel_tech::type.
00279 { 00280 struct chanlist *cl = NULL; 00281 00282 if (argc != 4) 00283 return RESULT_SHOWUSAGE; 00284 00285 if (AST_LIST_LOCK(&channels)) { 00286 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 00287 return RESULT_FAILURE; 00288 } 00289 00290 AST_LIST_TRAVERSE(&backends, cl, list) { 00291 if (!strncasecmp(cl->tech->type, argv[3], strlen(cl->tech->type))) { 00292 break; 00293 } 00294 } 00295 00296 00297 if (!cl) { 00298 ast_cli(fd, "\n%s is not a registered channel driver.\n", argv[3]); 00299 AST_LIST_UNLOCK(&channels); 00300 return RESULT_FAILURE; 00301 } 00302 00303 ast_cli(fd, 00304 "-- Info about channel driver: %s --\n" 00305 " Device State: %s\n" 00306 " Indication: %s\n" 00307 " Transfer : %s\n" 00308 " Capabilities: %d\n" 00309 " Digit Begin: %s\n" 00310 " Digit End: %s\n" 00311 " Send HTML : %s\n" 00312 " Image Support: %s\n" 00313 " Text Support: %s\n", 00314 cl->tech->type, 00315 (cl->tech->devicestate) ? "yes" : "no", 00316 (cl->tech->indicate) ? "yes" : "no", 00317 (cl->tech->transfer) ? "yes" : "no", 00318 (cl->tech->capabilities) ? cl->tech->capabilities : -1, 00319 (cl->tech->send_digit_begin) ? "yes" : "no", 00320 (cl->tech->send_digit_end) ? "yes" : "no", 00321 (cl->tech->send_html) ? "yes" : "no", 00322 (cl->tech->send_image) ? "yes" : "no", 00323 (cl->tech->send_text) ? "yes" : "no" 00324 00325 ); 00326 00327 AST_LIST_UNLOCK(&channels); 00328 return RESULT_SUCCESS; 00329 }
static int show_channeltype_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 225 of file channel.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_channel_tech::capabilities, ast_channel_tech::devicestate, ast_channel_tech::indicate, LOG_WARNING, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel_tech::send_digit_begin, ast_channel_tech::send_digit_end, ast_channel_tech::send_html, ast_channel_tech::send_image, ast_channel_tech::send_text, chanlist::tech, ast_channel_tech::transfer, and ast_channel_tech::type.
00226 { 00227 struct chanlist *cl = NULL; 00228 00229 if (argc != 3) 00230 return RESULT_SHOWUSAGE; 00231 00232 if (AST_LIST_LOCK(&channels)) { 00233 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 00234 return RESULT_FAILURE; 00235 } 00236 00237 AST_LIST_TRAVERSE(&backends, cl, list) { 00238 if (!strncasecmp(cl->tech->type, argv[2], strlen(cl->tech->type))) { 00239 break; 00240 } 00241 } 00242 00243 00244 if (!cl) { 00245 ast_cli(fd, "\n%s is not a registered channel driver.\n", argv[2]); 00246 AST_LIST_UNLOCK(&channels); 00247 return RESULT_FAILURE; 00248 } 00249 00250 ast_cli(fd, 00251 "-- Info about channel driver: %s --\n" 00252 " Device State: %s\n" 00253 " Indication: %s\n" 00254 " Transfer : %s\n" 00255 " Capabilities: %d\n" 00256 " Digit Begin: %s\n" 00257 " Digit End: %s\n" 00258 " Send HTML : %s\n" 00259 " Image Support: %s\n" 00260 " Text Support: %s\n", 00261 cl->tech->type, 00262 (cl->tech->devicestate) ? "yes" : "no", 00263 (cl->tech->indicate) ? "yes" : "no", 00264 (cl->tech->transfer) ? "yes" : "no", 00265 (cl->tech->capabilities) ? cl->tech->capabilities : -1, 00266 (cl->tech->send_digit_begin) ? "yes" : "no", 00267 (cl->tech->send_digit_end) ? "yes" : "no", 00268 (cl->tech->send_html) ? "yes" : "no", 00269 (cl->tech->send_image) ? "yes" : "no", 00270 (cl->tech->send_text) ? "yes" : "no" 00271 00272 ); 00273 00274 AST_LIST_UNLOCK(&channels); 00275 return RESULT_SUCCESS; 00276 }
static int show_channeltypes | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 198 of file channel.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_channel_tech::description, ast_channel_tech::devicestate, FORMAT, ast_channel_tech::indicate, LOG_WARNING, RESULT_SUCCESS, chanlist::tech, ast_channel_tech::transfer, and ast_channel_tech::type.
00199 { 00200 #define FORMAT "%-10.10s %-40.40s %-12.12s %-12.12s %-12.12s\n" 00201 struct chanlist *cl; 00202 int count_chan = 0; 00203 00204 ast_cli(fd, FORMAT, "Type", "Description", "Devicestate", "Indications", "Transfer"); 00205 ast_cli(fd, FORMAT, "----------", "-----------", "-----------", "-----------", "--------"); 00206 if (AST_LIST_LOCK(&channels)) { 00207 ast_log(LOG_WARNING, "Unable to lock channel list\n"); 00208 return -1; 00209 } 00210 AST_LIST_TRAVERSE(&backends, cl, list) { 00211 ast_cli(fd, FORMAT, cl->tech->type, cl->tech->description, 00212 (cl->tech->devicestate) ? "yes" : "no", 00213 (cl->tech->indicate) ? "yes" : "no", 00214 (cl->tech->transfer) ? "yes" : "no"); 00215 count_chan++; 00216 } 00217 AST_LIST_UNLOCK(&channels); 00218 ast_cli(fd, "----------\n%d channel drivers registered.\n", count_chan); 00219 return RESULT_SUCCESS; 00220 00221 #undef FORMAT 00222 00223 }
static void* silence_generator_alloc | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
static int silence_generator_generate | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 4743 of file channel.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_write(), and ast_frame::frametype.
04744 { 04745 short buf[samples]; 04746 struct ast_frame frame = { 04747 .frametype = AST_FRAME_VOICE, 04748 .subclass = AST_FORMAT_SLINEAR, 04749 .data = buf, 04750 .samples = samples, 04751 .datalen = sizeof(buf), 04752 }; 04753 memset(buf, 0, sizeof(buf)); 04754 if (ast_write(chan, &frame)) 04755 return -1; 04756 return 0; 04757 }
static void silence_generator_release | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
static void spy_cleanup | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 1427 of file channel.c.
References AST_LIST_EMPTY, ast_translator_free_path(), free, channel_spy_trans::path, ast_channel_spy_list::read_translator, ast_channel::spies, and ast_channel_spy_list::write_translator.
Referenced by ast_channel_spy_remove(), ast_channel_spy_stop_by_type(), and detach_spies().
01428 { 01429 if (!AST_LIST_EMPTY(&chan->spies->list)) 01430 return; 01431 if (chan->spies->read_translator.path) 01432 ast_translator_free_path(chan->spies->read_translator.path); 01433 if (chan->spies->write_translator.path) 01434 ast_translator_free_path(chan->spies->write_translator.path); 01435 free(chan->spies); 01436 chan->spies = NULL; 01437 return; 01438 }
static void spy_detach | ( | struct ast_channel_spy * | spy, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 1441 of file channel.c.
References ast_cond_signal(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_channel_spy::chan, CHANSPY_DONE, CHANSPY_STOP, CHANSPY_TRIGGER_MODE, CHANSPY_TRIGGER_NONE, ast_channel_spy::lock, LOG_DEBUG, option_debug, ast_channel_spy::status, ast_channel_spy::trigger, and ast_channel_spy::type.
Referenced by ast_channel_spy_remove(), ast_channel_spy_stop_by_type(), and detach_spies().
01442 { 01443 /* We only need to poke them if they aren't already done */ 01444 if (spy->status != CHANSPY_DONE) { 01445 ast_mutex_lock(&spy->lock); 01446 /* Indicate to the spy to stop */ 01447 spy->status = CHANSPY_STOP; 01448 spy->chan = NULL; 01449 /* Poke the spy if needed */ 01450 if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) 01451 ast_cond_signal(&spy->trigger); 01452 ast_mutex_unlock(&spy->lock); 01453 } 01454 01455 /* Print it out while we still have a lock so the structure can't go away (if signalled above) */ 01456 if (option_debug) 01457 ast_log(LOG_DEBUG, "Spy %s removed from channel %s\n", spy->type, chan->name); 01458 01459 return; 01460 }
static void* tonepair_alloc | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 4376 of file channel.c.
References ast_calloc, AST_FLAG_WRITE_INT, AST_FORMAT_SLINEAR, ast_log(), ast_set_flag, ast_set_write_format(), tonepair_def::duration, tonepair_state::duration, tonepair_state::fac1, tonepair_state::fac2, tonepair_def::freq1, tonepair_def::freq2, LOG_WARNING, tonepair_state::modulate, tonepair_state::origwfmt, tonepair_release(), tonepair_state::v1_1, tonepair_state::v2_1, tonepair_state::v2_2, tonepair_state::v3_1, tonepair_state::v3_2, tonepair_def::vol, and ast_channel::writeformat.
04377 { 04378 struct tonepair_state *ts; 04379 struct tonepair_def *td = params; 04380 04381 if (!(ts = ast_calloc(1, sizeof(*ts)))) 04382 return NULL; 04383 ts->origwfmt = chan->writeformat; 04384 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { 04385 ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name); 04386 tonepair_release(NULL, ts); 04387 ts = NULL; 04388 } else { 04389 ts->fac1 = 2.0 * cos(2.0 * M_PI * (td->freq1 / 8000.0)) * 32768.0; 04390 ts->v1_1 = 0; 04391 ts->v2_1 = sin(-4.0 * M_PI * (td->freq1 / 8000.0)) * td->vol; 04392 ts->v3_1 = sin(-2.0 * M_PI * (td->freq1 / 8000.0)) * td->vol; 04393 ts->v2_1 = 0; 04394 ts->fac2 = 2.0 * cos(2.0 * M_PI * (td->freq2 / 8000.0)) * 32768.0; 04395 ts->v2_2 = sin(-4.0 * M_PI * (td->freq2 / 8000.0)) * td->vol; 04396 ts->v3_2 = sin(-2.0 * M_PI * (td->freq2 / 8000.0)) * td->vol; 04397 ts->duration = td->duration; 04398 ts->modulate = 0; 04399 } 04400 /* Let interrupts interrupt :) */ 04401 ast_set_flag(chan, AST_FLAG_WRITE_INT); 04402 return ts; 04403 }
static int tonepair_generator | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 4405 of file channel.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), ast_frame::data, tonepair_state::data, ast_frame::datalen, tonepair_state::duration, tonepair_state::f, tonepair_state::fac1, tonepair_state::fac2, ast_frame::frametype, LOG_WARNING, tonepair_state::modulate, ast_frame::offset, tonepair_state::pos, ast_frame::samples, ast_frame::subclass, tonepair_state::v1_1, tonepair_state::v1_2, tonepair_state::v2_1, tonepair_state::v2_2, tonepair_state::v3_1, and tonepair_state::v3_2.
04406 { 04407 struct tonepair_state *ts = data; 04408 int x; 04409 04410 /* we need to prepare a frame with 16 * timelen samples as we're 04411 * generating SLIN audio 04412 */ 04413 len = samples * 2; 04414 04415 if (len > sizeof(ts->data) / 2 - 1) { 04416 ast_log(LOG_WARNING, "Can't generate that much data!\n"); 04417 return -1; 04418 } 04419 memset(&ts->f, 0, sizeof(ts->f)); 04420 for (x=0;x<len/2;x++) { 04421 ts->v1_1 = ts->v2_1; 04422 ts->v2_1 = ts->v3_1; 04423 ts->v3_1 = (ts->fac1 * ts->v2_1 >> 15) - ts->v1_1; 04424 04425 ts->v1_2 = ts->v2_2; 04426 ts->v2_2 = ts->v3_2; 04427 ts->v3_2 = (ts->fac2 * ts->v2_2 >> 15) - ts->v1_2; 04428 if (ts->modulate) { 04429 int p; 04430 p = ts->v3_2 - 32768; 04431 if (p < 0) p = -p; 04432 p = ((p * 9) / 10) + 1; 04433 ts->data[x] = (ts->v3_1 * p) >> 15; 04434 } else 04435 ts->data[x] = ts->v3_1 + ts->v3_2; 04436 } 04437 ts->f.frametype = AST_FRAME_VOICE; 04438 ts->f.subclass = AST_FORMAT_SLINEAR; 04439 ts->f.datalen = len; 04440 ts->f.samples = samples; 04441 ts->f.offset = AST_FRIENDLY_OFFSET; 04442 ts->f.data = ts->data; 04443 ast_write(chan, &ts->f); 04444 ts->pos += x; 04445 if (ts->duration > 0) { 04446 if (ts->pos >= ts->duration * 8) 04447 return -1; 04448 } 04449 return 0; 04450 }
static void tonepair_release | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 4367 of file channel.c.
References ast_set_write_format(), free, and tonepair_state::origwfmt.
Referenced by tonepair_alloc().
04368 { 04369 struct tonepair_state *ts = params; 04370 04371 if (chan) 04372 ast_set_write_format(chan, ts->origwfmt); 04373 free(ts); 04374 }
void(* ast_moh_cleanup_ptr)(struct ast_channel *) = NULL [static] |
Definition at line 4525 of file channel.c.
Referenced by ast_install_music_functions(), ast_moh_cleanup(), and ast_uninstall_music_functions().
int(* ast_moh_start_ptr)(struct ast_channel *, const char *, const char *) = NULL [static] |
Definition at line 4523 of file channel.c.
Referenced by ast_install_music_functions(), ast_moh_start(), and ast_uninstall_music_functions().
void(* ast_moh_stop_ptr)(struct ast_channel *) = NULL [static] |
Definition at line 4524 of file channel.c.
Referenced by ast_install_music_functions(), ast_moh_stop(), and ast_uninstall_music_functions().
map AST_CAUSE's to readable string representations
Referenced by ast_cause2str(), ast_str2cause(), and dump_cause().
struct ast_cli_entry cli_channel[] [static] |
struct ast_cli_entry cli_show_channeltype_deprecated [static] |
Initial value:
{ { "show", "channeltype", NULL }, show_channeltype_deprecated, NULL, NULL, complete_channeltypes_deprecated }
struct ast_cli_entry cli_show_channeltypes_deprecated [static] |
Initial value:
{ { "show", "channeltypes", NULL }, show_channeltypes, NULL, NULL }
unsigned long global_fin |
unsigned long global_fout |
struct ast_channel_tech null_tech [static] |
Initial value:
{ .type = "NULL", .description = "Null channel (should not see this)", }
Definition at line 722 of file channel.c.
Referenced by ast_channel_alloc().
char show_channeltype_usage[] [static] |
char show_channeltypes_usage[] [static] |
int shutting_down [static] |
Prevent new channel allocation if shutting down.
Definition at line 98 of file channel.c.
Referenced by ast_begin_shutdown(), ast_cancel_shutdown(), ast_channel_alloc(), and ast_shutting_down().
struct ast_generator silence_generator [static] |
Initial value:
{ .alloc = silence_generator_alloc, .release = silence_generator_release, .generate = silence_generator_generate, }
struct ast_generator tonepair [static] |
Initial value:
{ alloc: tonepair_alloc, release: tonepair_release, generate: tonepair_generator, }
Definition at line 4452 of file channel.c.
Referenced by ast_tonepair_start().
int uniqueint [static] |