![]() |
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) |