![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
channel.c File Reference
Definition in file channel.c.
#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/zapata.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"
Include dependency graph for channel.c:

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 | 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 | |
| int | __ast_answer (struct ast_channel *chan, unsigned int delay) |
| static struct ast_frame * | __ast_read (struct ast_channel *chan, int dropaudio) |
| 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 channel. | |
| void | ast_begin_shutdown (int hangup) |
| Initiate system shutdown. | |
| int | ast_best_codec (int fmts) |
| Pick the best audio codec. | |
| 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. | |
| ast_channel * | ast_channel_alloc (int needqueue, int state, const char *cid_num, const char *cid_name, const char *name_fmt,...) |
| Create a 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 the settings of when to hang a channel up. | |
| int | ast_channel_datastore_add (struct ast_channel *chan, struct ast_datastore *datastore) |
| Add a datastore to a channel. | |
| ast_datastore * | ast_channel_datastore_alloc (const struct ast_datastore_info *info, char *uid) |
| Create a channel datastore structure. | |
| 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. | |
| int | ast_channel_early_bridge (struct ast_channel *c0, struct ast_channel *c1) |
| Bridge two channels together (early). | |
| 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. | |
| static int | ast_channel_make_compatible_helper (struct ast_channel *from, struct ast_channel *to) |
| Set up translation from one channel to another. | |
| 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 channel technology (a new channel driver) Called by a channel module to register the kind of channels it supports. | |
| 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 hang a channel up. | |
| 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. | |
| 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. | |
| 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. | |
| ast_channel * | ast_channel_walk_locked (const struct ast_channel *prev) |
| Browse channels in use Browse the channels currently 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) |
| ast_variable * | ast_channeltype_list (void) |
| return an ast_variable list of channeltypes | |
| int | ast_check_hangup (struct ast_channel *chan) |
| Check 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) |
| Start masquerading a channel XXX This is a seriously whacked 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. | |
| 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) |
| ast_channel * | ast_get_channel_by_exten_locked (const char *exten, const char *context) |
| Get channel by exten (and optionally context) and lock it. | |
| ast_channel * | ast_get_channel_by_name_locked (const char *name) |
| Get channel by name (locks channel). | |
| ast_channel * | ast_get_channel_by_name_prefix_locked (const char *name, const int namelen) |
| Get channel by name prefix (locks channel). | |
| const 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) |
| Hang up 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- and pickup groups into buffer | |
| 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 with payload. | |
| 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 frame. | |
| int | ast_queue_hangup (struct ast_channel *chan) |
| Queue a hangup frame. | |
| ast_frame * | ast_read (struct ast_channel *chan) |
| Reads a frame. | |
| ast_frame * | ast_read_noaudio (struct ast_channel *chan) |
| Reads a frame, returning AST_FRAME_NULL frame if audio. | |
| 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. | |
| ast_channel * | ast_request (const char *type, int format, void *data, int *cause) |
| Requests a channel. | |
| 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 for a specified amount of time, looking for hangups. | |
| int | ast_safe_sleep_conditional (struct ast_channel *chan, int ms, int(*cond)(void *), void *data) |
| Wait for a specified amount of time, looking for hangups and a condition argument. | |
| 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) |
| Send a DTMF digit to a channel Send a DTMF digit to a channel. | |
| int | ast_senddigit_end (struct ast_channel *chan, char digit, unsigned int duration) |
| Send a DTMF digit to a channel. | |
| 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 component 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 up a channel. | |
| int | ast_softhangup_nolock (struct ast_channel *chan, int cause) |
| Softly hangup up a channel (no channel lock). | |
| const 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) | |
| 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 channel (if supported). Returns -1 on error, 0 if not supported and 1 if supported and requested. | |
| 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. | |
| 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) |
| Waits for input on an fd This version works on fd's only. Be careful with it. | |
| ast_channel * | ast_waitfor_nandfds (struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms) |
| Waits for activity on a group of channels. | |
| 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. | |
| 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. | |
| ast_channel * | ast_walk_channel_by_name_prefix_locked (const struct ast_channel *chan, const char *name, const int namelen) |
| Get channel by name prefix (locks channel). | |
| 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 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_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 |
| const struct ast_cause | causes [] |
| static struct ast_cli_entry | cli_channel [] |
| unsigned long | global_fin |
| unsigned long | global_fout |
| static const struct ast_channel_tech | null_tech |
| static const char | show_channeltype_usage [] |
| static const char | show_channeltypes_usage [] |
| static int | shutting_down |
| static struct ast_generator | silence_generator |
| static struct ast_generator | tonepair |
| static int | uniqueint |
|
|
100ms Definition at line 105 of file channel.c. Referenced by __ast_read(). |
|
|
|
|
|
Definition at line 1400 of file channel.c. Referenced by queue_frame_to_spies(). |
|
|
Definition at line 102 of file channel.c. Referenced by ast_state2str(). |
|
|
Definition at line 1395 of file channel.c.
|
|
||||||||||||
|
Definition at line 1612 of file channel.c. References ast_channel::_state, ast_channel_tech::answer, ast_cdr_answer(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), AST_FLAG_OUTGOING, AST_FLAG_ZOMBIE, ast_safe_sleep(), ast_setstate(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_test_flag, ast_channel::cdr, and ast_channel::tech. Referenced by ast_answer(), and pbx_builtin_answer(). 01613 { 01614 int res = 0; 01615 01616 ast_channel_lock(chan); 01617 01618 /* You can't answer an outbound call */ 01619 if (ast_test_flag(chan, AST_FLAG_OUTGOING)) { 01620 ast_channel_unlock(chan); 01621 return 0; 01622 } 01623 01624 /* Stop if we're a zombie or need a soft hangup */ 01625 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 01626 ast_channel_unlock(chan); 01627 return -1; 01628 } 01629 01630 switch (chan->_state) { 01631 case AST_STATE_RINGING: 01632 case AST_STATE_RING: 01633 if (chan->tech->answer) 01634 res = chan->tech->answer(chan); 01635 ast_setstate(chan, AST_STATE_UP); 01636 ast_cdr_answer(chan->cdr); 01637 ast_channel_unlock(chan); 01638 if (delay) 01639 ast_safe_sleep(chan, delay); 01640 return res; 01641 break; 01642 case AST_STATE_UP: 01643 ast_cdr_answer(chan->cdr); 01644 break; 01645 default: 01646 break; 01647 } 01648 01649 ast_channel_unlock(chan); 01650 01651 return res; 01652 }
|
|
||||||||||||
|
Definition at line 1977 of file channel.c. References ast_channel::_softhangup, ast_channel::_state, ast_channel::alertpipe, ast_cdr_answer(), ast_cdr_end(), 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_CNG, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frame_dump(), AST_FRAME_VOICE, ast_frfree(), AST_GENERATOR_FD, ast_getformatname(), ast_internal_timing_enabled(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_SET_NOLOCK, AST_LIST_NEXT, AST_LIST_REMOVE_HEAD, ast_log(), AST_MONITOR_RUNNING, ast_null_frame, ast_seekstream(), ast_set_flag, ast_setstate(), ast_settimeout(), 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_begin_tv, ast_channel::dtmff, ast_channel::dtmfq, ast_channel::emulate_dtmf_digit, ast_channel::emulate_dtmf_duration, ast_channel_tech::exception, ast_channel::fdno, ast_channel::fds, ast_channel::fin, FRAMECOUNT_INC, ast_frame::frametype, func, ast_generator::generate, ast_channel::generator, generator_force(), ast_channel::generatordata, ast_channel::insmpl, 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, 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(). 01978 { 01979 struct ast_frame *f = NULL; /* the return value */ 01980 int blah; 01981 int prestate; 01982 01983 /* this function is very long so make sure there is only one return 01984 * point at the end (there is only one exception to this). 01985 */ 01986 ast_channel_lock(chan); 01987 if (chan->masq) { 01988 if (ast_do_masquerade(chan)) 01989 ast_log(LOG_WARNING, "Failed to perform masquerade\n"); 01990 else 01991 f = &ast_null_frame; 01992 goto done; 01993 } 01994 01995 /* Stop if we're a zombie or need a soft hangup */ 01996 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 01997 if (chan->generator) 01998 ast_deactivate_generator(chan); 01999 goto done; 02000 } 02001 prestate = chan->_state; 02002 02003 if (!ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF | AST_FLAG_IN_DTMF) && 02004 !ast_strlen_zero(chan->dtmfq)) { 02005 /* We have DTMF that has been deferred. Return it now */ 02006 chan->dtmff.subclass = chan->dtmfq[0]; 02007 /* Drop first digit from the buffer */ 02008 memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1); 02009 f = &chan->dtmff; 02010 if (ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) 02011 chan->dtmff.frametype = AST_FRAME_DTMF_END; 02012 else { 02013 chan->dtmff.frametype = AST_FRAME_DTMF_BEGIN; 02014 ast_set_flag(chan, AST_FLAG_EMULATE_DTMF); 02015 chan->emulate_dtmf_digit = f->subclass; 02016 chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION; 02017 chan->dtmf_begin_tv = ast_tvnow(); 02018 } 02019 goto done; 02020 } 02021 02022 /* Read and ignore anything on the alertpipe, but read only 02023 one sizeof(blah) per frame that we send from it */ 02024 if (chan->alertpipe[0] > -1) 02025 read(chan->alertpipe[0], &blah, sizeof(blah)); 02026 02027 #ifdef HAVE_ZAPTEL 02028 if (chan->timingfd > -1 && chan->fdno == AST_TIMING_FD && ast_test_flag(chan, AST_FLAG_EXCEPTION)) { 02029 int res; 02030 02031 ast_clear_flag(chan, AST_FLAG_EXCEPTION); 02032 blah = -1; 02033 /* IF we can't get event, assume it's an expired as-per the old interface */ 02034 res = ioctl(chan->timingfd, ZT_GETEVENT, &blah); 02035 if (res) 02036 blah = ZT_EVENT_TIMER_EXPIRED; 02037 02038 if (blah == ZT_EVENT_TIMER_PING) { 02039 if (AST_LIST_EMPTY(&chan->readq) || !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) { 02040 /* Acknowledge PONG unless we need it again */ 02041 if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) { 02042 ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno)); 02043 } 02044 } 02045 } else if (blah == ZT_EVENT_TIMER_EXPIRED) { 02046 ioctl(chan->timingfd, ZT_TIMERACK, &blah); 02047 if (chan->timingfunc) { 02048 /* save a copy of func/data before unlocking the channel */ 02049 int (*func)(void *) = chan->timingfunc; 02050 void *data = chan->timingdata; 02051 ast_channel_unlock(chan); 02052 func(data); 02053 } else { 02054 blah = 0; 02055 ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah); 02056 chan->timingdata = NULL; 02057 ast_channel_unlock(chan); 02058 } 02059 /* cannot 'goto done' because the channel is already unlocked */ 02060 return &ast_null_frame; 02061 } else 02062 ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name); 02063 } else 02064 #endif 02065 if (chan->fds[AST_GENERATOR_FD] > -1 && chan->fdno == AST_GENERATOR_FD) { 02066 /* if the AST_GENERATOR_FD is set, call the generator with args 02067 * set to -1 so it can do whatever it needs to. 02068 */ 02069 void *tmp = chan->generatordata; 02070 chan->generatordata = NULL; /* reset to let ast_write get through */ 02071 chan->generator->generate(chan, tmp, -1, -1); 02072 chan->generatordata = tmp; 02073 f = &ast_null_frame; 02074 goto done; 02075 } 02076 02077 /* Check for pending read queue */ 02078 if (!AST_LIST_EMPTY(&chan->readq)) { 02079 f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list); 02080 /* Interpret hangup and return NULL */ 02081 /* XXX why not the same for frames from the channel ? */ 02082 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) { 02083 ast_frfree(f); 02084 f = NULL; 02085 } 02086 } else { 02087 chan->blocker = pthread_self(); 02088 if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) { 02089 if (chan->tech->exception) 02090 f = chan->tech->exception(chan); 02091 else { 02092 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name); 02093 f = &ast_null_frame; 02094 } 02095 /* Clear the exception flag */ 02096 ast_clear_flag(chan, AST_FLAG_EXCEPTION); 02097 } else if (chan->tech->read) 02098 f = chan->tech->read(chan); 02099 else 02100 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name); 02101 } 02102 02103 if (f) { 02104 /* if the channel driver returned more than one frame, stuff the excess 02105 into the readq for the next ast_read call (note that we can safely assume 02106 that the readq is empty, because otherwise we would not have called into 02107 the channel driver and f would be only a single frame) 02108 */ 02109 if (AST_LIST_NEXT(f, frame_list)) { 02110 AST_LIST_HEAD_SET_NOLOCK(&chan->readq, AST_LIST_NEXT(f, frame_list)); 02111 AST_LIST_NEXT(f, frame_list) = NULL; 02112 } 02113 02114 switch (f->frametype) { 02115 case AST_FRAME_CONTROL: 02116 if (f->subclass == AST_CONTROL_ANSWER) { 02117 if (!ast_test_flag(chan, AST_FLAG_OUTGOING)) { 02118 if (option_debug) 02119 ast_log(LOG_DEBUG, "Ignoring answer on an inbound call!\n"); 02120 ast_frfree(f); 02121 f = &ast_null_frame; 02122 } else if (prestate == AST_STATE_UP) { 02123 if (option_debug) 02124 ast_log(LOG_DEBUG, "Dropping duplicate answer!\n"); 02125 ast_frfree(f); 02126 f = &ast_null_frame; 02127 } else { 02128 /* Answer the CDR */ 02129 ast_setstate(chan, AST_STATE_UP); 02130 ast_cdr_answer(chan->cdr); 02131 } 02132 } 02133 break; 02134 case AST_FRAME_DTMF_END: 02135 ast_log(LOG_DTMF, "DTMF end '%c' received on %s\n", f->subclass, chan->name); 02136 /* Queue it up if DTMF is deffered, or if DTMF emulation is forced. 02137 * However, only let emulation be forced if the other end cares about BEGIN frames */ 02138 if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF) || 02139 (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) ) { 02140 if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) 02141 chan->dtmfq[strlen(chan->dtmfq)] = f->subclass; 02142 else 02143 ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name); 02144 ast_frfree(f); 02145 f = &ast_null_frame; 02146 } else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) { 02147 f->frametype = AST_FRAME_DTMF_BEGIN; 02148 ast_set_flag(chan, AST_FLAG_EMULATE_DTMF); 02149 chan->emulate_dtmf_digit = f->subclass; 02150 chan->dtmf_begin_tv = ast_tvnow(); 02151 if (f->len) 02152 chan->emulate_dtmf_duration = f->len; 02153 else 02154 chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION; 02155 } else { 02156 ast_clear_flag(chan, AST_FLAG_IN_DTMF); 02157 if (!f->len) 02158 f->len = ast_tvdiff_ms(chan->dtmf_begin_tv, ast_tvnow()); 02159 } 02160 break; 02161 case AST_FRAME_DTMF_BEGIN: 02162 ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass, chan->name); 02163 if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY)) { 02164 ast_frfree(f); 02165 f = &ast_null_frame; 02166 } else { 02167 ast_set_flag(chan, AST_FLAG_IN_DTMF); 02168 chan->dtmf_begin_tv = ast_tvnow(); 02169 } 02170 break; 02171 case AST_FRAME_VOICE: 02172 /* The EMULATE_DTMF flag must be cleared here as opposed to when the samples 02173 * first get to zero, because we want to make sure we pass at least one 02174 * voice frame through before starting the next digit, to ensure a gap 02175 * between DTMF digits. */ 02176 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !chan->emulate_dtmf_duration) { 02177 ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF); 02178 chan->emulate_dtmf_digit = 0; 02179 } 02180 02181 if (dropaudio || ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 02182 ast_frfree(f); 02183 f = &ast_null_frame; 02184 } else if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) { 02185 if ((f->samples / 8) >= chan->emulate_dtmf_duration) { /* XXX 8kHz */ 02186 chan->emulate_dtmf_duration = 0; 02187 f->frametype = AST_FRAME_DTMF_END; 02188 f->subclass = chan->emulate_dtmf_digit; 02189 } else { 02190 chan->emulate_dtmf_duration -= f->samples / 8; /* XXX 8kHz */ 02191 ast_frfree(f); 02192 f = &ast_null_frame; 02193 } 02194 } else if (!(f->subclass & chan->nativeformats)) { 02195 /* This frame can't be from the current native formats -- drop it on the 02196 floor */ 02197 ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", 02198 chan->name, ast_getformatname(f->subclass), ast_getformatname(chan->nativeformats)); 02199 ast_frfree(f); 02200 f = &ast_null_frame; 02201 } else { 02202 if (chan->spies) 02203 queue_frame_to_spies(chan, f, SPY_READ); 02204 02205 if (chan->monitor && chan->monitor->read_stream ) { 02206 /* XXX what does this do ? */ 02207 #ifndef MONITOR_CONSTANT_DELAY 02208 int jump = chan->outsmpl - chan->insmpl - 4 * f->samples; 02209 if (jump >= 0) { 02210 jump = chan->outsmpl - chan->insmpl; 02211 if (ast_seekstream(chan->monitor->read_stream, jump, SEEK_FORCECUR) == -1) 02212 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 02213 chan->insmpl += jump + f->samples; 02214 } else 02215 chan->insmpl+= f->samples; 02216 #else 02217 int jump = chan->outsmpl - chan->insmpl; 02218 if (jump - MONITOR_DELAY >= 0) { 02219 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) 02220 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 02221 chan->insmpl += jump; 02222 } else 02223 chan->insmpl += f->samples; 02224 #endif 02225 if (chan->monitor->state == AST_MONITOR_RUNNING) { 02226 if (ast_writestream(chan->monitor->read_stream, f) < 0) 02227 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n"); 02228 } 02229 } 02230 02231 if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL) 02232 f = &ast_null_frame; 02233 02234 /* Run generator sitting on the line if timing device not available 02235 * and synchronous generation of outgoing frames is necessary */ 02236 if (chan->generatordata && !ast_internal_timing_enabled(chan)) { 02237 void *tmp = chan->generatordata; 02238 int res; 02239 02240 if (chan->timingfunc) { 02241 if (option_debug > 1) 02242 ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n"); 02243 ast_settimeout(chan, 0, NULL, NULL); 02244 } 02245 02246 chan->generatordata = NULL; /* reset, to let writes go through */ 02247 res = chan->generator->generate(chan, tmp, f->datalen, f->samples); 02248 chan->generatordata = tmp; 02249 if (res) { 02250 if (option_debug > 1) 02251 ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); 02252 ast_deactivate_generator(chan); 02253 } 02254 02255 } else if (f->frametype == AST_FRAME_CNG) { 02256 if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) { 02257 if (option_debug > 1) 02258 ast_log(LOG_DEBUG, "Generator got CNG, switching to timed mode\n"); 02259 ast_settimeout(chan, 160, generator_force, chan); 02260 } 02261 } 02262 } 02263 default: 02264 /* Just pass it on! */ 02265 break; 02266 } 02267 } else { 02268 /* Make sure we always return NULL in the future */ 02269 chan->_softhangup |= AST_SOFTHANGUP_DEV; 02270 if (chan->generator) 02271 ast_deactivate_generator(chan); 02272 /* End the CDR if appropriate */ 02273 if (chan->cdr) 02274 ast_cdr_end(chan->cdr); 02275 } 02276 02277 /* High bit prints debugging */ 02278 if (chan->fin & DEBUGCHAN_FLAG) 02279 ast_frame_dump(chan->name, f, "<<"); 02280 chan->fin = FRAMECOUNT_INC(chan->fin); 02281 02282 done: 02283 ast_channel_unlock(chan); 02284 return f; 02285 }
|
|
||||||||||||||||||||||||||||||||||||
|
Definition at line 2772 of file channel.c. References ast_channel::_state, outgoing_helper::account, ast_call(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_setapp(), ast_cdr_start(), ast_cdr_update(), ast_channel_inherit_variables(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, ast_frfree(), ast_hangup(), ast_log(), ast_read(), ast_request(), ast_set_callerid(), ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_waitfor(), ast_channel::cdr, outgoing_helper::cid_name, outgoing_helper::cid_num, outgoing_helper::context, ast_channel::context, outgoing_helper::exten, ast_channel::exten, ast_frame::frametype, ast_channel::hangupcause, LOG_NOTICE, outgoing_helper::parent_channel, outgoing_helper::priority, ast_channel::priority, ast_frame::subclass, and outgoing_helper::vars. Referenced by ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), and ast_request_and_dial(). 02773 { 02774 int dummy_outstate; 02775 int cause = 0; 02776 struct ast_channel *chan; 02777 int res = 0; 02778 02779 if (outstate) 02780 *outstate = 0; 02781 else 02782 outstate = &dummy_outstate; /* make outstate always a valid pointer */ 02783 02784 chan = ast_request(type, format, data, &cause); 02785 if (!chan) { 02786 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 02787 /* compute error and return */ 02788 if (cause == AST_CAUSE_BUSY) 02789 *outstate = AST_CONTROL_BUSY; 02790 else if (cause == AST_CAUSE_CONGESTION) 02791 *outstate = AST_CONTROL_CONGESTION; 02792 return NULL; 02793 } 02794 02795 if (oh) { 02796 if (oh->vars) 02797 ast_set_variables(chan, oh->vars); 02798 /* XXX why is this necessary, for the parent_channel perhaps ? */ 02799 if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) 02800 ast_set_callerid(chan, oh->cid_num, oh->cid_name, oh->cid_num); 02801 if (oh->parent_channel) 02802 ast_channel_inherit_variables(oh->parent_channel, chan); 02803 if (oh->account) 02804 ast_cdr_setaccount(chan, oh->account); 02805 } 02806 ast_set_callerid(chan, cid_num, cid_name, cid_num); 02807 02808 if (ast_call(chan, data, 0)) { /* ast_call failed... */ 02809 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data); 02810 } else { 02811 res = 1; /* mark success in case chan->_state is already AST_STATE_UP */ 02812 while (timeout && chan->_state != AST_STATE_UP) { 02813 struct ast_frame *f; 02814 res = ast_waitfor(chan, timeout); 02815 if (res <= 0) /* error, timeout, or done */ 02816 break; 02817 if (timeout > -1) 02818 timeout = res; 02819 f = ast_read(chan); 02820 if (!f) { 02821 *outstate = AST_CONTROL_HANGUP; 02822 res = 0; 02823 break; 02824 } 02825 if (f->frametype == AST_FRAME_CONTROL) { 02826 switch (f->subclass) { 02827 case AST_CONTROL_RINGING: /* record but keep going */ 02828 *outstate = f->subclass; 02829 break; 02830 02831 case AST_CONTROL_BUSY: 02832 case AST_CONTROL_CONGESTION: 02833 case AST_CONTROL_ANSWER: 02834 *outstate = f->subclass; 02835 timeout = 0; /* trick to force exit from the while() */ 02836 break; 02837 02838 /* Ignore these */ 02839 case AST_CONTROL_PROGRESS: 02840 case AST_CONTROL_PROCEEDING: 02841 case AST_CONTROL_HOLD: 02842 case AST_CONTROL_UNHOLD: 02843 case AST_CONTROL_VIDUPDATE: 02844 case -1: /* Ignore -- just stopping indications */ 02845 break; 02846 02847 default: 02848 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass); 02849 } 02850 } 02851 ast_frfree(f); 02852 } 02853 } 02854 02855 /* Final fixups */ 02856 if (oh) { 02857 if (!ast_strlen_zero(oh->context)) 02858 ast_copy_string(chan->context, oh->context, sizeof(chan->context)); 02859 if (!ast_strlen_zero(oh->exten)) 02860 ast_copy_string(chan->exten, oh->exten, sizeof(chan->exten)); 02861 if (oh->priority) 02862 chan->priority = oh->priority; 02863 } 02864 if (chan->_state == AST_STATE_UP) 02865 *outstate = AST_CONTROL_ANSWER; 02866 02867 if (res <= 0) { 02868 if (!chan->cdr && (chan->cdr = ast_cdr_alloc())) 02869 ast_cdr_init(chan->cdr, chan); 02870 if (chan->cdr) { 02871 char tmp[256]; 02872 snprintf(tmp, sizeof(tmp), "%s/%s", type, (char *)data); 02873 ast_cdr_setapp(chan->cdr,"Dial",tmp); 02874 ast_cdr_update(chan); 02875 ast_cdr_start(chan->cdr); 02876 ast_cdr_end(chan->cdr); 02877 /* If the cause wasn't handled properly */ 02878 if (ast_cdr_disposition(chan->cdr,chan->hangupcause)) 02879 ast_cdr_failed(chan->cdr); 02880 } 02881 ast_hangup(chan); 02882 chan = NULL; 02883 } 02884 return chan; 02885 }
|
|
||||||||||||||||
|
Activate a given generator Definition at line 1694 of file channel.c. References ast_generator::alloc, ast_channel_lock, ast_channel_unlock, ast_prod(), ast_settimeout(), ast_channel::generator, generator_force(), ast_channel::generatordata, and ast_generator::release. Referenced by ast_channel_start_silence_generator(), ast_linear_stream(), ast_playtones_start(), ast_tonepair_start(), and local_ast_moh_start(). 01695 { 01696 int res = 0; 01697 01698 ast_channel_lock(chan); 01699 01700 if (chan->generatordata) { 01701 if (chan->generator && chan->generator->release) 01702 chan->generator->release(chan, chan->generatordata); 01703 chan->generatordata = NULL; 01704 } 01705 01706 ast_prod(chan); 01707 if (gen->alloc && !(chan->generatordata = gen->alloc(chan, params))) { 01708 res = -1; 01709 } 01710 01711 if (!res) { 01712 ast_settimeout(chan, 160, generator_force, chan); 01713 chan->generator = gen; 01714 } 01715 01716 ast_channel_unlock(chan); 01717 01718 return res; 01719 }
|
|
|
returns number of active/allocated channels Returns number of active/allocated channels Definition at line 345 of file channel.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK. Referenced by quit_handler(). 00346 { 00347 struct ast_channel *c; 00348 int cnt = 0; 00349 AST_LIST_LOCK(&channels); 00350 AST_LIST_TRAVERSE(&channels, c, chan_list) 00351 cnt++; 00352 AST_LIST_UNLOCK(&channels); 00353 return cnt; 00354 }
|
|
|
Answer a channel.
Definition at line 1654 of file channel.c. References __ast_answer(). Referenced by __login_exec(), agi_exec_full(), ast_bridge_call(), ast_control_streamfile(), ast_pickup_call(), builtin_parkcall(), features_answer(), handle_answer(), park_call_exec(), park_exec(), and pbx_builtin_background(). 01655 { 01656 return __ast_answer(chan, 500); 01657 }
|
|
|
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 332 of file channel.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_softhangup(), AST_SOFTHANGUP_SHUTDOWN, and shutting_down. Referenced by quit_handler(). 00333 { 00334 struct ast_channel *c; 00335 shutting_down = 1; 00336 if (hangup) { 00337 AST_LIST_LOCK(&channels); 00338 AST_LIST_TRAVERSE(&channels, c, chan_list) 00339 ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN); 00340 AST_LIST_UNLOCK(&channels); 00341 } 00342 }
|
|
|
Pick the best audio 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 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 559 of file channel.c. References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_AUDIO_MASK, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G726_AAL2, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_ILBC, AST_FORMAT_LPC10, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, ast_log(), LOG_WARNING, and prefs. Referenced by __login_exec(), __oh323_new(), agent_call(), ast_iax2_new(), builtin_atxfer(), gtalk_new(), handle_open_receive_channel_ack_message(), iax2_request(), jingle_new(), local_new(), mgcp_new(), sip_new(), skinny_new(), socket_process(), and transmit_connect(). 00560 { 00561 /* This just our opinion, expressed in code. We are asked to choose 00562 the best codec to use, given no information */ 00563 int x; 00564 static int prefs[] = 00565 { 00566 /*! Okay, ulaw is used by all telephony equipment, so start with it */ 00567 AST_FORMAT_ULAW, 00568 /*! Unless of course, you're a silly European, so then prefer ALAW */ 00569 AST_FORMAT_ALAW, 00570 /*! Okay, well, signed linear is easy to translate into other stuff */ 00571 AST_FORMAT_SLINEAR, 00572 /*! G.726 is standard ADPCM, in RFC3551 packing order */ 00573 AST_FORMAT_G726, 00574 /*! G.726 is standard ADPCM, in AAL2 packing order */ 00575 AST_FORMAT_G726_AAL2, 00576 /*! ADPCM has great sound quality and is still pretty easy to translate */ 00577 AST_FORMAT_ADPCM, 00578 /*! Okay, we're down to vocoders now, so pick GSM because it's small and easier to 00579 translate and sounds pretty good */ 00580 AST_FORMAT_GSM, 00581 /*! iLBC is not too bad */ 00582 AST_FORMAT_ILBC, 00583 /*! Speex is free, but computationally more expensive than GSM */ 00584 AST_FORMAT_SPEEX, 00585 /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough 00586 to use it */ 00587 AST_FORMAT_LPC10, 00588 /*! G.729a is faster than 723 and slightly less expensive */ 00589 AST_FORMAT_G729A, 00590 /*! Down to G.723.1 which is proprietary but at least designed for voice */ 00591 AST_FORMAT_G723_1, 00592 }; 00593 00594 /* Strip out video */ 00595 fmts &= AST_FORMAT_AUDIO_MASK; 00596 00597 /* Find the first preferred codec in the format given */ 00598 for (x=0; x < (sizeof(prefs) / sizeof(prefs[0]) ); x++) 00599 if (fmts & prefs[x]) 00600 return prefs[x]; 00601 ast_log(LOG_WARNING, "Don't know any of 0x%x formats\n", fmts); 00602 return 0; 00603 }
|
|
|
Find bridged channel.
Definition at line 3589 of file channel.c. References ast_channel::_bridge, ast_channel_tech::bridged_channel, and ast_channel::tech. Referenced by __zt_exception(), agents_show(), agents_show_online(), ast_channel_masquerade(), attempt_transfer(), console_transfer(), create_jb(), handle_chanlist(), handle_hd_hf(), handle_invite_replaces(), handle_request(), handle_request_bye(), handle_request_info(), handle_request_invite(), handle_request_refer(), handle_response_answer(), handle_response_invite(), handle_showchan(), local_attended_transfer(), mgcp_hangup(), mgcp_ss(), schedule_delivery(), sip_read(), socket_process(), ss_thread(), zt_handle_event(), and zt_hangup(). 03590 { 03591 struct ast_channel *bridged; 03592 bridged = chan->_bridge; 03593 if (bridged && bridged->tech->bridged_channel) 03594 bridged = bridged->tech->bridged_channel(chan, bridged); 03595 return bridged; 03596 }
|
|
||||||||||||||||
|
Make a call.
Definition at line 2941 of file channel.c. References ast_channel_lock, ast_channel_unlock, ast_check_hangup(), AST_FLAG_OUTGOING, AST_FLAG_ZOMBIE, ast_set_flag, ast_test_flag, ast_channel_tech::call, and ast_channel::tech. Referenced by __ast_request_and_dial(), agent_call(), ast_feature_request_and_dial(), begin_dial(), and features_call(). 02942 { 02943 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 02944 If the remote end does not answer within the timeout, then do NOT hang up, but 02945 return anyway. */ 02946 int res = -1; 02947 /* Stop if we're a zombie or need a soft hangup */ 02948 ast_channel_lock(chan); 02949 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) { 02950 if (chan->tech->call) 02951 res = chan->tech->call(chan, addr, timeout); 02952 ast_set_flag(chan, AST_FLAG_OUTGOING); 02953 } 02954 ast_channel_unlock(chan); 02955 return res; 02956 }
|
|
|
Cancel a shutdown in progress. Cancels an existing shutdown and returns to normal operation Definition at line 357 of file channel.c. References shutting_down. Referenced by handle_abort_halt(). 00358 { 00359 shutting_down = 0; 00360 }
|
|
|
Gives the string form of a given hangup cause.
Definition at line 477 of file channel.c. Referenced by __transmit_response(), ast_hangup(), and transmit_request_with_auth(). 00478 { 00479 int x; 00480 00481 for (x=0; x < sizeof(causes) / sizeof(causes[0]); x++) { 00482 if (causes[x].cause == cause) 00483 return causes[x].desc; 00484 } 00485 00486 return "Unknown"; 00487 }
|
|
||||||||||||
|
Change channel name.
Definition at line 3162 of file channel.c. References ast_string_field_set, EVENT_FLAG_CALL, manager_event, and name. 03163 { 03164 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", chan->name, newname, chan->uniqueid); 03165 ast_string_field_set(chan, name, newname); 03166 }
|
|
||||||||||||||||||||||||||||
|
Create a channel structure.
Definition at line 611 of file channel.c. References ast_calloc, ast_log(), AST_MAX_FDS, ast_string_field_init, free, LOG_WARNING, sched_context_create(), and shutting_down. 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(), gtalk_new(), iax_park(), jingle_new(), local_new(), mgcp_new(), nbs_new(), oss_new(), phone_new(), sip_new(), sip_park(), and skinny_new(). 00612 { 00613 struct ast_channel *tmp; 00614 int x; 00615 int flags; 00616 struct varshead *headp; 00617 va_list ap1, ap2; 00618 00619 /* If shutting down, don't allocate any new channels */ 00620 if (shutting_down) { 00621 ast_log(LOG_WARNING, "Channel allocation failed: Refusing due to active shutdown\n"); 00622 return NULL; 00623 } 00624 00625 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) 00626 return NULL; 00627 00628 if (!(tmp->sched = sched_context_create())) { 00629 ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n"); 00630 free(tmp); 00631 return NULL; 00632 } 00633 00634 ast_string_field_init(tmp, 128); 00635 00636 /* Don't bother initializing the last two FD here, because they 00637 will *always* be set just a few lines down (AST_TIMING_FD, 00638 AST_ALERT_FD). */ 00639 for (x = 0; x < AST_MAX_FDS - 2; x++) 00640 tmp->fds[x] = -1; 00641 00642 #ifdef HAVE_ZAPTEL 00643 tmp->timingfd = open("/dev/zap/timer", O_RDWR); 00644 if (tmp->timingfd > -1) { 00645 /* Check if timing interface supports new 00646 ping/pong scheme */ 00647 flags = 1; 00648 if (!ioctl(tmp->timingfd, ZT_TIMERPONG, &flags)) 00649 needqueue = 0; 00650 } 00651 #else 00652 tmp->timingfd = -1; 00653 #endif 00654 00655 if (needqueue) { 00656 if (pipe(tmp->alertpipe)) { 00657 ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe!\n"); 00658 ast_string_field_free_pools(tmp); 00659 free(tmp); 00660 return NULL; 00661 } else { 00662 flags = fcntl(tmp->alertpipe[0], F_GETFL); 00663 fcntl(tmp->alertpipe[0], F_SETFL, flags | O_NONBLOCK); 00664 flags = fcntl(tmp->alertpipe[1], F_GETFL); 00665 fcntl(tmp->alertpipe[1], F_SETFL, flags | O_NONBLOCK); 00666 } 00667 } else /* Make sure we've got it done right if they don't */ 00668 tmp->alertpipe[0] = tmp->alertpipe[1] = -1; 00669 00670 /* Always watch the alertpipe */ 00671 tmp->fds[AST_ALERT_FD] = tmp->alertpipe[0]; 00672 /* And timing pipe */ 00673 tmp->fds[AST_TIMING_FD] = tmp->timingfd; 00674 ast_string_field_set(tmp, name, "**Unknown**"); 00675 00676 /* Initial state */ 00677 tmp->_state = state; 00678 00679 tmp->streamid = -1; 00680 00681 tmp->fin = global_fin; 00682 tmp->fout = global_fout; 00683 00684 if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) { 00685 ast_string_field_build(tmp, uniqueid, "%li.%d", (long) time(NULL), 00686 ast_atomic_fetchadd_int(&uniqueint, 1)); 00687 } else { 00688 ast_string_field_build(tmp, uniqueid, "%s-%li.%d", ast_config_AST_SYSTEM_NAME, 00689 (long) time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1)); 00690 } 00691 00692 if (!ast_strlen_zero(name_fmt)) { 00693 /* Almost every channel is calling this function, and setting the name via the ast_string_field_build() call. 00694 * And they all use slightly different formats for their name string. 00695 * This means, to set the name here, we have to accept variable args, and call the string_field_build from here. 00696 * This means, that the stringfields must have a routine that takes the va_lists directly, and 00697 * uses them to build the string, instead of forming the va_lists internally from the vararg ... list. 00698 * This new function was written so this can be accomplished. 00699 */ 00700 va_start(ap1, name_fmt); 00701 va_start(ap2, name_fmt); 00702 ast_string_field_build_va(tmp, name, name_fmt, ap1, ap2); 00703 va_end(ap1); 00704 va_end(ap2); 00705 00706 /* and now, since the channel structure is built, and has its name, let's call the 00707 * manager event generator with this Newchannel event. This is the proper and correct 00708 * place to make this call, but you sure do have to pass a lot of data into this func 00709 * to do it here! 00710 */ 00711 manager_event(EVENT_FLAG_CALL, "Newchannel", 00712 "Channel: %s\r\n" 00713 "State: %s\r\n" 00714 "CallerIDNum: %s\r\n" 00715 "CallerIDName: %s\r\n" 00716 "Uniqueid: %s\r\n", 00717 tmp->name, ast_state2str(state), 00718 S_OR(cid_num, "<unknown>"), 00719 S_OR(cid_name, "<unknown>"), 00720 tmp->uniqueid); 00721 } 00722 00723 headp = &tmp->varshead; 00724 AST_LIST_HEAD_INIT_NOLOCK(headp); 00725 00726 ast_mutex_init(&tmp->lock); 00727 00728 AST_LIST_HEAD_INIT_NOLOCK(&tmp->datastores); 00729 00730 strcpy(tmp->context, "default"); 00731 strcpy(tmp->exten, "s"); 00732 tmp->priority = 1; 00733 00734 ast_string_field_set(tmp, language, defaultlanguage); 00735 tmp->amaflags = ast_default_amaflags; 00736 ast_string_field_set(tmp, accountcode, ast_default_accountcode); 00737 00738 tmp->tech = &null_tech; 00739 00740 AST_LIST_LOCK(&channels); 00741 AST_LIST_INSERT_HEAD(&channels, tmp, chan_list); 00742 AST_LIST_UNLOCK(&channels); 00743 00744 return tmp; 00745 }
|
|
||||||||||||||||||||||||
|
Bridge two channels together. Bridge two channels together
Definition at line 3788 of file channel.c. References ast_channel::_bridge, AST_BRIDGE_COMPLETE, ast_check_hangup_locked(), AST_FEATURE_PLAY_WARNING, AST_FLAG_END_DTMF_ONLY, AST_FLAG_ZOMBIE, ast_log(), ast_set_flag, ast_test_flag, ast_tvadd(), ast_tvsub(), bridge_playfile(), ast_channel::cid, ast_callerid::cid_num, config, EVENT_FLAG_CALL, LOG_WARNING, manager_event, ast_channel::nativeformats, ast_channel_tech::send_digit_begin, and ast_channel::tech. Referenced by ast_bridge_call(). 03790 { 03791 struct ast_channel *who = NULL; 03792 enum ast_bridge_result res = AST_BRIDGE_COMPLETE; 03793 int nativefailed=0; 03794 int firstpass; 03795 int o0nativeformats; 03796 int o1nativeformats; 03797 long time_left_ms=0; 03798 struct timeval nexteventts = { 0, }; 03799 char caller_warning = 0; 03800 char callee_warning = 0; 03801 03802 if (c0->_bridge) { 03803 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 03804 c0->name, c0->_bridge->name); 03805 return -1; 03806 } 03807 if (c1->_bridge) { 03808 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 03809 c1->name, c1->_bridge->name); 03810 return -1; 03811 } 03812 03813 /* Stop if we're a zombie or need a soft hangup */ 03814 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) || 03815 ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) 03816 return -1; 03817 03818 *fo = NULL; 03819 firstpass = config->firstpass; 03820 config->firstpass = 0; 03821 03822 if (ast_tvzero(config->start_time)) 03823 config->start_time = ast_tvnow(); 03824 time_left_ms = config->timelimit; 03825 03826 caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING); 03827 callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING); 03828 03829 if (config->start_sound && firstpass) { 03830 if (caller_warning) 03831 bridge_playfile(c0, c1, config->start_sound, time_left_ms / 1000); 03832 if (callee_warning) 03833 bridge_playfile(c1, c0, config->start_sound, time_left_ms / 1000); 03834 } 03835 03836 /* Keep track of bridge */ 03837 c0->_bridge = c1; 03838 c1->_bridge = c0; 03839 03840 /* \todo XXX here should check that cid_num is not NULL */ 03841 manager_event(EVENT_FLAG_CALL, "Link", 03842 "Channel1: %s\r\n" 03843 "Channel2: %s\r\n" 03844 "Uniqueid1: %s\r\n" 03845 "Uniqueid2: %s\r\n" 03846 "CallerID1: %s\r\n" 03847 "CallerID2: %s\r\n", 03848 c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num); 03849 03850 o0nativeformats = c0->nativeformats; 03851 o1nativeformats = c1->nativeformats; 03852 03853 if (config->feature_timer) { 03854 nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->feature_timer, 1000)); 03855 } else if (config->timelimit) { 03856 nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000)); 03857 if (caller_warning || callee_warning) 03858 nexteventts = ast_tvsub(nexteventts, ast_samp2tv(config->play_warning, 1000)); 03859 } 03860 03861 if (!c0->tech->send_digit_begin) 03862 ast_set_flag(c1, AST_FLAG_END_DTMF_ONLY); 03863 if (!c1->tech->send_digit_begin) 03864 ast_set_flag(c0, AST_FLAG_END_DTMF_ONLY); 03865 03866 for (/* ever */;;) { 03867 struct timeval now = { 0, }; 03868 int to; 03869 03870 to = -1; 03871 03872 if (!ast_tvzero(nexteventts)) { 03873 now = ast_tvnow(); 03874 to = ast_tvdiff_ms(nexteventts, now); 03875 if (to <= 0) { 03876 if (!config->timelimit) { 03877 res = AST_BRIDGE_COMPLETE; 03878 break; 03879 } 03880 to = 0; 03881 } 03882 } 03883 03884 if (config->timelimit) { 03885 time_left_ms = config->timelimit - ast_tvdiff_ms(now, config->start_time); 03886 if (time_left_ms < to) 03887 to = time_left_ms; 03888 03889 if (time_left_ms <= 0) { 03890 if (caller_warning && config->end_sound) 03891 bridge_playfile(c0, c1, config->end_sound, 0); 03892 if (callee_warning && config->end_sound) 03893 bridge_playfile(c1, c0, config->end_sound, 0); 03894 *fo = NULL; 03895 if (who) 03896 *rc = who; 03897 res = 0; 03898 break; 03899 } 03900 03901 if (!to) { 03902 if (time_left_ms >= 5000 && config->warning_sound && config->play_warning) { 03903 int t = (time_left_ms + 500) / 1000; /* round to nearest second */ 03904 if (caller_warning) 03905 bridge_playfile(c0, c1, config->warning_sound, t); 03906 if (callee_warning) 03907 bridge_playfile(c1, c0, config->warning_sound, t); 03908 } 03909 if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000))) 03910 nexteventts = ast_tvadd(nexteventts, ast_samp2tv(config->warning_freq, 1000)); 03911 else 03912 nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000)); 03913 } 03914 } 03915 03916 if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) { 03917 if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE) 03918 c0->_softhangup = 0; 03919 if (c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) 03920 c1->_softhangup = 0; 03921 c0->_bridge = c1; 03922 c1->_bridge = c0; 03923 if (option_debug) 03924 ast_log(LOG_DEBUG, "Unbridge signal received. Ending native bridge.\n"); 03925 continue; 03926 } 03927 03928 /* Stop if we're a zombie or need a soft hangup */ 03929 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) || 03930 ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) { 03931 *fo = NULL; 03932 if (who) 03933 *rc = who; 03934 res = 0; 03935 if (option_debug) 03936 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", 03937 c0->name, c1->name, 03938 ast_test_flag(c0, AST_FLAG_ZOMBIE) ? "Yes" : "No", 03939 ast_check_hangup(c0) ? "Yes" : "No", 03940 ast_test_flag(c1, AST_FLAG_ZOMBIE) ? "Yes" : "No", 03941 ast_check_hangup(c1) ? "Yes" : "No"); 03942 break; 03943 } 03944 03945 if (c0->tech->bridge && 03946 (config->timelimit == 0) && 03947 (c0->tech->bridge == c1->tech->bridge) && 03948 !nativefailed && !c0->monitor && !c1->monitor && 03949 !c0->spies && !c1->spies && !ast_test_flag(&(config->features_callee),AST_FEATURE_REDIRECT) && 03950 !ast_test_flag(&(config->features_caller),AST_FEATURE_REDIRECT) ) { 03951 /* Looks like they share a bridge method and nothing else is in the way */ 03952 ast_set_flag(c0, AST_FLAG_NBRIDGE); 03953 ast_set_flag(c1, AST_FLAG_NBRIDGE); 03954 if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, to)) == AST_BRIDGE_COMPLETE) { 03955 /* \todo XXX here should check that cid_num is not NULL */ 03956 manager_event(EVENT_FLAG_CALL, "Unlink", 03957 "Channel1: %s\r\n" 03958 "Channel2: %s\r\n" 03959 "Uniqueid1: %s\r\n" 03960 "Uniqueid2: %s\r\n" 03961 "CallerID1: %s\r\n" 03962 "CallerID2: %s\r\n", 03963 c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num); 03964 if (option_debug) 03965 ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n", c0->name, c1->name); 03966 03967 ast_clear_flag(c0, AST_FLAG_NBRIDGE); 03968 ast_clear_flag(c1, AST_FLAG_NBRIDGE); 03969 03970 if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) 03971 continue; 03972 03973 c0->_bridge = NULL; 03974 c1->_bridge = NULL; 03975 03976 return res; 03977 } else { 03978 ast_clear_flag(c0, AST_FLAG_NBRIDGE); 03979 ast_clear_flag(c1, AST_FLAG_NBRIDGE); 03980 } 03981 switch (res) { 03982 case AST_BRIDGE_RETRY: 03983 continue; 03984 default: 03985 if (option_verbose > 2) 03986 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s ended\n", 03987 c0->name, c1->name); 03988 /* fallthrough */ 03989 case AST_BRIDGE_FAILED_NOWARN: 03990 nativefailed++; 03991 break; 03992 } 03993 } 03994 03995 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || 03996 (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) && 03997 !(c0->generator || c1->generator)) { 03998 if (ast_channel_make_compatible(c0, c1)) { 03999 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); 04000 /* \todo XXX here should check that cid_num is not NULL */ 04001 manager_event(EVENT_FLAG_CALL, "Unlink", 04002 "Channel1: %s\r\n" 04003 "Channel2: %s\r\n" 04004 "Uniqueid1: %s\r\n" 04005 "Uniqueid2: %s\r\n" 04006 "CallerID1: %s\r\n" 04007 "CallerID2: %s\r\n", 04008 c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num); 04009 return AST_BRIDGE_FAILED; 04010 } 04011 o0nativeformats = c0->nativeformats; 04012 o1nativeformats = c1->nativeformats; 04013 } 04014 res = ast_generic_bridge(c0, c1, config, fo, rc, nexteventts); 04015 if (res != AST_BRIDGE_RETRY) 04016 break; 04017 } 04018 04019 ast_clear_flag(c0, AST_FLAG_END_DTMF_ONLY); 04020 ast_clear_flag(c1, AST_FLAG_END_DTMF_ONLY); 04021 04022 c0->_bridge = NULL; 04023 c1->_bridge = NULL; 04024 04025 /* \todo XXX here should check that cid_num is not NULL */ 04026 manager_event(EVENT_FLAG_CALL, "Unlink", 04027 "Channel1: %s\r\n" 04028 "Channel2: %s\r\n" 04029 "Uniqueid1: %s\r\n" 04030 "Uniqueid2: %s\r\n" 04031 "CallerID1: %s\r\n" 04032 "CallerID2: %s\r\n", 04033 c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num); 04034 if (option_debug) 04035 ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n", c0->name, c1->name); 04036 04037 return res; 04038 }
|
|
||||||||||||
|
Compare a offset with the settings of when to hang a channel up.
Definition at line 377 of file channel.c. References ast_channel::whentohangup. 00378 { 00379 time_t whentohangup; 00380 00381 if (chan->whentohangup == 0) { 00382 return (offset == 0) ? 0 : -1; 00383 } else { 00384 if (offset == 0) /* XXX why is this special ? */ 00385 return (1); 00386 else { 00387 whentohangup = offset + time (NULL); 00388 if (chan->whentohangup < whentohangup) 00389 return (1); 00390 else if (chan->whentohangup == whentohangup) 00391 return (0); 00392 else 00393 return (-1); 00394 } 00395 } 00396 }
|
|
||||||||||||
|
Add a datastore to a channel.
Definition at line 1142 of file channel.c. References AST_LIST_INSERT_HEAD. 01143 { 01144 int res = 0; 01145 01146 AST_LIST_INSERT_HEAD(&chan->datastores, datastore, entry); 01147 01148 return res; 01149 }
|
|
||||||||||||
|
Create a channel datastore structure.
Definition at line 1098 of file channel.c. References ast_calloc, ast_strdup, and ast_datastore::info. 01099 { 01100 struct ast_datastore *datastore = NULL; 01101 01102 /* Make sure we at least have type so we can identify this */ 01103 if (info == NULL) { 01104 return NULL; 01105 } 01106 01107 /* Allocate memory for datastore and clear it */ 01108 datastore = ast_calloc(1, sizeof(*datastore)); 01109 if (datastore == NULL) { 01110 return NULL; 01111 } 01112 01113 datastore->info = info; 01114 01115 datastore->uid = ast_strdup(uid); 01116 01117 return datastore; 01118 }
|
|
||||||||||||||||
|
Find a datastore on a channel.
Definition at line 1169 of file channel.c. References AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_datastore::info, and ast_datastore::uid. 01170 { 01171 struct ast_datastore *datastore = NULL; 01172 01173 if (info == NULL) 01174 return NULL; 01175 01176 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->datastores, datastore, entry) { 01177 if (datastore->info == info) { 01178 if (uid != NULL && datastore->uid != NULL) { 01179 if (!strcasecmp(uid, datastore->uid)) { 01180 /* Matched by type AND uid */ 01181 break; 01182 } 01183 } else { 01184 /* Matched by type at least */ 01185 break; 01186 } 01187 } 01188 } 01189 AST_LIST_TRAVERSE_SAFE_END 01190 01191 return datastore; 01192 }
|
|
|
Free a channel datastore structure.
Definition at line 1120 of file channel.c. References ast_datastore::data, ast_datastore_info::destroy, free, ast_datastore::info, and ast_datastore::uid. Referenced by ast_channel_free(). 01121 { 01122 int res = 0; 01123 01124 /* Using the destroy function (if present) destroy the data */ 01125 if (datastore->info->destroy != NULL && datastore->data != NULL) { 01126 datastore->info->destroy(datastore->data); 01127 datastore->data = NULL; 01128 } 01129 01130 /* Free allocated UID memory */ 01131 if (datastore->uid != NULL) { 01132 free(datastore->uid); 01133 datastore->uid = NULL; 01134 } 01135 01136 /* Finally free memory used by ourselves */ 01137 free(datastore); 01138 01139 return res; 01140 }
|
|
||||||||||||
|
Remove a datastore from a channel.
Definition at line 1151 of file channel.c. References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, and AST_LIST_TRAVERSE_SAFE_END. 01152 { 01153 struct ast_datastore *datastore2 = NULL; 01154 int res = -1; 01155 01156 /* Find our position and remove ourselves */ 01157 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->datastores, datastore2, entry) { 01158 if (datastore2 == datastore) { 01159 AST_LIST_REMOVE_CURRENT(&chan->datastores, entry); 01160 res = 0; 01161 break; 01162 } 01163 } 01164 AST_LIST_TRAVERSE_SAFE_END 01165 01166 return res; 01167 }
|
|
|
Set defer DTMF flag on channel. 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 839 of file channel.c. References AST_FLAG_DEFER_DTMF, ast_set_flag, and ast_test_flag. Referenced by find_cache(). 00840 { 00841 int pre = 0; 00842 00843 if (chan) { 00844 pre = ast_test_flag(chan, AST_FLAG_DEFER_DTMF); 00845 ast_set_flag(chan, AST_FLAG_DEFER_DTMF); 00846 } 00847 return pre; 00848 }
|
|
||||||||||||
|
Bridge two channels together (early). Bridge two channels together (early)
Definition at line 3778 of file channel.c. References ast_channel_tech::early_bridge, and ast_channel::tech. 03779 { 03780 /* Make sure we can early bridge, if not error out */ 03781 if (!c0->tech->early_bridge || (c1 && (!c1->tech->early_bridge || c0->tech->early_bridge != c1->tech->early_bridge))) 03782 return -1; 03783 03784 return c0->tech->early_bridge(c0, c1); 03785 }
|
|
|
Free a channel structure.
Definition at line 1018 of file channel.c. References ast_channel::alertpipe, ast_channel_datastore_free(), ast_channel_lock, AST_CHANNEL_NAME, ast_channel_unlock, ast_channel_whisper_stop(), ast_device_state_changed_literal(), ast_frfree(), ast_jb_destroy(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_moh_cleanup(), ast_mutex_destroy(), ast_string_field_free_pools, ast_translator_free_path(), ast_var_delete(), ast_channel::cid, free, free_cid(), ast_channel::lock, LOG_WARNING, ast_channel::monitor, ast_channel::music_state, name, ast_channel::pbx, ast_channel::readtrans, ast_channel::sched, sched_context_destroy(), ast_channel_monitor::stop, ast_channel::tech_pvt, ast_channel::timingfd, ast_channel::varshead, ast_channel::whisper, and ast_channel::writetrans. Referenced by agent_cleanup(), agent_new(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), and local_new(). 01019 { 01020 int fd; 01021 struct ast_var_t *vardata; 01022 struct ast_frame *f; 01023 struct varshead *headp; 01024 struct ast_datastore *datastore = NULL; 01025 char name[AST_CHANNEL_NAME]; 01026 01027 headp=&chan->varshead; 01028 01029 AST_LIST_LOCK(&channels); 01030 AST_LIST_REMOVE(&channels, chan, chan_list); 01031 /* Lock and unlock the channel just to be sure nobody 01032 has it locked still */ 01033 ast_channel_lock(chan); 01034 ast_channel_unlock(chan); 01035 if (chan->tech_pvt) { 01036 ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name); 01037 free(chan->tech_pvt); 01038 } 01039 01040 if (chan->sched) 01041 sched_context_destroy(chan->sched); 01042 01043 ast_copy_string(name, chan->name, sizeof(name)); 01044 01045 /* Stop monitoring */ 01046 if (chan->monitor) 01047 chan->monitor->stop( chan, 0 ); 01048 01049 /* If there is native format music-on-hold state, free it */ 01050 if (chan->music_state) 01051 ast_moh_cleanup(chan); 01052 01053 /* if someone is whispering on the channel, stop them */ 01054 if (chan->whisper) 01055 ast_channel_whisper_stop(chan); 01056 01057 /* Free translators */ 01058 if (chan->readtrans) 01059 ast_translator_free_path(chan->readtrans); 01060 if (chan->writetrans) 01061 ast_translator_free_path(chan->writetrans); 01062 if (chan->pbx) 01063 ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name); 01064 free_cid(&chan->cid); 01065 ast_mutex_destroy(&chan->lock); 01066 /* Close pipes if appropriate */ 01067 if ((fd = chan->alertpipe[0]) > -1) 01068 close(fd); 01069 if ((fd = chan->alertpipe[1]) > -1) 01070 close(fd); 01071 if ((fd = chan->timingfd) > -1) 01072 close(fd); 01073 while ((f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list))) 01074 ast_frfree(f); 01075 01076 /* Get rid of each of the data stores on the channel */ 01077 while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry))) 01078 /* Free the data store */ 01079 ast_channel_datastore_free(datastore); 01080 AST_LIST_HEAD_INIT_NOLOCK(&chan->datastores); 01081 01082 /* loop over the variables list, freeing all data and deleting list items */ 01083 /* no need to lock the list, as the channel is already locked */ 01084 01085 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 01086 ast_var_delete(vardata); 01087 01088 /* Destroy the jitterbuffer */ 01089 ast_jb_destroy(chan); 01090 01091 ast_string_field_free_pools(chan); 01092 free(chan); 01093 AST_LIST_UNLOCK(&channels); 01094 01095 ast_device_state_changed_literal(name); 01096 }
|
|
||||||||||||
|
Inherits channel variable from parent to child channel.
Definition at line 3168 of file channel.c. References AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_var_assign(), ast_var_full_name(), ast_var_name(), ast_var_value(), LOG_DEBUG, option_debug, and ast_channel::varshead. Referenced by __ast_request_and_dial(), agent_call(), ast_feature_request_and_dial(), and begin_dial(). 03169 { 03170 struct ast_var_t *current, *newvar; 03171 const char *varname; 03172 03173 AST_LIST_TRAVERSE(&parent->varshead, current, entries) { 03174 int vartype = 0; 03175 03176 varname = ast_var_full_name(current); 03177 if (!varname) 03178 continue; 03179 03180 if (varname[0] == '_') { 03181 vartype = 1; 03182 if (varname[1] == '_') 03183 vartype = 2; 03184 } 03185 03186 switch (vartype) { 03187 case 1: 03188 newvar = ast_var_assign(&varname[1], ast_var_value(current)); 03189 if (newvar) { 03190 AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries); 03191 if (option_debug) 03192 ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n", ast_var_name(newvar)); 03193 } 03194 break; 03195 case 2: 03196 newvar = ast_var_assign(ast_var_full_name(current), ast_var_value(current)); 03197 if (newvar) { 03198 AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries); 03199 if (option_debug) 03200 ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n", ast_var_name(newvar)); 03201 } 03202 break; 03203 default: 03204 if (option_debug) 03205 ast_log(LOG_DEBUG, "Not copying variable %s.\n", ast_var_name(current)); 03206 break; 03207 } 03208 } 03209 }
|
|
||||||||||||
|
Makes two channel formats compatible.
Definition at line 3080 of file channel.c. References ast_channel_make_compatible_helper(). Referenced by check_compat(), and park_exec(). 03081 { 03082 /* Some callers do not check return code, and we must try to set all call legs correctly */ 03083 int rc = 0; 03084 03085 /* Set up translation from the chan to the peer */ 03086 rc = ast_channel_make_compatible_helper(chan, peer); 03087 03088 if (rc < 0) 03089 return rc; 03090 03091 /* Set up translation from the peer to the chan */ 03092 rc = ast_channel_make_compatible_helper(peer, chan); 03093 03094 return rc; 03095 }
|
|
||||||||||||
|
Set up translation from one channel to another.
Definition at line 3049 of file channel.c. References AST_FORMAT_SLINEAR, ast_log(), ast_opt_transcode_via_slin, ast_set_read_format(), ast_set_write_format(), ast_translate_path_steps(), ast_translator_best_choice(), LOG_WARNING, and ast_channel::nativeformats. Referenced by ast_channel_make_compatible(). 03050 { 03051 int src; 03052 int dst; 03053 03054 /* Set up translation from the 'from' channel to the 'to' channel */ 03055 src = from->nativeformats; 03056 dst = to->nativeformats; 03057 if (ast_translator_best_choice(&dst, &src) < 0) { 03058 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", from->name, src, to->name, dst); 03059 return -1; 03060 } 03061 03062 /* if the best path is not 'pass through', then 03063 transcoding is needed; if desired, force transcode path 03064 to use SLINEAR between channels, but only if there is 03065 no direct conversion available */ 03066 if ((src != dst) && ast_opt_transcode_via_slin && 03067 (ast_translate_path_steps(dst, src) != 1)) 03068 dst = AST_FORMAT_SLINEAR; 03069 if (ast_set_read_format(from, dst) < 0) { 03070 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", from->name, dst); 03071 return -1; 03072 } 03073 if (ast_set_write_format(to, dst) < 0) { 03074 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", to->name, dst); 03075 return -1; 03076 } 03077 return 0; 03078 }
|
|
||||||||||||
|
Weird function made for call transfers.
Definition at line 3097 of file channel.c. References ast_channel::_bridge, ast_bridged_channel(), ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), ast_null_frame, ast_queue_frame(), LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, and option_debug. Referenced by ast_async_goto(), ast_masq_park_call(), ast_pickup_call(), attempt_transfer(), builtin_atxfer(), check_availability(), check_bridge(), handle_invite_replaces(), iax_park(), misdn_transfer_bc(), and sip_park(). 03098 { 03099 int res = -1; 03100 struct ast_channel *final_orig = original, *final_clone = clone; 03101 03102 ast_channel_lock(original); 03103 while (ast_channel_trylock(clone)) { 03104 ast_channel_unlock(original); 03105 usleep(1); 03106 ast_channel_lock(original); 03107 } 03108 03109 /* each of these channels may be sitting behind a channel proxy (i.e. chan_agent) 03110 and if so, we don't really want to masquerade it, but its proxy */ 03111 if (original->_bridge && (original->_bridge != ast_bridged_channel(original))) 03112 final_orig = original->_bridge; 03113 03114 if (clone->_bridge && (clone->_bridge != ast_bridged_channel(clone))) 03115 final_clone = clone->_bridge; 03116 03117 if ((final_orig != original) || (final_clone != clone)) { 03118 ast_channel_lock(final_orig); 03119 while (ast_channel_trylock(final_clone)) { 03120 ast_channel_unlock(final_orig); 03121 usleep(1); 03122 ast_channel_lock(final_orig); 03123 } 03124 ast_channel_unlock(clone); 03125 ast_channel_unlock(original); 03126 original = final_orig; 03127 clone = final_clone; 03128 } 03129 03130 if (original == clone) { 03131 ast_log(LOG_WARNING, "Can't masquerade channel '%s' into itself!\n", original->name); 03132 ast_channel_unlock(clone); 03133 ast_channel_unlock(original); 03134 return -1; 03135 } 03136 03137 if (option_debug) 03138 ast_log(LOG_DEBUG, "Planning to masquerade channel %s into the structure of %s\n", 03139 clone->name, original->name); 03140 if (original->masq) { 03141 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 03142 original->masq->name, original->name); 03143 } else if (clone->masqr) { 03144 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 03145 clone->name, clone->masqr->name); 03146 } else { 03147 original->masq = clone; 03148 clone->masqr = original; 03149 ast_queue_frame(original, &ast_null_frame); 03150 ast_queue_frame(clone, &ast_null_frame); 03151 if (option_debug) 03152 ast_log(LOG_DEBUG, "Done planning to masquerade channel %s into the structure of %s\n", clone->name, original->name); 03153 res = 0; 03154 } 03155 03156 ast_channel_unlock(clone); 03157 ast_channel_unlock(original); 03158 03159 return res; 03160 }
|
|
|
Register a channel technology (a new channel driver) Called by a channel module to register the kind of channels it supports.
Definition at line 399 of file channel.c. References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_verbose(), LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, chanlist::tech, ast_channel_tech::type, and VERBOSE_PREFIX_2. Referenced by load_module(), and unload_module(). 00400 { 00401 struct chanlist *chan; 00402 00403 AST_LIST_LOCK(&channels); 00404 00405 AST_LIST_TRAVERSE(&backends, chan, list) { 00406 if (!strcasecmp(tech->type, chan->tech->type)) { 00407 ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", tech->type); 00408 AST_LIST_UNLOCK(&channels); 00409 return -1; 00410 } 00411 } 00412 00413 if (!(chan = ast_calloc(1, sizeof(*chan)))) { 00414 AST_LIST_UNLOCK(&channels); 00415 return -1; 00416 } 00417 chan->tech = tech; 00418 AST_LIST_INSERT_HEAD(&backends, chan, list); 00419 00420 if (option_debug) 00421 ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->tech->type, chan->tech->description); 00422 00423 if (option_verbose > 1) 00424 ast_verbose(VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->tech->type, 00425 chan->tech->description); 00426 00427 AST_LIST_UNLOCK(&channels); 00428 return 0; 00429 }
|
|
||||||||||||||||||||
|
Send HTML or URL on link. Returns 0 on success or -1 on failure Definition at line 3036 of file channel.c. References ast_channel_tech::send_html, and ast_channel::tech. Referenced by agent_sendhtml(), and ast_channel_sendurl(). 03037 { 03038 if (chan->tech->send_html) 03039 return chan->tech->send_html(chan, subclass, data, datalen); 03040 return -1; 03041 }
|
|
||||||||||||
|
Send URL on link. Returns 0 on success or -1 on failure Definition at line 3043 of file channel.c. References ast_channel_sendhtml(), and AST_HTML_URL. 03044 { 03045 return ast_channel_sendhtml(chan, AST_HTML_URL, url, strlen(url) + 1); 03046 }
|
|
||||||||||||||||||||||||
|
Sets an option on a channel.
Definition at line 4041 of file channel.c. References ast_log(), LOG_ERROR, ast_channel_tech::setoption, and ast_channel::tech. Referenced by ast_bridge_call(), handle_tddmode(), and zt_hangup(). 04042 { 04043 int res; 04044 04045 if (chan->tech->setoption) { 04046 res = chan->tech->setoption(chan, option, data, datalen); 04047 if (res < 0) 04048 return res; 04049 } else { 04050 errno = ENOSYS; 04051 return -1; 04052 } 04053 if (block) { 04054 /* XXX Implement blocking -- just wait for our option frame reply, discarding 04055 intermediate packets. XXX */ 04056 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 04057 return -1; 04058 } 04059 return 0; 04060 }
|
|
||||||||||||
|
Set when to hang a channel up.
Definition at line 369 of file channel.c. References ast_null_frame, ast_queue_frame(), and ast_channel::whentohangup. Referenced by action_timeout(). 00370 { 00371 chan->whentohangup = offset ? time(NULL) + offset : 0; 00372 ast_queue_frame(chan, &ast_null_frame); 00373 return; 00374 }
|
|
||||||||||||
|
Adds a spy to a channel, to begin receiving copies of the channel's audio frames.
Definition at line 1194 of file channel.c. References ast_calloc, ast_clear_flag, ast_cond_init(), AST_FORMAT_SLINEAR, ast_getformatname(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, ast_log(), ast_set_flag, ast_test_flag, ast_channel_spy::chan, CHANSPY_FORMAT_AUDIO, CHANSPY_MIXAUDIO, CHANSPY_READ_VOLADJUST, CHANSPY_TRIGGER_MODE, CHANSPY_TRIGGER_NONE, CHANSPY_TRIGGER_READ, CHANSPY_TRIGGER_WRITE, CHANSPY_WRITE_VOLADJUST, ast_channel_spy_queue::format, LOG_DEBUG, LOG_WARNING, option_debug, ast_channel_spy::read_queue, ast_channel::spies, ast_channel_spy::trigger, ast_channel_spy::type, and ast_channel_spy::write_queue. 01195 { 01196 /* Link the owner channel to the spy */ 01197 spy->chan = chan; 01198 01199 if (!ast_test_flag(spy, CHANSPY_FORMAT_AUDIO)) { 01200 ast_log(LOG_WARNING, "Could not add channel spy '%s' to channel '%s', only audio format spies are supported.\n", 01201 spy->type, chan->name); 01202 return -1; 01203 } 01204 01205 if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST) && (spy->read_queue.format != AST_FORMAT_SLINEAR)) { 01206 ast_log(LOG_WARNING, "Cannot provide volume adjustment on '%s' format spies\n", 01207 ast_getformatname(spy->read_queue.format)); 01208 return -1; 01209 } 01210 01211 if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST) && (spy->write_queue.format != AST_FORMAT_SLINEAR)) { 01212 ast_log(LOG_WARNING, "Cannot provide volume adjustment on '%s' format spies\n", 01213 ast_getformatname(spy->write_queue.format)); 01214 return -1; 01215 } 01216 01217 if (ast_test_flag(spy, CHANSPY_MIXAUDIO) && 01218 ((spy->read_queue.format != AST_FORMAT_SLINEAR) || 01219 (spy->write_queue.format != AST_FORMAT_SLINEAR))) { 01220 ast_log(LOG_WARNING, "Cannot provide audio mixing on '%s'-'%s' format spies\n", 01221 ast_getformatname(spy->read_queue.format), ast_getformatname(spy->write_queue.format)); 01222 return -1; 01223 } 01224 01225 if (!chan->spies) { 01226 if (!(chan->spies = ast_calloc(1, sizeof(*chan->spies)))) { 01227 return -1; 01228 } 01229 01230 AST_LIST_HEAD_INIT_NOLOCK(&chan->spies->list); 01231 AST_LIST_INSERT_HEAD(&chan->spies->list, spy, list); 01232 } else { 01233 AST_LIST_INSERT_TAIL(&chan->spies->list, spy, list); 01234 } 01235 01236 if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) { 01237 ast_cond_init(&spy->trigger, NULL); 01238 ast_set_flag(spy, CHANSPY_TRIGGER_READ); 01239 ast_clear_flag(spy, CHANSPY_TRIGGER_WRITE); 01240 } 01241 01242 if (option_debug) 01243 ast_log(LOG_DEBUG, "Spy %s added to channel %s\n", 01244 spy->type, chan->name); 01245 01246 return 0; 01247 }
|
|
|
Free a spy.
Definition at line 1329 of file channel.c. References ast_cond_destroy(), ast_frfree(), AST_LIST_REMOVE_HEAD, ast_mutex_destroy(), ast_test_flag, CHANSPY_DONE, CHANSPY_TRIGGER_MODE, CHANSPY_TRIGGER_NONE, ast_channel_spy::lock, ast_channel_spy::read_queue, ast_channel_spy::status, ast_channel_spy::trigger, and ast_channel_spy::write_queue. 01330 { 01331 struct ast_frame *f = NULL; 01332 01333 if (spy->status == CHANSPY_DONE) 01334 return; 01335 01336 /* Switch status to done in case we get called twice */ 01337 spy->status = CHANSPY_DONE; 01338 01339 /* Drop any frames in the queue */ 01340 while ((f = AST_LIST_REMOVE_HEAD(&spy->write_queue.list, frame_list))) 01341 ast_frfree(f); 01342 while ((f = AST_LIST_REMOVE_HEAD(&spy->read_queue.list, frame_list))) 01343 ast_frfree(f); 01344 01345 /* Destroy the condition if in use */ 01346 if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) 01347 ast_cond_destroy(&spy->trigger); 01348 01349 /* Destroy our mutex since it is no longer in use */ 01350 ast_mutex_destroy(&spy->lock); 01351 01352 return; 01353 }
|
|
||||||||||||
|
Read one (or more) frames of audio from a channel being spied upon.
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 4357 of file channel.c. References ast_clear_flag, ast_codec_get_len(), ast_frame_adjust_volume(), ast_frame_slinear_sum(), AST_FRAME_VOICE, ast_frdup(), ast_frfree(), AST_LIST_FIRST, AST_LIST_HEAD_SET_NOLOCK, AST_LIST_NEXT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, ast_test_flag, CHANSPY_MIXAUDIO, CHANSPY_READ_VOLADJUST, CHANSPY_TRIGGER_FLUSH, CHANSPY_WRITE_VOLADJUST, copy_data_from_queue(), ast_channel_spy_queue::format, ast_frame::frametype, ast_channel_spy::read_queue, ast_channel_spy::read_vol_adjustment, ast_channel_spy_queue::samples, ast_channel_spy::write_queue, and ast_channel_spy::write_vol_adjustment. 04358 { 04359 struct ast_frame *result; 04360 /* buffers are allocated to hold SLINEAR, which is the largest format */ 04361 short read_buf[samples]; 04362 short write_buf[samples]; 04363 struct ast_frame *read_frame; 04364 struct ast_frame *write_frame; 04365 int need_dup; 04366 struct ast_frame stack_read_frame = { .frametype = AST_FRAME_VOICE, 04367 .subclass = spy->read_queue.format, 04368 .data = read_buf, 04369 .samples = samples, 04370 .datalen = ast_codec_get_len(spy->read_queue.format, samples), 04371 }; 04372 struct ast_frame stack_write_frame = { .frametype = AST_FRAME_VOICE, 04373 .subclass = spy->write_queue.format, 04374 .data = write_buf, 04375 .samples = samples, 04376 .datalen = ast_codec_get_len(spy->write_queue.format, samples), 04377 }; 04378 04379 /* if a flush has been requested, dump everything in whichever queue is larger */ 04380 if (ast_test_flag(spy, CHANSPY_TRIGGER_FLUSH)) { 04381 if (spy->read_queue.samples > spy->write_queue.samples) { 04382 if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST)) { 04383 AST_LIST_TRAVERSE(&spy->read_queue.list, result, frame_list) 04384 ast_frame_adjust_volume(result, spy->read_vol_adjustment); 04385 } 04386 result = AST_LIST_FIRST(&spy->read_queue.list); 04387 AST_LIST_HEAD_SET_NOLOCK(&spy->read_queue.list, NULL); 04388 spy->read_queue.samples = 0; 04389 } else { 04390 if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST)) { 04391 AST_LIST_TRAVERSE(&spy->write_queue.list, result, frame_list) 04392 ast_frame_adjust_volume(result, spy->write_vol_adjustment); 04393 } 04394 result = AST_LIST_FIRST(&spy->write_queue.list); 04395 AST_LIST_HEAD_SET_NOLOCK(&spy->write_queue.list, NULL); 04396 spy->write_queue.samples = 0; 04397 } 04398 ast_clear_flag(spy, CHANSPY_TRIGGER_FLUSH); 04399 return result; 04400 } 04401 04402 if ((spy->read_queue.samples < samples) || (spy->write_queue.samples < samples)) 04403 return NULL; 04404 04405 /* short-circuit if both head frames have exactly what we want */ 04406 if ((AST_LIST_FIRST(&spy->read_queue.list)->samples == samples) && 04407 (AST_LIST_FIRST(&spy->write_queue.list)->samples == samples)) { 04408 read_frame = AST_LIST_REMOVE_HEAD(&spy->read_queue.list, frame_list); 04409 write_frame = AST_LIST_REMOVE_HEAD(&spy->write_queue.list, frame_list); 04410 04411 spy->read_queue.samples -= samples; 04412 spy->write_queue.samples -= samples; 04413 04414 need_dup = 0; 04415 } else { 04416 copy_data_from_queue(&spy->read_queue, read_buf, samples); 04417 copy_data_from_queue(&spy->write_queue, write_buf, samples); 04418 04419 read_frame = &stack_read_frame; 04420 write_frame = &stack_write_frame; 04421 need_dup = 1; 04422 } 04423 04424 if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST)) 04425 ast_frame_adjust_volume(read_frame, spy->read_vol_adjustment); 04426 04427 if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST)) 04428 ast_frame_adjust_volume(write_frame, spy->write_vol_adjustment); 04429 04430 if (ast_test_flag(spy, CHANSPY_MIXAUDIO)) { 04431 ast_frame_slinear_sum(read_frame, write_frame); 04432 04433 if (need_dup) 04434 result = ast_frdup(read_frame); 04435 else { 04436 result = read_frame; 04437 ast_frfree(write_frame); 04438 } 04439 } else { 04440 if (need_dup) { 04441 result = ast_frdup(read_frame); 04442 AST_LIST_NEXT(result, frame_list) = ast_frdup(write_frame); 04443 } else { 04444 result = read_frame; 04445 AST_LIST_NEXT(result, frame_list) = write_frame; 04446 } 04447 } 04448 04449 return result; 04450 }
|
|
||||||||||||
|
Remove a spy from a channel.
Definition at line 1319 of file channel.c. References AST_LIST_REMOVE, ast_channel::spies, spy_cleanup(), and spy_detach(). 01320 { 01321 if (!chan->spies) 01322 return; 01323 01324 AST_LIST_REMOVE(&chan->spies->list, spy, list); 01325 spy_detach(spy, chan); 01326 spy_cleanup(chan); 01327 }
|
|
||||||||||||
|
Find all spies of a particular type on a channel and stop them.
Definition at line 1287 of file channel.c. References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), ast_channel_spy::chan, CHANSPY_RUNNING, ast_channel_spy::lock, ast_channel::spies, spy_cleanup(), spy_detach(), ast_channel_spy::status, and ast_channel_spy::type. 01288 { 01289 struct ast_channel_spy *spy = NULL; 01290 01291 if (!chan->spies) 01292 return; 01293 01294 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->spies->list, spy, list) { 01295 ast_mutex_lock(&spy->lock); 01296 if ((spy->type == type) && (spy->status == CHANSPY_RUNNING)) { 01297 ast_mutex_unlock(&spy->lock); 01298 AST_LIST_REMOVE_CURRENT(&chan->spies->list, list); 01299 spy_detach(spy, chan); 01300 } else 01301 ast_mutex_unlock(&spy->lock); 01302 } 01303 AST_LIST_TRAVERSE_SAFE_END 01304 spy_cleanup(chan); 01305 }
|
|
|
Efficiently wait until audio is available for a spy, or an exception occurs.
Definition at line 1307 of file channel.c. References ast_cond_timedwait(), ast_tvadd(), ast_channel_spy::lock, and ast_channel_spy::trigger. 01308 { 01309 struct timeval tv; 01310 struct timespec ts; 01311 01312 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000)); 01313 ts.tv_sec = tv.tv_sec; 01314 ts.tv_nsec = tv.tv_usec * 1000; 01315 01316 ast_cond_timedwait(&spy->trigger, &spy->lock, &ts); 01317 }
|
|
|
Starts a silence generator on the given channel.
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 4489 of file channel.c. References ast_activate_generator(), ast_calloc, AST_FORMAT_SLINEAR, ast_log(), ast_set_write_format(), free, LOG_ERROR, ast_silence_generator::old_write_format, silence_generator, and ast_channel::writeformat. 04490 { 04491 struct ast_silence_generator *state; 04492 04493 if (!(state = ast_calloc(1, sizeof(*state)))) { 04494 return NULL; 04495 } 04496 04497 state->old_write_format = chan->writeformat; 04498 04499 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 04500 ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n"); 04501 free(state); 04502 return NULL; 04503 } 04504 04505 ast_activate_generator(chan, &silence_generator, state); 04506 04507 if (option_debug) 04508 ast_log(LOG_DEBUG, "Started silence generator on '%s'\n", chan->name); 04509 04510 return state; 04511 }
|
|
||||||||||||
|
Stops a previously-started silence generator on the given channel.
Definition at line 4513 of file channel.c. References ast_deactivate_generator(), ast_log(), ast_set_write_format(), free, LOG_ERROR, and ast_silence_generator::old_write_format. 04514 { 04515 if (!state) 04516 return; 04517 04518 ast_deactivate_generator(chan); 04519 04520 if (option_debug) 04521 ast_log(LOG_DEBUG, "Stopped silence generator on '%s'\n", chan->name); 04522 04523 if (ast_set_write_format(chan, state->old_write_format) < 0) 04524 ast_log(LOG_ERROR, "Could not return write format to its original state\n"); 04525 04526 free(state); 04527 }
|
|
|
Returns 0 if channel does not support HTML or non-zero if it does Definition at line 3031 of file channel.c. References ast_channel_tech::send_html, and ast_channel::tech.
|
|
|
Unset defer DTMF flag on channel. Undo defer. ast_read will return any dtmf characters that were queued Definition at line 851 of file channel.c. References ast_clear_flag, and AST_FLAG_DEFER_DTMF. Referenced by find_cache(). 00852 { 00853 if (chan) 00854 ast_clear_flag(chan, AST_FLAG_DEFER_DTMF); 00855 }
|
|
|
Unregister a channel technology.
Definition at line 431 of file channel.c. References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), free, LOG_DEBUG, option_debug, option_verbose, chanlist::tech, ast_channel_tech::type, and VERBOSE_PREFIX_2. Referenced by __unload_module(), and unload_module(). 00432 { 00433 struct chanlist *chan; 00434 00435 if (option_debug) 00436 ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", tech->type); 00437 00438 AST_LIST_LOCK(&channels); 00439 00440 AST_LIST_TRAVERSE_SAFE_BEGIN(&backends, chan, list) { 00441 if (chan->tech == tech) { 00442 AST_LIST_REMOVE_CURRENT(&backends, list); 00443 free(chan); 00444 if (option_verbose > 1) 00445 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", tech->type); 00446 break; 00447 } 00448 } 00449 AST_LIST_TRAVERSE_SAFE_END 00450 00451 AST_LIST_UNLOCK(&channels); 00452 }
|
|
|
Browse channels in use Browse the channels currently in use.
Definition at line 938 of file channel.c. References channel_find_locked(). Referenced by action_status(), ast_app_group_get_count(), ast_app_group_match_get_count(), ast_complete_channels(), ast_pickup_call(), complete_ch_helper(), group_show_channels(), handle_chanlist(), handle_core_set_debug_channel(), and moh_on_off(). 00939 { 00940 return channel_find_locked(prev, NULL, 0, NULL, NULL); 00941 }
|
|
||||||||||||
|
Feed an audio frame into the whisper buffer on a channel.
Definition at line 4732 of file channel.c. References ast_mutex_lock(), ast_mutex_unlock(), ast_slinfactory_feed(), ast_channel_whisper_buffer::lock, ast_channel_whisper_buffer::sf, and ast_channel::whisper. 04733 { 04734 if (!chan->whisper) 04735 return -1; 04736 04737 ast_mutex_lock(&chan->whisper->lock); 04738 ast_slinfactory_feed(&chan->whisper->sf, f); 04739 ast_mutex_unlock(&chan->whisper->lock); 04740 04741 return 0; 04742 }
|
|
|
Begin 'whispering' onto a channel.
Definition at line 4717 of file channel.c. References ast_calloc, AST_FLAG_WHISPER, ast_mutex_init(), ast_set_flag, ast_slinfactory_init(), ast_channel_whisper_buffer::lock, ast_channel_whisper_buffer::sf, and ast_channel::whisper. 04718 { 04719 if (chan->whisper) 04720 return -1; 04721 04722 if (!(chan->whisper = ast_calloc(1, sizeof(*chan->whisper)))) 04723 return -1; 04724 04725 ast_mutex_init(&chan->whisper->lock); 04726 ast_slinfactory_init(&chan->whisper->sf); 04727 ast_set_flag(chan, AST_FLAG_WHISPER); 04728 04729 return 0; 04730 }
|
|
|
Stop 'whispering' onto a channel.
Definition at line 4744 of file channel.c. References ast_clear_flag, AST_FLAG_WHISPER, AST_FORMAT_SLINEAR, ast_mutex_destroy(), ast_set_write_format(), ast_slinfactory_destroy(), ast_translator_free_path(), free, ast_channel_whisper_buffer::original_format, ast_channel_whisper_buffer::path, ast_channel::whisper, and ast_channel::writeformat. Referenced by ast_channel_free(). 04745 { 04746 if (!chan->whisper) 04747 return; 04748 04749 ast_clear_flag(chan, AST_FLAG_WHISPER); 04750 if (chan->whisper->path) 04751 ast_translator_free_path(chan->whisper->path); 04752 if (chan->whisper->original_format && chan->writeformat == AST_FORMAT_SLINEAR) 04753 ast_set_write_format(chan, chan->whisper->original_format); 04754 ast_slinfactory_destroy(&chan->whisper->sf); 04755 ast_mutex_destroy(&chan->whisper->lock); 04756 free(chan->whisper); 04757 chan->whisper = NULL; 04758 }
|
|
|
Provided by channel.c Definition at line 4290 of file channel.c. References ast_cli_register_multiple(), and cli_channel. 04291 { 04292 ast_cli_register_multiple(cli_channel, sizeof(cli_channel) / sizeof(struct ast_cli_entry)); 04293 }
|
|
|
return an ast_variable list of channeltypes
Definition at line 171 of file channel.c. References AST_LIST_TRAVERSE, ast_variable_new(), ast_channel_tech::description, chanlist::tech, ast_channel_tech::type, and var. 00172 { 00173 struct chanlist *cl; 00174 struct ast_variable *var=NULL, *prev = NULL; 00175 AST_LIST_TRAVERSE(&backends, cl, list) { 00176 if (prev) { 00177 if ((prev->next = ast_variable_new(cl->tech->type, cl->tech->description))) 00178 prev = prev->next; 00179 } else { 00180 var = ast_variable_new(cl->tech->type, cl->tech->description); 00181 prev = var; 00182 } 00183 } 00184 return var; 00185 }
|
|
|
Check to see if a channel is needing hang up.
Definition at line 308 of file channel.c. References ast_channel::_softhangup, AST_SOFTHANGUP_TIMEOUT, ast_channel::tech_pvt, and ast_channel::whentohangup. Referenced by __ast_answer(), __ast_read(), ast_call(), ast_check_hangup_locked(), ast_feature_request_and_dial(), ast_indicate_data(), ast_readstring_full(), ast_recvtext(), ast_sendtext(), ast_transfer(), ast_waitfordigit_full(), ast_write(), builtin_atxfer(), handle_sendimage(), and zt_setoption(). 00309 { 00310 if (chan->_softhangup) /* yes if soft hangup flag set */ 00311 return 1; 00312 if (!chan->tech_pvt) /* yes if no technology private data */ 00313 return 1; 00314 if (!chan->whentohangup) /* no if no hangup scheduled */ 00315 return 0; 00316 if (chan->whentohangup > time(NULL)) /* no if hangup time has not come yet. */ 00317 return 0; 00318 chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; /* record event */ 00319 return 1; 00320 }
|
|
|
Definition at line 322 of file channel.c. References ast_channel_lock, ast_channel_unlock, and ast_check_hangup(). Referenced by ast_channel_bridge(). 00323 { 00324 int res; 00325 ast_channel_lock(chan); 00326 res = ast_check_hangup(chan); 00327 ast_channel_unlock(chan); 00328 return res; 00329 }
|
|
|
Deactivate an active generator Definition at line 1659 of file channel.c. References ast_channel_lock, ast_channel_unlock, ast_clear_flag, AST_FLAG_WRITE_INT, AST_GENERATOR_FD, ast_settimeout(), ast_channel::fds, ast_channel::generator, ast_channel::generatordata, and ast_generator::release. Referenced by __ast_read(), ast_channel_stop_silence_generator(), ast_openstream_full(), ast_playtones_stop(), ast_quiet_chan(), ast_tonepair_stop(), ast_write(), generator_force(), local_ast_moh_stop(), and moh_on_off(). 01660 { 01661 ast_channel_lock(chan); 01662 if (chan->generatordata) { 01663 if (chan->generator && chan->generator->release) 01664 chan->generator->release(chan, chan->generatordata); 01665 chan->generatordata = NULL; 01666 chan->generator = NULL; 01667 chan->fds[AST_GENERATOR_FD] = -1; 01668 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 01669 ast_settimeout(chan, 0, NULL, NULL); 01670 } 01671 ast_channel_unlock(chan); 01672 }
|
|
|
Start masquerading a channel XXX This is a seriously whacked 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 3249 of file channel.c. References ast_channel::_state, ast_channel::alertpipe, ast_channel_lock, AST_LIST_FIRST, AST_LIST_HEAD_SET_NOLOCK, ast_log(), ast_state2str(), ast_string_field_set, EVENT_FLAG_CALL, free_translation(), ast_channel::lock, LOG_DEBUG, manager_event, ast_channel::masq, ast_channel::masqr, name, option_debug, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat. Referenced by __ast_read(), ast_async_goto(), ast_hangup(), ast_waitfor_nandfds(), ast_write(), iax_park(), sip_park(), and sip_park_thread(). 03250 { 03251 int x,i; 03252 int res=0; 03253 int origstate; 03254 struct ast_frame *cur; 03255 const struct ast_channel_tech *t; 03256 void *t_pvt; 03257 struct ast_callerid tmpcid; 03258 struct ast_channel *clone = original->masq; 03259 struct ast_channel_spy_list *spy_list = NULL; 03260 struct ast_channel_spy *spy = NULL; 03261 int rformat = original->readformat; 03262 int wformat = original->writeformat; 03263 char newn[100]; 03264 char orig[100]; 03265 char masqn[100]; 03266 char zombn[100]; 03267 03268 if (option_debug > 3) 03269 ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n", 03270 clone->name, clone->_state, original->name, original->_state); 03271 03272 manager_event(EVENT_FLAG_CALL, "Masquerade", "Clone: %s\r\nCloneState: %s\r\nOriginal: %s\r\nOriginalState: %s\r\n", 03273 clone->name, ast_state2str(clone->_state), original->name, ast_state2str(original->_state)); 03274 03275 /* XXX This is a seriously wacked out operation. We're essentially putting the guts of 03276 the clone channel into the original channel. Start by killing off the original 03277 channel's backend. I'm not sure we're going to keep this function, because 03278 while the features are nice, the cost is very high in terms of pure nastiness. XXX */ 03279 03280 /* We need the clone's lock, too */ 03281 ast_channel_lock(clone); 03282 03283 if (option_debug > 1) 03284 ast_log(LOG_DEBUG, "Got clone lock for masquerade on '%s' at %p\n", clone->name, &clone->lock); 03285 03286 /* Having remembered the original read/write formats, we turn off any translation on either 03287 one */ 03288 free_translation(clone); 03289 free_translation(original); 03290 03291 03292 /* Unlink the masquerade */ 03293 original->masq = NULL; 03294 clone->masqr = NULL; 03295 03296 /* Save the original name */ 03297 ast_copy_string(orig, original->name, sizeof(orig)); 03298 /* Save the new name */ 03299 ast_copy_string(newn, clone->name, sizeof(newn)); 03300 /* Create the masq name */ 03301 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn); 03302 03303 /* Copy the name from the clone channel */ 03304 ast_string_field_set(original, name, newn); 03305 03306 /* Mangle the name of the clone channel */ 03307 ast_string_field_set(clone, name, masqn); 03308 03309 /* Notify any managers of the change, first the masq then the other */ 03310 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid); 03311 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid); 03312 03313 /* Swap the technologies */ 03314 t = original->tech; 03315 original->tech = clone->tech; 03316 clone->tech = t; 03317 03318 t_pvt = original->tech_pvt; 03319 original->tech_pvt = clone->tech_pvt; 03320 clone->tech_pvt = t_pvt; 03321 03322 /* Swap the readq's */ 03323 cur = AST_LIST_FIRST(&original->readq); 03324 AST_LIST_HEAD_SET_NOLOCK(&original->readq, AST_LIST_FIRST(&clone->readq)); 03325 AST_LIST_HEAD_SET_NOLOCK(&clone->readq, cur); 03326 03327 /* Swap the alertpipes */ 03328 for (i = 0; i < 2; i++) { 03329 x = original->alertpipe[i]; 03330 original->alertpipe[i] = clone->alertpipe[i]; 03331 clone->alertpipe[i] = x; 03332 } 03333 03334 /* Swap the raw formats */ 03335 x = original->rawreadformat; 03336 original->rawreadformat = clone->rawreadformat; 03337 clone->rawreadformat = x; 03338 x = original->rawwriteformat; 03339 original->rawwriteformat = clone->rawwriteformat; 03340 clone->rawwriteformat = x; 03341 03342 /* Swap the spies */ 03343 spy_list = original->spies; 03344 original->spies = clone->spies; 03345 clone->spies = spy_list; 03346 03347 /* Update channel on respective spy lists if present */ 03348 if (original->spies) { 03349 AST_LIST_TRAVERSE(&original->spies->list, spy, list) { 03350 ast_mutex_lock(&spy->lock); 03351 spy->chan = original; 03352 ast_mutex_unlock(&spy->lock); 03353 } 03354 } 03355 if (clone->spies) { 03356 AST_LIST_TRAVERSE(&clone->spies->list, spy, list) { 03357 ast_mutex_lock(&spy->lock); 03358 spy->chan = clone; 03359 ast_mutex_unlock(&spy->lock); 03360 } 03361 } 03362 03363 /* Save any pending frames on both sides. Start by counting 03364 * how many we're going to need... */ 03365 x = 0; 03366 if (original->alertpipe[1] > -1) { 03367 AST_LIST_TRAVERSE(&clone->readq, cur, frame_list) 03368 x++; 03369 } 03370 03371 /* If we had any, prepend them to the ones already in the queue, and 03372 * load up the alertpipe */ 03373 if (AST_LIST_FIRST(&clone->readq)) { 03374 AST_LIST_INSERT_TAIL(&clone->readq, AST_LIST_FIRST(&original->readq), frame_list); 03375 AST_LIST_HEAD_SET_NOLOCK(&original->readq, AST_LIST_FIRST(&clone->readq)); 03376 AST_LIST_HEAD_SET_NOLOCK(&clone->readq, NULL); 03377 for (i = 0; i < x; i++) 03378 write(original->alertpipe[1], &x, sizeof(x)); 03379 } 03380 03381 clone->_softhangup = AST_SOFTHANGUP_DEV; 03382 03383 03384 /* And of course, so does our current state. Note we need not 03385 call ast_setstate since the event manager doesn't really consider 03386 these separate. We do this early so that the clone has the proper 03387 state of the original channel. */ 03388 origstate = original->_state; 03389 original->_state = clone->_state; 03390 clone->_state = origstate; 03391 03392 if (clone->tech->fixup){ 03393 res = clone->tech->fixup(original, clone); 03394 if (res) 03395 ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name); 03396 } 03397 03398 /* Start by disconnecting the original's physical side */ 03399 if (clone->tech->hangup) 03400 res = clone->tech->hangup(clone); 03401 if (res) { 03402 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n"); 03403 ast_channel_unlock(clone); 03404 return -1; 03405 } 03406 03407 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig); 03408 /* Mangle the name of the clone channel */ 03409 ast_string_field_set(clone, name, zombn); 03410 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid); 03411 03412 /* Update the type. */ 03413 t_pvt = original->monitor; 03414 original->monitor = clone->monitor; 03415 clone->monitor = t_pvt; 03416 03417 /* Keep the same language. */ 03418 ast_string_field_set(original, language, clone->language); 03419 /* Copy the FD's other than the generator fd */ 03420 for (x = 0; x < AST_MAX_FDS; x++) { 03421 if (x != AST_GENERATOR_FD) 03422 original->fds[x] = clone->fds[x]; 03423 } 03424 03425 /* move any whisperer over */ 03426 ast_channel_whisper_stop(original); 03427 if (ast_test_flag(clone, AST_FLAG_WHISPER)) { 03428 original->whisper = clone->whisper; 03429 ast_set_flag(original, AST_FLAG_WHISPER); 03430 clone->whisper = NULL; 03431 ast_clear_flag(clone, AST_FLAG_WHISPER); 03432 } 03433 03434 /* Move data stores over */ 03435 if (AST_LIST_FIRST(&clone->datastores)) 03436 AST_LIST_INSERT_TAIL(&original->datastores, AST_LIST_FIRST(&clone->datastores), entry); 03437 AST_LIST_HEAD_INIT_NOLOCK(&clone->datastores); 03438 03439 clone_variables(original, clone); 03440 AST_LIST_HEAD_INIT_NOLOCK(&clone->varshead); 03441 /* Presense of ADSI capable CPE follows clone */ 03442 original->adsicpe = clone->adsicpe; 03443 /* Bridge remains the same */ 03444 /* CDR fields remain the same */ 03445 /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */ 03446 /* Application and data remain the same */ 03447 /* Clone exception becomes real one, as with fdno */ 03448 ast_copy_flags(original, clone, AST_FLAG_EXCEPTION); 03449 original->fdno = clone->fdno; 03450 /* Schedule context remains the same */ 03451 /* Stream stuff stays the same */ 03452 /* Keep the original state. The fixup code will need to work with it most likely */ 03453 03454 /* Just swap the whole structures, nevermind the allocations, they'll work themselves 03455 out. */ 03456 tmpcid = original->cid; 03457 original->cid = clone->cid; 03458 clone->cid = tmpcid; 03459 03460 /* Restore original timing file descriptor */ 03461 original->fds[AST_TIMING_FD] = original->timingfd; 03462 03463 /* Our native formats are different now */ 03464 original->nativeformats = clone->nativeformats; 03465 03466 /* Context, extension, priority, app data, jump table, remain the same */ 03467 /* pvt switches. pbx stays the same, as does next */ 03468 03469 /* Set the write format */ 03470 ast_set_write_format(original, wformat); 03471 03472 /* Set the read format */ 03473 ast_set_read_format(original, rformat); 03474 03475 /* Copy the music class */ 03476 ast_string_field_set(original, musicclass, clone->musicclass); 03477 03478 if (option_debug) 03479 ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat); 03480 03481 /* Okay. Last thing is to let the channel driver know about all this mess, so he 03482 can fix up everything as best as possible */ 03483 if (original->tech->fixup) { 03484 res = original->tech->fixup(clone, original); 03485 if (res) { 03486 ast_log(LOG_WARNING, "Channel for type '%s' could not fixup channel %s\n", 03487 |