Sat Nov 1 06:28:59 2008

Asterisk developer's documentation


channel.c File Reference

Channel Management. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <math.h>
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/audiohook.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_silence_generator
struct  chanlist
struct  tonepair_def
struct  tonepair_state

Defines

#define AST_DEFAULT_EMULATE_DTMF_DURATION   100
#define AST_MIN_DTMF_DURATION   80
#define AST_MIN_DTMF_GAP   45
#define FORMAT   "%-10.10s %-40.40s %-12.12s %-12.12s %-12.12s\n"
#define STATE2STR_BUFSIZE   32

Functions

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 ringing call.
void ast_begin_shutdown (int hangup)
 Initiate system shutdown.
int ast_best_codec (int fmts)
 Pick the best audio codec.
ast_channelast_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_channelast_channel_alloc (int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt,...)
 Create a 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_datastoreast_channel_datastore_alloc (const struct ast_datastore_info *info, char *uid)
 Create a channel datastore structure.
ast_datastoreast_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_inherit (struct ast_channel *from, struct ast_channel *to)
 Inherit datastores from a parent to a child.
int ast_channel_datastore_remove (struct ast_channel *chan, struct ast_datastore *datastore)
 Remove a datastore from a channel.
int ast_channel_defer_dtmf (struct ast_channel *chan)
 Set defer DTMF flag on channel.
void ast_channel_free (struct ast_channel *chan)
 Free a channel structure.
void ast_channel_inherit_variables (const struct ast_channel *parent, struct ast_channel *child)
 Inherits channel variable from parent to child channel.
int ast_channel_make_compatible (struct ast_channel *chan, struct ast_channel *peer)
 Makes two channel formats compatible.
int ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone)
 Weird function made for call transfers.
char * ast_channel_reason2str (int reason)
 return an english explanation of the code returned thru __ast_request_and_dial's 'outstate' argument
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.
ast_silence_generatorast_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_channelast_channel_walk_locked (const struct ast_channel *prev)
 Browse channels in use Browse the channels currently in use.
void ast_channels_init (void)
ast_variableast_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 wacked out operation. We're essentially putting the guts of the clone channel into the original channel. Start by killing off the original channel's backend. I'm not sure we're going to keep this function, because while the features are nice, the cost is very high in terms of pure nastiness. XXX.
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_channelast_get_channel_by_exten_locked (const char *exten, const char *context)
 Get channel by exten (and optionally context) and lock it.
ast_channelast_get_channel_by_name_locked (const char *name)
 Get channel by name (locks channel).
ast_channelast_get_channel_by_name_prefix_locked (const char *name, const int namelen)
 Get channel by name prefix (locks channel).
ast_channel_techast_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_frameast_read (struct ast_channel *chan)
 Reads a frame.
static void ast_read_generator_actions (struct ast_channel *chan, struct ast_frame *f)
ast_frameast_read_noaudio (struct ast_channel *chan)
 Reads a frame, returning AST_FRAME_NULL frame if audio. Read a frame.
int ast_readstring (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
int ast_readstring_full (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
int ast_recvchar (struct ast_channel *chan, int timeout)
 Receives a text character from a channel.
char * ast_recvtext (struct ast_channel *chan, int timeout)
 Receives a text string from a channel Read a string of text from a channel.
ast_channelast_request (const char *type, int format, void *data, int *cause)
 Requests a channel.
ast_channelast_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 specied amount of time, looking for hangups.
int ast_safe_sleep_conditional (struct ast_channel *chan, int ms, int(*cond)(void *), void *data)
 Wait for a specied amount of time, looking for hangups and a condition argument.
char * ast_safe_string_alloc (const char *fmt,...)
 printf the string into a correctly sized mallocd buffer, and return the buffer
int ast_say_character_str (struct ast_channel *chan, const char *str, const char *ints, const char *lang)
int ast_say_digit_str (struct ast_channel *chan, const char *str, const char *ints, const char *lang)
int ast_say_digits (struct ast_channel *chan, int num, const char *ints, const char *lang)
int ast_say_digits_full (struct ast_channel *chan, int num, const char *ints, const char *lang, int audiofd, int ctrlfd)
int ast_say_enumeration (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options)
int ast_say_number (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options)
int ast_say_phonetic_str (struct ast_channel *chan, const char *str, const char *ints, const char *lang)
int ast_senddigit (struct ast_channel *chan, char digit)
 Send a DTMF digit to a channel Send a DTMF digit to a channel.
int ast_senddigit_begin (struct ast_channel *chan, char digit)
int ast_senddigit_end (struct ast_channel *chan, char digit, unsigned int duration)
int ast_sendtext (struct ast_channel *chan, const char *text)
 Sends text to a channel Write text to a display on a channel.
void ast_set_callerid (struct ast_channel *chan, const char *callerid, const char *calleridname, const char *ani)
int ast_set_read_format (struct ast_channel *chan, int fmt)
 Sets read format on channel chan Set read format for channel to whichever component of "format" is best.
void ast_set_variables (struct ast_channel *chan, struct ast_variable *vars)
 adds a list of channel variables to a channel
int ast_set_write_format (struct ast_channel *chan, int fmt)
 Sets write format on channel chan Set write format for channel to whichever compoent of "format" is best.
int ast_setstate (struct ast_channel *chan, enum ast_channel_state state)
 Change the state of a channel.
int ast_settimeout (struct ast_channel *c, int samples, int(*func)(const 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).
char * ast_state2str (enum ast_channel_state state)
 Gives the string form of a given channel state.
int ast_str2cause (const char *name)
 Convert a symbolic hangup cause to number.
 AST_THREADSTORAGE (state2str_threadbuf, state2str_threadbuf_init)
int ast_tonepair (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
int ast_tonepair_start (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
void ast_tonepair_stop (struct ast_channel *chan)
int ast_transfer (struct ast_channel *chan, char *dest)
 Transfer a 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_channelast_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_channelast_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_channelast_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_channelast_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_channelchannel_find_locked (const struct ast_channel *prev, const char *name, const int namelen, const char *context, const char *exten)
 Helper function to find channels.
const char * channelreloadreason2txt (enum channelreloadreason reason)
 Convert enum channelreloadreason to text string for manager event.
static void clone_variables (struct ast_channel *original, struct ast_channel *clone)
 Clone channel variables from 'clone' channel into 'original' channel.
static char * complete_channeltypes (const char *line, const char *word, int pos, int state)
static char * complete_channeltypes_deprecated (const char *line, const char *word, int pos, int state)
static void free_cid (struct ast_callerid *cid)
static void free_translation (struct ast_channel *clone)
static int generator_force (const void *data)
static int set_format (struct ast_channel *chan, int fmt, int *rawformat, int *format, struct ast_trans_pvt **trans, const int direction)
static int show_channeltype (int fd, int argc, char *argv[])
static int show_channeltype_deprecated (int fd, int argc, char *argv[])
static int show_channeltypes (int fd, int argc, char *argv[])
static void * silence_generator_alloc (struct ast_channel *chan, void *data)
static int silence_generator_generate (struct ast_channel *chan, void *data, int len, int samples)
static void silence_generator_release (struct ast_channel *chan, void *data)
static void * 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
ast_cause causes []
static struct ast_cli_entry cli_channel []
static struct ast_cli_entry cli_show_channeltype_deprecated
static struct ast_cli_entry cli_show_channeltypes_deprecated
unsigned long global_fin
unsigned long global_fout
static struct ast_channel_tech null_tech
static char show_channeltype_usage []
static char show_channeltypes_usage []
static int shutting_down
static struct ast_generator silence_generator
static struct ast_generator tonepair
static int uniqueint


Detailed Description

Channel Management.

Author:
Mark Spencer <markster@digium.com>

Definition in file channel.c.


Define Documentation

#define AST_DEFAULT_EMULATE_DTMF_DURATION   100

Default amount of time to use when emulating a digit as a begin and end 100ms

Definition at line 91 of file channel.c.

Referenced by __ast_read(), and ast_senddigit().

#define AST_MIN_DTMF_DURATION   80

Minimum allowed digit length - 80ms

Definition at line 94 of file channel.c.

Referenced by __ast_read().

#define AST_MIN_DTMF_GAP   45

Minimum amount of time between the end of the last digit and the beginning of a new one - 45ms

Definition at line 98 of file channel.c.

Referenced by __ast_read().

#define FORMAT   "%-10.10s %-40.40s %-12.12s %-12.12s %-12.12s\n"

#define STATE2STR_BUFSIZE   32

Definition at line 87 of file channel.c.

Referenced by ast_state2str().


Function Documentation

static struct ast_frame* __ast_read ( struct ast_channel chan,
int  dropaudio 
) [static]

Definition at line 1968 of file channel.c.

References ast_channel::_softhangup, ast_channel::_state, ast_channel::alertpipe, AST_AUDIOHOOK_DIRECTION_READ, ast_audiohook_write_list(), ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_HANGUP, ast_deactivate_generator(), AST_DEFAULT_EMULATE_DTMF_DURATION, ast_do_masquerade(), AST_FLAG_DEFER_DTMF, AST_FLAG_EMULATE_DTMF, AST_FLAG_END_DTMF_ONLY, AST_FLAG_EXCEPTION, AST_FLAG_IN_DTMF, AST_FLAG_OUTGOING, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frame_dump(), AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree, AST_GENERATOR_FD, ast_getformatname(), ast_getformatname_multiple(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_SET_NOLOCK, AST_LIST_NEXT, AST_LIST_REMOVE_HEAD, ast_log(), AST_MIN_DTMF_DURATION, AST_MIN_DTMF_GAP, AST_MONITOR_RUNNING, ast_null_frame, ast_read_generator_actions(), ast_seekstream(), ast_set_flag, ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_strlen_zero(), ast_test_flag, AST_TIMING_FD, ast_translate(), ast_writestream(), ast_channel::audiohooks, ast_channel::blocker, ast_frame::data, DEBUGCHAN_FLAG, ast_channel::dtmf_tv, ast_channel::dtmff, ast_channel::dtmfq, ast_channel::emulate_dtmf_digit, ast_channel::emulate_dtmf_duration, errno, ast_channel_tech::exception, f, ast_channel::fdno, ast_channel::fds, ast_channel::fin, ast_frame::flags, FRAMECOUNT_INC, ast_frame::frametype, func, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, ast_channel::insmpl, LOG_DEBUG, LOG_DTMF, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::masq, ast_channel::monitor, ast_channel::nativeformats, option_debug, ast_channel::outsmpl, ast_channel_tech::read, ast_channel_monitor::read_stream, ast_channel::readtrans, SEEK_FORCECUR, 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().

01969 {
01970    struct ast_frame *f = NULL;   /* the return value */
01971    int blah;
01972    int prestate;
01973    int count = 0;
01974 
01975    /* this function is very long so make sure there is only one return
01976     * point at the end (there are only two exceptions to this).
01977     */
01978    while(ast_channel_trylock(chan)) {
01979       if(count++ > 10) 
01980          /*cannot goto done since the channel is not locked*/
01981          return &ast_null_frame;
01982       usleep(1);
01983    }
01984 
01985    if (chan->masq) {
01986       if (ast_do_masquerade(chan))
01987          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01988       else
01989          f =  &ast_null_frame;
01990       goto done;
01991    }
01992 
01993    /* Stop if we're a zombie or need a soft hangup */
01994    if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
01995       if (chan->generator)
01996          ast_deactivate_generator(chan);
01997       goto done;
01998    }
01999    prestate = chan->_state;
02000 
02001    if (!ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF | AST_FLAG_IN_DTMF) && 
02002        !ast_strlen_zero(chan->dtmfq) && 
02003       (ast_tvzero(chan->dtmf_tv) || ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) > AST_MIN_DTMF_GAP) ) {
02004       /* We have DTMF that has been deferred.  Return it now */
02005       chan->dtmff.subclass = chan->dtmfq[0];
02006       /* Drop first digit from the buffer */
02007       memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
02008       f = &chan->dtmff;
02009       if (ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) {
02010          ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass, chan->name);
02011          chan->dtmff.frametype = AST_FRAME_DTMF_END;
02012       } else {
02013          ast_log(LOG_DTMF, "DTMF begin emulation of '%c' with duration %d queued on %s\n", f->subclass, AST_DEFAULT_EMULATE_DTMF_DURATION, chan->name);
02014          chan->dtmff.frametype = AST_FRAME_DTMF_BEGIN;
02015          ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
02016          chan->emulate_dtmf_digit = f->subclass;
02017          chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
02018       }
02019       chan->dtmf_tv = ast_tvnow();
02020       goto done;
02021    }
02022    
02023    /* Read and ignore anything on the alertpipe, but read only
02024       one sizeof(blah) per frame that we send from it */
02025    if (chan->alertpipe[0] > -1) {
02026       int flags = fcntl(chan->alertpipe[0], F_GETFL);
02027       /* For some odd reason, the alertpipe occasionally loses nonblocking status,
02028        * which immediately causes a deadlock scenario.  Detect and prevent this. */
02029       if ((flags & O_NONBLOCK) == 0) {
02030          ast_log(LOG_ERROR, "Alertpipe on channel %s lost O_NONBLOCK?!!\n", chan->name);
02031          if (fcntl(chan->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
02032             ast_log(LOG_WARNING, "Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
02033             f = &ast_null_frame;
02034             goto done;
02035          }
02036       }
02037       read(chan->alertpipe[0], &blah, sizeof(blah));
02038    }
02039 
02040 #ifdef HAVE_DAHDI
02041    if (chan->timingfd > -1 && chan->fdno == AST_TIMING_FD && ast_test_flag(chan, AST_FLAG_EXCEPTION)) {
02042       int res;
02043 
02044       ast_clear_flag(chan, AST_FLAG_EXCEPTION);
02045       blah = -1;
02046       /* IF we can't get event, assume it's an expired as-per the old interface */
02047       res = ioctl(chan->timingfd, DAHDI_GETEVENT, &blah);
02048       if (res)
02049          blah = DAHDI_EVENT_TIMER_EXPIRED;
02050 
02051       if (blah == DAHDI_EVENT_TIMER_PING) {
02052          if (AST_LIST_EMPTY(&chan->readq) || !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) {
02053             /* Acknowledge PONG unless we need it again */
02054             if (ioctl(chan->timingfd, DAHDI_TIMERPONG, &blah)) {
02055                ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno));
02056             }
02057          }
02058       } else if (blah == DAHDI_EVENT_TIMER_EXPIRED) {
02059          ioctl(chan->timingfd, DAHDI_TIMERACK, &blah);
02060          if (chan->timingfunc) {
02061             /* save a copy of func/data before unlocking the channel */
02062             int (*func)(const void *) = chan->timingfunc;
02063             void *data = chan->timingdata;
02064             ast_channel_unlock(chan);
02065             func(data);
02066          } else {
02067             blah = 0;
02068             ioctl(chan->timingfd, DAHDI_TIMERCONFIG, &blah);
02069             chan->timingdata = NULL;
02070             ast_channel_unlock(chan);
02071          }
02072          /* cannot 'goto done' because the channel is already unlocked */
02073          return &ast_null_frame;
02074       } else
02075          ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
02076    } else
02077 #endif
02078    if (chan->fds[AST_GENERATOR_FD] > -1 && chan->fdno == AST_GENERATOR_FD) {
02079       /* if the AST_GENERATOR_FD is set, call the generator with args
02080        * set to -1 so it can do whatever it needs to.
02081        */
02082       void *tmp = chan->generatordata;
02083       chan->generatordata = NULL;     /* reset to let ast_write get through */
02084       chan->generator->generate(chan, tmp, -1, -1);
02085       chan->generatordata = tmp;
02086       f = &ast_null_frame;
02087       goto done;
02088    }
02089 
02090    /* Check for pending read queue */
02091    if (!AST_LIST_EMPTY(&chan->readq)) {
02092       f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list);
02093       /* Interpret hangup and return NULL */
02094       /* XXX why not the same for frames from the channel ? */
02095       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
02096          ast_frfree(f);
02097          f = NULL;
02098       }
02099    } else {
02100       chan->blocker = pthread_self();
02101       if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) {
02102          if (chan->tech->exception)
02103             f = chan->tech->exception(chan);
02104          else {
02105             ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
02106             f = &ast_null_frame;
02107          }
02108          /* Clear the exception flag */
02109          ast_clear_flag(chan, AST_FLAG_EXCEPTION);
02110       } else if (chan->tech->read)
02111          f = chan->tech->read(chan);
02112       else
02113          ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
02114    }
02115 
02116    if (f) {
02117       /* if the channel driver returned more than one frame, stuff the excess
02118          into the readq for the next ast_read call (note that we can safely assume
02119          that the readq is empty, because otherwise we would not have called into
02120          the channel driver and f would be only a single frame)
02121       */
02122       if (AST_LIST_NEXT(f, frame_list)) {
02123          AST_LIST_HEAD_SET_NOLOCK(&chan->readq, AST_LIST_NEXT(f, frame_list));
02124          AST_LIST_NEXT(f, frame_list) = NULL;
02125       }
02126 
02127       switch (f->frametype) {
02128       case AST_FRAME_CONTROL:
02129          if (f->subclass == AST_CONTROL_ANSWER) {
02130             if (!ast_test_flag(chan, AST_FLAG_OUTGOING)) {
02131                if (option_debug)
02132                   ast_log(LOG_DEBUG, "Ignoring answer on an inbound call!\n");
02133                ast_frfree(f);
02134                f = &ast_null_frame;
02135             } else if (prestate == AST_STATE_UP) {
02136                if (option_debug)
02137                   ast_log(LOG_DEBUG, "Dropping duplicate answer!\n");
02138                ast_frfree(f);
02139                f = &ast_null_frame;
02140             } else {
02141                /* Answer the CDR */
02142                ast_setstate(chan, AST_STATE_UP);
02143                /* removed a call to ast_cdr_answer(chan->cdr) from here. */
02144             }
02145          }
02146          break;
02147       case AST_FRAME_DTMF_END:
02148          ast_log(LOG_DTMF, "DTMF end '%c' received on %s, duration %ld ms\n", f->subclass, chan->name, f->len);
02149          /* Queue it up if DTMF is deffered, or if DTMF emulation is forced.
02150           * However, only let emulation be forced if the other end cares about BEGIN frames */
02151          if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF) ||
02152             (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) ) {
02153             if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) {
02154                ast_log(LOG_DTMF, "DTMF end '%c' put into dtmf queue on %s\n", f->subclass, chan->name);
02155                chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
02156             } else
02157                ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
02158             ast_frfree(f);
02159             f = &ast_null_frame;
02160          } else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) {
02161             if (!ast_tvzero(chan->dtmf_tv) && 
02162                 ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) {
02163                /* If it hasn't been long enough, defer this digit */
02164                if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2) {
02165                   ast_log(LOG_DTMF, "DTMF end '%c' put into dtmf queue on %s\n", f->subclass, chan->name);
02166                   chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
02167                } else
02168                   ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
02169                ast_frfree(f);
02170                f = &ast_null_frame;
02171             } else {
02172                /* There was no begin, turn this into a begin and send the end later */
02173                f->frametype = AST_FRAME_DTMF_BEGIN;
02174                ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
02175                chan->emulate_dtmf_digit = f->subclass;
02176                chan->dtmf_tv = ast_tvnow();
02177                if (f->len) {
02178                   if (f->len > AST_MIN_DTMF_DURATION)
02179                      chan->emulate_dtmf_duration = f->len;
02180                   else 
02181                      chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION;
02182                } else
02183                   chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
02184                ast_log(LOG_DTMF, "DTMF begin emulation of '%c' with duration %u queued on %s\n", f->subclass, chan->emulate_dtmf_duration, chan->name);
02185             }
02186             if (chan->audiohooks) {
02187                struct ast_frame *old_frame = f;
02188                f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f);
02189                if (old_frame != f)
02190                   ast_frfree(old_frame);
02191                                 }
02192          } else {
02193             struct timeval now = ast_tvnow();
02194             if (ast_test_flag(chan,