channel.h File Reference

#include <asterisk/frame.h>
#include <asterisk/sched.h>
#include <asterisk/chanvars.h>
#include <unistd.h>
#include <setjmp.h>
#include <sys/poll.h>
#include <asterisk/lock.h>
#include <asterisk/cdr.h>
#include <asterisk/monitor.h>

Include dependency graph for channel.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_generator
struct  ast_channel
 Main Channel structure associated with a channel. More...
struct  ast_bridge_config
struct  outgoing_helper

Defines

#define AST_MAX_EXTENSION   80
 Max length of an extension.
#define AST_CHANNEL_NAME   80
#define AST_CHANNEL_MAX_STACK   32
#define MAX_LANGUAGE   20
#define AST_MAX_FDS   8
#define AST_FLAG_DIGITAL   1
#define LOAD_OH(oh)
#define AST_CDR_TRANSFER   (1 << 0)
#define AST_CDR_FORWARD   (1 << 1)
#define AST_CDR_CALLWAIT   (1 << 2)
#define AST_CDR_CONFERENCE   (1 << 3)
#define AST_ADSI_UNKNOWN   (0)
#define AST_ADSI_AVAILABLE   (1)
#define AST_ADSI_UNAVAILABLE   (2)
#define AST_ADSI_OFFHOOKONLY   (3)
#define AST_SOFTHANGUP_DEV   (1 << 0)
#define AST_SOFTHANGUP_ASYNCGOTO   (1 << 1)
#define AST_SOFTHANGUP_SHUTDOWN   (1 << 2)
#define AST_SOFTHANGUP_TIMEOUT   (1 << 3)
#define AST_SOFTHANGUP_APPUNLOAD   (1 << 4)
#define AST_SOFTHANGUP_EXPLICIT   (1 << 5)
#define AST_STATE_DOWN   0
#define AST_STATE_RESERVED   1
#define AST_STATE_OFFHOOK   2
#define AST_STATE_DIALING   3
#define AST_STATE_RING   4
#define AST_STATE_RINGING   5
#define AST_STATE_UP   6
#define AST_STATE_BUSY   7
#define AST_STATE_DIALING_OFFHOOK   8
#define AST_STATE_PRERING   9
#define AST_STATE_MUTE   (1 << 16)
#define AST_DEVICE_UNKNOWN   0
#define AST_DEVICE_NOT_INUSE   1
#define AST_DEVICE_INUSE   2
#define AST_DEVICE_BUSY   3
#define AST_DEVICE_INVALID   4
#define AST_DEVICE_UNAVAILABLE   5
#define AST_BRIDGE_DTMF_CHANNEL_0   (1 << 0)
#define AST_BRIDGE_DTMF_CHANNEL_1   (1 << 1)
#define AST_BRIDGE_REC_CHANNEL_0   (1 << 2)
#define AST_BRIDGE_REC_CHANNEL_1   (1 << 3)
#define AST_BRIDGE_IGNORE_SIGS   (1 << 4)
#define CRASH   do { } while(0)
#define CHECK_BLOCKING(c)

Functions

struct ast_channelast_request (char *type, int format, void *data)
 Requests a channel.
int ast_parse_device_state (char *device)
 Search the Channels by Name.
int ast_device_state (char *device)
 Asks a channel for device state.
struct ast_channelast_request_and_dial (char *type, int format, void *data, int timeout, int *reason, char *callerid)
struct ast_channel__ast_request_and_dial (char *type, int format, void *data, int timeout, int *reason, char *callerid, struct outgoing_helper *oh)
int ast_channel_register (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data))
 Registers a channel.
int ast_channel_register_ex (char *type, char *description, int capabilities, struct ast_channel *(*requester)(char *type, int format, void *data), int(*devicestate)(void *data))
void ast_channel_unregister (char *type)
 Unregister a channel class.
int ast_hangup (struct ast_channel *chan)
 Hang up a channel.
int ast_softhangup (struct ast_channel *chan, int cause)
 Softly hangup up a channel.
int ast_softhangup_nolock (struct ast_channel *chan, int cause)
int ast_check_hangup (struct ast_channel *chan)
 Check to see if a channel is needing hang up.
void ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset)
 Set when to hang a channel up.
int ast_answer (struct ast_channel *chan)
 Answer a ringing call.
int ast_call (struct ast_channel *chan, char *addr, int timeout)
 Make a call.
int ast_indicate (struct ast_channel *chan, int condition)
 Indicates condition of channel.
int ast_waitfor (struct ast_channel *chan, int ms)
 Wait for input on a channel.
int ast_safe_sleep (struct ast_channel *chan, int ms)
 Wait for a specied amount of time, looking for hangups.
int ast_safe_sleep_conditional (struct ast_channel *chan, int ms, int(*cond)(void *), void *data)
 Wait for a specied amount of time, looking for hangups and a condition argument.
struct ast_channelast_waitfor_nandfds (struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
 Waits for activity on a group of channels.
struct ast_channelast_waitfor_n (struct ast_channel **chan, int n, int *ms)
 Waits for input on a group of channels.
int ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception)
 Waits for input on an fd.
struct ast_frameast_read (struct ast_channel *chan)
 Reads a frame.
int ast_write (struct ast_channel *chan, struct ast_frame *frame)
 Write a frame to a channel.
int ast_write_video (struct ast_channel *chan, struct ast_frame *frame)
 Write video frame to a channel.
int ast_prod (struct ast_channel *chan)
int ast_set_read_format (struct ast_channel *chan, int format)
 Sets read format on channel chan.
int ast_set_write_format (struct ast_channel *chan, int format)
 Sets write format on channel chan.
int ast_sendtext (struct ast_channel *chan, char *text)
 Sends text to a channel.
int ast_senddigit (struct ast_channel *chan, char digit)
 Receives a text character from a channel.
int ast_recvchar (struct ast_channel *chan, int timeout)
struct ast_channelast_channel_walk_locked (struct ast_channel *prev)
 Browse channels in use.
struct ast_channelast_get_channel_by_name_locked (char *channame)
 Get channel by name (locks channel).
int ast_waitfordigit (struct ast_channel *c, int ms)
 Waits for a digit.
int ast_waitfordigit_full (struct ast_channel *c, int ms, int audiofd, int ctrlfd)
int ast_readstring (struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
 Reads multiple digits.
int ast_readstring_full (struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd)
int ast_channel_make_compatible (struct ast_channel *c0, struct ast_channel *c1)
 Makes two channel formats compatible.
int ast_channel_bridge (struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
 Bridge two channels together.
int ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone)
 Weird function made for call transfers.
char * ast_state2str (int state)
 Gives the string form of a given state.
int ast_channel_setoption (struct ast_channel *channel, int option, void *data, int datalen, int block)
 Sets an option on a channel.
struct ast_frameast_channel_queryoption (struct ast_channel *channel, int option, void *data, int *datalen, int block)
 Checks the value of an option.
int ast_channel_supports_html (struct ast_channel *channel)
 Checks for HTML support on a channel.
int ast_channel_sendhtml (struct ast_channel *channel, int subclass, char *data, int datalen)
 Sends HTML on given channel.
int ast_channel_sendurl (struct ast_channel *channel, char *url)
 Sends a URL on a given link.
int ast_channel_defer_dtmf (struct ast_channel *chan)
 Defers DTMF.
void ast_channel_undefer_dtmf (struct ast_channel *chan)
 Undeos a defer.
void ast_begin_shutdown (int hangup)
void ast_cancel_shutdown (void)
int ast_active_channels (void)
int ast_shutting_down (void)
int ast_activate_generator (struct ast_channel *chan, struct ast_generator *gen, void *params)
void ast_deactivate_generator (struct ast_channel *chan)
void ast_set_callerid (struct ast_channel *chan, char *callerid, int anitoo)
int ast_tonepair_start (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
void ast_tonepair_stop (struct ast_channel *chan)
int ast_tonepair (struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
int ast_autoservice_start (struct ast_channel *chan)
int ast_autoservice_stop (struct ast_channel *chan)
int ast_settimeout (struct ast_channel *c, int samples, int(*func)(void *data), void *data)
int ast_transfer (struct ast_channel *chan, char *dest)
int ast_do_masquerade (struct ast_channel *chan)
unsigned int ast_get_group (char *s)


Define Documentation

#define AST_ADSI_AVAILABLE   (1)

Definition at line 315 of file channel.h.

#define AST_ADSI_OFFHOOKONLY   (3)

Definition at line 317 of file channel.h.

#define AST_ADSI_UNAVAILABLE   (2)

Definition at line 316 of file channel.h.

#define AST_ADSI_UNKNOWN   (0)

Definition at line 314 of file channel.h.

#define AST_BRIDGE_DTMF_CHANNEL_0   (1 << 0)

Report DTMF on channel 0

Definition at line 669 of file channel.h.

#define AST_BRIDGE_DTMF_CHANNEL_1   (1 << 1)

Report DTMF on channel 1

Definition at line 671 of file channel.h.

#define AST_BRIDGE_IGNORE_SIGS   (1 << 4)

Ignore all signal frames except NULL

Definition at line 677 of file channel.h.

#define AST_BRIDGE_REC_CHANNEL_0   (1 << 2)

Return all voice frames on channel 0

Definition at line 673 of file channel.h.

#define AST_BRIDGE_REC_CHANNEL_1   (1 << 3)

Return all voice frames on channel 1

Definition at line 675 of file channel.h.

#define AST_CDR_CALLWAIT   (1 << 2)

Definition at line 311 of file channel.h.

#define AST_CDR_CONFERENCE   (1 << 3)

Definition at line 312 of file channel.h.

#define AST_CDR_FORWARD   (1 << 1)

Definition at line 310 of file channel.h.

#define AST_CDR_TRANSFER   (1 << 0)

Definition at line 309 of file channel.h.

#define AST_CHANNEL_MAX_STACK   32

Definition at line 42 of file channel.h.

#define AST_CHANNEL_NAME   80

Definition at line 41 of file channel.h.

#define AST_DEVICE_BUSY   3

Device is busy

Definition at line 359 of file channel.h.

#define AST_DEVICE_INUSE   2

Device is in use

Definition at line 357 of file channel.h.

#define AST_DEVICE_INVALID   4

Device is invalid

Definition at line 361 of file channel.h.

#define AST_DEVICE_NOT_INUSE   1

Device is not used

Definition at line 355 of file channel.h.

#define AST_DEVICE_UNAVAILABLE   5

Device is unavailable

Definition at line 363 of file channel.h.

#define AST_DEVICE_UNKNOWN   0

Device is valid but channel didn't know state

Definition at line 353 of file channel.h.

#define AST_FLAG_DIGITAL   1

Definition at line 240 of file channel.h.

#define AST_MAX_EXTENSION   80

Max length of an extension.

Definition at line 35 of file channel.h.

#define AST_MAX_FDS   8

Definition at line 47 of file channel.h.

#define AST_SOFTHANGUP_APPUNLOAD   (1 << 4)

Definition at line 323 of file channel.h.

#define AST_SOFTHANGUP_ASYNCGOTO   (1 << 1)

Definition at line 320 of file channel.h.

#define AST_SOFTHANGUP_DEV   (1 << 0)

Definition at line 319 of file channel.h.

#define AST_SOFTHANGUP_EXPLICIT   (1 << 5)

Definition at line 324 of file channel.h.

#define AST_SOFTHANGUP_SHUTDOWN   (1 << 2)

Definition at line 321 of file channel.h.

#define AST_SOFTHANGUP_TIMEOUT   (1 << 3)

Definition at line 322 of file channel.h.

#define AST_STATE_BUSY   7

Line is busy

Definition at line 342 of file channel.h.

#define AST_STATE_DIALING   3

Digits (or equivalent) have been dialed

Definition at line 334 of file channel.h.

#define AST_STATE_DIALING_OFFHOOK   8

Digits (or equivalent) have been dialed while offhook

Definition at line 344 of file channel.h.

#define AST_STATE_DOWN   0

Channel is down and available

Definition at line 328 of file channel.h.

#define AST_STATE_MUTE   (1 << 16)

Do not transmit voice data

Definition at line 350 of file channel.h.

#define AST_STATE_OFFHOOK   2

Channel is off hook

Definition at line 332 of file channel.h.

#define AST_STATE_PRERING   9

Channel has detected an incoming call and is waiting for ring

Definition at line 346 of file channel.h.

#define AST_STATE_RESERVED   1

Channel is down, but reserved

Definition at line 330 of file channel.h.

#define AST_STATE_RING   4

Line is ringing

Definition at line 336 of file channel.h.

#define AST_STATE_RINGING   5

Remote end is ringing

Definition at line 338 of file channel.h.

#define AST_STATE_UP   6

Line is up

Definition at line 340 of file channel.h.

#define CHECK_BLOCKING (  ) 

Definition at line 883 of file channel.h.

#define CRASH   do { } while(0)

Definition at line 880 of file channel.h.

#define LOAD_OH ( oh   ) 

Definition at line 291 of file channel.h.

#define MAX_LANGUAGE   20

Definition at line 44 of file channel.h.


Function Documentation

struct ast_channel* __ast_request_and_dial ( char *  type,
int  format,
void *  data,
int  timeout,
int *  reason,
char *  callerid,
struct outgoing_helper oh 
) [read]

Definition at line 1758 of file channel.c.

01759 {
01760    int state = 0;
01761    struct ast_channel *chan;
01762    struct ast_frame *f;
01763    int res = 0;
01764    char *variable;
01765    chan = ast_request(type, format, data);
01766    if (chan) {
01767       if (oh) {
01768          char *tmp, *var;
01769          /* JDG chanvar */
01770          if (oh->variable)
01771             variable = ast_strdupa(oh->variable);
01772          else
01773             variable = NULL;
01774          tmp = variable;
01775          /* FIXME replace this call with strsep  NOT*/
01776          while( (var = strtok_r(NULL, "|", &tmp)) ) {
01777             pbx_builtin_setvar( chan, var );
01778          } /* /JDG */
01779          if (oh->callerid && *oh->callerid)
01780             ast_set_callerid(chan, oh->callerid, 1);
01781          if (oh->account && *oh->account)
01782             ast_cdr_setaccount(chan, oh->account);
01783       }
01784       if (callerid && !ast_strlen_zero(callerid))
01785          ast_set_callerid(chan, callerid, 1);
01786 
01787       if (!ast_call(chan, data, 0)) {
01788          while(timeout && (chan->_state != AST_STATE_UP)) {
01789             res = ast_waitfor(chan, timeout);
01790             if (res < 0) {
01791                /* Something not cool, or timed out */
01792                break;
01793             }
01794             /* If done, break out */
01795             if (!res)
01796                break;
01797             if (timeout > -1)
01798                timeout = res;
01799             f = ast_read(chan);
01800             if (!f) {
01801                state = AST_CONTROL_HANGUP;
01802                res = 0;
01803                break;
01804             }
01805             if (f->frametype == AST_FRAME_CONTROL) {
01806                if (f->subclass == AST_CONTROL_RINGING)
01807                   state = AST_CONTROL_RINGING;
01808                else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01809                   state = f->subclass;
01810                   ast_frfree(f);
01811                   break;
01812                } else if (f->subclass == AST_CONTROL_ANSWER) {
01813                   state = f->subclass;
01814                   ast_frfree(f);
01815                   break;
01816                } else if (f->subclass == AST_CONTROL_PROGRESS) {
01817                   /* Ignore */
01818                } else if (f->subclass == -1) {
01819                   /* Ignore -- just stopping indications */
01820                } else {
01821                   ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
01822                }
01823             }
01824             ast_frfree(f);
01825          }
01826       } else
01827          ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01828    } else
01829       ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01830    if (chan) {
01831       /* Final fixups */
01832       if (oh) {
01833          if (oh->context && *oh->context)
01834             strncpy(chan->context, oh->context, sizeof(chan->context) - 1);
01835          if (oh->exten && *oh->exten)
01836             strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1);
01837          chan->priority = oh->priority;
01838       }
01839       if (chan->_state == AST_STATE_UP) 
01840          state = AST_CONTROL_ANSWER;
01841    }
01842    if (outstate)
01843       *outstate = state;
01844    if (chan && res <= 0) {
01845       if (!chan->cdr) {
01846          chan->cdr = ast_cdr_alloc();
01847          if (chan->cdr)
01848             ast_cdr_init(chan->cdr, chan);
01849       }
01850       if (chan->cdr) {
01851          char tmp[256];
01852          snprintf(tmp, 256, "%s/%s", type, (char *)data);
01853          ast_cdr_setapp(chan->cdr,"Dial",tmp);
01854          ast_cdr_update(chan);
01855          ast_cdr_start(chan->cdr);
01856          ast_cdr_end(chan->cdr);
01857          /* If the cause wasn't handled properly */
01858          if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
01859             ast_cdr_failed(chan->cdr);
01860       } else 
01861          ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01862       ast_hangup(chan);
01863       chan = NULL;
01864    }
01865    return chan;
01866 }

int ast_activate_generator ( struct ast_channel chan,
struct ast_generator gen,
void *  params 
)

Activate a given generator

Definition at line 849 of file channel.c.

00850 {
00851    int res = 0;
00852    ast_mutex_lock(&chan->lock);
00853    if (chan->generatordata) {
00854       if (chan->generator && chan->generator->release)
00855          chan->generator->release(chan, chan->generatordata);
00856       chan->generatordata = NULL;
00857    }
00858    ast_prod(chan);
00859    if ((chan->generatordata = gen->alloc(chan, params))) {
00860       ast_settimeout(chan, 160, generator_force, chan);
00861       chan->generator = gen;
00862    } else {
00863       res = -1;
00864    }
00865    ast_mutex_unlock(&chan->lock);
00866    return res;
00867 }

int ast_active_channels ( void   ) 

Returns number of active/allocated channels

Definition at line 120 of file channel.c.

00121 {
00122    struct ast_channel *c;
00123    int cnt = 0;
00124    ast_mutex_lock(&chlock);
00125    c = channels;
00126    while(c) {
00127       cnt++;
00128       c = c->next;
00129    }
00130    ast_mutex_unlock(&chlock);
00131    return cnt;
00132 }

int ast_answer ( struct ast_channel chan  ) 

Answer a ringing call.

Parameters:
chan channel to answer This function answers a channel and handles all necessary call setup functions. Returns 0 on success, -1 on failure

Definition at line 785 of file channel.c.

00786 {
00787    int res = 0;
00788    ast_mutex_lock(&chan->lock);
00789    /* Stop if we're a zombie or need a soft hangup */
00790    if (chan->zombie || ast_check_hangup(chan)) {
00791       ast_mutex_unlock(&chan->lock);
00792       return -1;
00793    }
00794    switch(chan->_state) {
00795    case AST_STATE_RINGING:
00796    case AST_STATE_RING:
00797       if (chan->pvt->answer)
00798          res = chan->pvt->answer(chan);
00799       ast_setstate(chan, AST_STATE_UP);
00800       if (chan->cdr)
00801          ast_cdr_answer(chan->cdr);
00802       ast_mutex_unlock(&chan->lock);
00803       return res;
00804       break;
00805    case AST_STATE_UP:
00806       if (chan->cdr)
00807          ast_cdr_answer(chan->cdr);
00808       break;
00809    }
00810    ast_mutex_unlock(&chan->lock);
00811    return 0;
00812 }

int ast_autoservice_start ( struct ast_channel chan  ) 

Automatically service a channel for us...

Definition at line 88 of file autoservice.c.

00089 {
00090    int res = -1;
00091    struct asent *as;
00092    int needstart;
00093    ast_mutex_lock(&autolock);
00094    needstart = (asthread == AST_PTHREADT_NULL) ? 1 : 0 /* aslist ? 0 : 1 */;
00095    as = aslist;
00096    while(as) {
00097       if (as->chan == chan)
00098          break;
00099       as = as->next;
00100    }
00101    if (!as) {
00102       as = malloc(sizeof(struct asent));
00103       if (as) {
00104          memset(as, 0, sizeof(struct asent));
00105          as->chan = chan;
00106          as->next = aslist;
00107          aslist = as;
00108          res = 0;
00109          if (needstart) {
00110             if (ast_pthread_create(&asthread, NULL, autoservice_run, NULL)) {
00111                ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
00112                free(aslist);
00113                aslist = NULL;
00114                res = -1;
00115             } else
00116                pthread_kill(asthread, SIGURG);
00117          }
00118       }
00119    }
00120    ast_mutex_unlock(&autolock);
00121    return res;
00122 }

int ast_autoservice_stop ( struct ast_channel chan  ) 

Stop servicing a channel for us... Returns -1 on error or if channel has been hungup

Definition at line 124 of file autoservice.c.

00125 {
00126    int res = -1;
00127    struct asent *as, *prev;
00128    ast_mutex_lock(&autolock);
00129    as = aslist;
00130    prev = NULL;
00131    while(as) {
00132       if (as->chan == chan)
00133          break;
00134       prev = as;
00135       as = as->next;
00136    }
00137    if (as) {
00138       if (prev)
00139          prev->next = as->next;
00140       else
00141          aslist = as->next;
00142       free(as);
00143       if (!chan->_softhangup)
00144          res = 0;
00145    }
00146    if (asthread != AST_PTHREADT_NULL) 
00147       pthread_kill(asthread, SIGURG);
00148    ast_mutex_unlock(&autolock);
00149    /* Wait for it to un-block */
00150    while(chan->blocking)
00151       usleep(1000);
00152    return res;
00153 }

void ast_begin_shutdown ( int  hangup  ) 

Initiate system shutdown -- prevents new channels from being allocated. If "hangup" is non-zero, all existing channels will receive soft hangups

Definition at line 105 of file channel.c.

00106 {
00107    struct ast_channel *c;
00108    shutting_down = 1;
00109    if (hangup) {
00110       ast_mutex_lock(&chlock);
00111       c = channels;
00112       while(c) {
00113          ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
00114          c = c->next;
00115       }
00116       ast_mutex_unlock(&chlock);
00117    }
00118 }

int ast_call ( struct ast_channel chan,
char *  addr,
int  timeout 
)

Make a call.

Parameters:
chan which channel to make the call on
addr destination of the call
timeout time to wait on for connect Place a call, take no longer than timeout ms. Returns -1 on failure, 0 on not enough time (does not auto matically stop ringing), and the number of seconds the connect took otherwise. Returns 0 on success, -1 on failure

Definition at line 1977 of file channel.c.

01978 {
01979    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
01980       If the remote end does not answer within the timeout, then do NOT hang up, but 
01981       return anyway.  */
01982    int res = -1;
01983    /* Stop if we're a zombie or need a soft hangup */
01984    ast_mutex_lock(&chan->lock);
01985    if (!chan->zombie && !ast_check_hangup(chan)) 
01986       if (chan->pvt->call)
01987          res = chan->pvt->call(chan, addr, timeout);
01988    ast_mutex_unlock(&chan->lock);
01989    return res;
01990 }

void ast_cancel_shutdown ( void   ) 

Cancels an existing shutdown and returns to normal operation

Definition at line 134 of file channel.c.

00135 {
00136    shutting_down = 0;
00137 }

int ast_channel_bridge ( struct ast_channel c0,
struct ast_channel c1,
struct ast_bridge_config config,
struct ast_frame **  fo,
struct ast_channel **  rc 
)

Bridge two channels together.

Parameters:
c0 first channel to bridge
c1 second channel to bridge
flags for the channels
fo destination frame(?)
rc destination channel(?) Bridge two channels (c0 and c1) together. If an important frame occurs, we return that frame in rf (remember, it could be NULL) and which channel (0 or 1) in rc

Definition at line 2523 of file channel.c.

02524 {
02525    /* Copy voice back and forth between the two channels.   Give the peer
02526       the ability to transfer calls with '#<extension' syntax. */
02527    int flags;
02528    struct ast_channel *cs[3];
02529    int to = -1;
02530    struct ast_frame *f;
02531    struct ast_channel *who = NULL;
02532    int res=0;
02533    int nativefailed=0;
02534    int firstpass;
02535    int o0nativeformats;
02536    int o1nativeformats;
02537    struct timeval start_time,precise_now;
02538    long elapsed_ms=0, time_left_ms=0;
02539    int playit=0, playitagain=1, first_time=1;
02540 
02541    flags = (config->allowdisconnect_out||config->allowredirect_out ? AST_BRIDGE_DTMF_CHANNEL_0 : 0) + (config->allowdisconnect_in||config->allowredirect_in ? AST_BRIDGE_DTMF_CHANNEL_1 : 0);
02542 
02543    firstpass = config->firstpass;
02544    config->firstpass = 0;
02545 
02546    /* timestamp */
02547    gettimeofday(&start_time,NULL);
02548    time_left_ms = config->timelimit;
02549 
02550    if (config->play_to_caller && config->start_sound && firstpass)
02551       bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000);
02552    if (config->play_to_callee && config->start_sound && firstpass)
02553       bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000);
02554 
02555    /* Stop if we're a zombie or need a soft hangup */
02556    if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 
02557       return -1;
02558    if (c0->bridge) {
02559       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02560          c0->name, c0->bridge->name);
02561       return -1;
02562    }
02563    if (c1->bridge) {
02564       ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
02565          c1->name, c1->bridge->name);
02566       return -1;
02567    }
02568    
02569    /* Keep track of bridge */
02570    c0->bridge = c1;
02571    c1->bridge = c0;
02572    cs[0] = c0;
02573    cs[1] = c1;
02574    
02575    manager_event(EVENT_FLAG_CALL, "Link", 
02576          "Channel1: %s\r\n"
02577          "Channel2: %s\r\n"
02578          "Uniqueid1: %s\r\n"
02579          "Uniqueid2: %s\r\n",
02580          c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02581    o1nativeformats = c1->nativeformats;
02582    o0nativeformats = c0->nativeformats;
02583    for (/* ever */;;) {
02584       /* timestamp */
02585       if (config->timelimit) {
02586          gettimeofday(&precise_now,NULL);
02587          elapsed_ms = tvdiff(&precise_now,&start_time);
02588          time_left_ms = config->timelimit - elapsed_ms;
02589 
02590          if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) { 
02591             /* narrowing down to the end */
02592             if (config->warning_freq == 0) {
02593                playit = 1;
02594                first_time=0;
02595                playitagain=0;
02596             } else if (first_time) {
02597                playit = 1;
02598                first_time=0;
02599             } else {
02600                if ((time_left_ms % config->warning_freq) <= 50) {
02601                   playit = 1;
02602                }
02603             }
02604          }
02605          if (time_left_ms <= 0) {
02606             if (config->play_to_caller && config->end_sound)
02607                bridge_playfile(c0,c1,config->end_sound,0);
02608             if (config->play_to_callee && config->end_sound)
02609                bridge_playfile(c1,c0,config->end_sound,0);
02610             *fo = NULL;
02611             if (who) *rc = who;
02612             res = 0;
02613             break;
02614          }
02615          if (time_left_ms >= 5000 && playit) {
02616             if (config->play_to_caller && config->warning_sound && config->play_warning)
02617                bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000);
02618             if (config->play_to_callee && config->warning_sound && config->play_warning)
02619                bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000);
02620             playit = 0;
02621          }
02622          
02623       }
02624       /* Stop if we're a zombie or need a soft hangup */
02625       if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
02626          *fo = NULL;
02627          if (who) *rc = who;
02628          res = 0;
02629          ast_log(LOG_DEBUG, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",c0->name,c1->name,c0->zombie?"Yes":"No",ast_check_hangup(c0)?"Yes":"No",c1->zombie?"Yes":"No",ast_check_hangup(c1)?"Yes":"No");
02630          break;
02631       }
02632       if (c0->pvt->bridge && config->timelimit==0 &&
02633          (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
02634             /* Looks like they share a bridge code */
02635          if (option_verbose > 2) 
02636             ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
02637          if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
02638             c0->bridge = NULL;
02639             c1->bridge = NULL;
02640             manager_event(EVENT_FLAG_CALL, "Unlink", 
02641                "Channel1: %s\r\n"
02642                "Channel2: %s\r\n"
02643                "Uniqueid1: %s\r\n"
02644                "Uniqueid2: %s\r\n",
02645                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02646             ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
02647             return 0;
02648          }
02649          /* If they return non-zero then continue on normally.  Let "-2" mean don't worry about
02650             my not wanting to bridge */
02651          if ((res != -2) && (res != -3))
02652             ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
02653          if (res != -3) nativefailed++;
02654       }
02655    
02656       if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) &&
02657          !(c0->generator || c1->generator))  {
02658          if (ast_channel_make_compatible(c0, c1)) {
02659             ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
02660             manager_event(EVENT_FLAG_CALL, "Unlink", 
02661                "Channel1: %s\r\n"
02662                "Channel2: %s\r\n"
02663                "Uniqueid1: %s\r\n"
02664                "Uniqueid2: %s\r\n",
02665                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02666             return -1;
02667          }
02668          o0nativeformats = c0->nativeformats;
02669          o1nativeformats = c1->nativeformats;
02670       }
02671       who = ast_waitfor_n(cs, 2, &to);
02672       if (!who) {
02673          ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 
02674          continue;
02675       }
02676       f = ast_read(who);
02677       if (!f) {
02678          *fo = NULL;
02679          *rc = who;
02680          res = 0;
02681          ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
02682          break;
02683       }
02684 
02685       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02686          *fo = f;
02687          *rc = who;
02688          res =  0;
02689          ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
02690          break;
02691       }
02692       if ((f->frametype == AST_FRAME_VOICE) ||
02693          (f->frametype == AST_FRAME_TEXT) ||
02694          (f->frametype == AST_FRAME_VIDEO) || 
02695          (f->frametype == AST_FRAME_IMAGE) ||
02696          (f->frametype == AST_FRAME_HTML) ||
02697          (f->frametype == AST_FRAME_DTMF)) {
02698          if ((f->frametype == AST_FRAME_DTMF) && 
02699             (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
02700             if ((who == c0)) {
02701                if  ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
02702                   *rc = c0;
02703                   *fo = f;
02704                   /* Take out of conference mode */
02705                   res = 0;
02706                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
02707                   break;
02708                } else 
02709                   goto tackygoto;
02710             } else
02711             if ((who == c1)) {
02712                if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
02713                   *rc = c1;
02714                   *fo = f;
02715                   res =  0;
02716                   ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
02717                   break;
02718                } else
02719                   goto tackygoto;
02720             }
02721          } else {
02722 #if 0
02723             ast_log(LOG_DEBUG, "Read from %s\n", who->name);
02724             if (who == last) 
02725                ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
02726             last = who;
02727 #endif
02728 tackygoto:
02729             /* Don't copy packets if there is a generator on either one, since they're
02730                not supposed to be listening anyway */
02731             if (who == c0) 
02732                ast_write(c1, f);
02733             else 
02734                ast_write(c0, f);
02735          }
02736          ast_frfree(f);
02737       } else
02738          ast_frfree(f);
02739       /* Swap who gets priority */
02740       cs[2] = cs[0];
02741       cs[0] = cs[1];
02742       cs[1] = cs[2];
02743    }
02744    c0->bridge = NULL;
02745    c1->bridge = NULL;
02746    manager_event(EVENT_FLAG_CALL, "Unlink", 
02747                "Channel1: %s\r\n"
02748                "Channel2: %s\r\n"
02749                "Uniqueid1: %s\r\n"
02750                "Uniqueid2: %s\r\n",
02751                c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02752    ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name);
02753    return res;
02754 }

int ast_channel_defer_dtmf ( struct ast_channel chan  ) 

Defers DTMF.

Defer DTMF so that you only read things like hangups and audio. Returns non-zero if channel was already DTMF-deferred or 0 if channel is just now being DTMF-deferred

Definition at line 441 of file channel.c.

00442 {
00443    int pre = 0;
00444    if (chan) {
00445       pre = chan->deferdtmf;
00446       chan->deferdtmf = 1;
00447    }
00448    return pre;
00449 }

int ast_channel_make_compatible ( struct ast_channel c0,
struct ast_channel c1 
)

Makes two channel formats compatible.

Parameters:
c0 first channel to make compatible
c1 other channel to make compatible Set two channels to compatible formats -- call before ast_channel_bridge in general . Returns 0 on success and -1 if it could not be done

Definition at line 2114 of file channel.c.

02115 {
02116    int peerf;
02117    int chanf;
02118    int res;
02119    ast_mutex_lock(&peer->lock);
02120    peerf = peer->nativeformats;
02121    ast_mutex_unlock(&peer->lock);
02122    ast_mutex_lock(&chan->lock);
02123    chanf = chan->nativeformats;
02124    ast_mutex_unlock(&chan->lock);
02125    res = ast_translator_best_choice(&peerf, &chanf);
02126    if (res < 0) {
02127       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
02128       return -1;
02129    }
02130    /* Set read format on channel */
02131    res = ast_set_read_format(chan, peerf);
02132    if (res < 0) {
02133       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
02134       return -1;
02135    }
02136    /* Set write format on peer channel */
02137    res = ast_set_write_format(peer, peerf);
02138    if (res < 0) {
02139       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
02140       return -1;
02141    }
02142    /* Now we go the other way */
02143    peerf = peer->nativeformats;
02144    chanf = chan->nativeformats;
02145    res = ast_translator_best_choice(&chanf, &peerf);
02146    if (res < 0) {
02147       ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
02148       return -1;
02149    }
02150    /* Set writeformat on channel */
02151    res = ast_set_write_format(chan, chanf);
02152    if (res < 0) {
02153       ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
02154       return -1;
02155    }
02156    /* Set read format on peer channel */
02157    res = ast_set_read_format(peer, chanf);
02158    if (res < 0) {
02159       ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
02160       return -1;
02161    }
02162    return 0;
02163 }

int ast_channel_masquerade ( struct ast_channel original,
struct ast_channel clone 
)

Weird function made for call transfers.

Parameters:
original channel to make a copy of
clone copy of the original channel This is a very strange and freaky function used primarily for transfer. Suppose that "original" and "clone" are two channels in random situations. This function takes the guts out of "clone" and puts them into the "original" channel, then alerts the channel driver of the change, asking it to fixup any private information (like the p->owner pointer) that is affected by the change. The physical layer of the original channel is hung up.

Definition at line 2165 of file channel.c.

02166 {
02167    struct ast_frame null = { AST_FRAME_NULL, };
02168    int res = -1;
02169    ast_mutex_lock(&original->lock);
02170    while(ast_mutex_trylock(&clone->lock)) {
02171       ast_mutex_unlock(&original->lock);
02172       usleep(1);
02173       ast_mutex_lock(&original->lock);
02174    }
02175    ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
02176       clone->name, original->name);
02177    if (original->masq) {
02178       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02179          original->masq->name, original->name);
02180    } else if (clone->masqr) {
02181       ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
02182          clone->name, clone->masqr->name);
02183    } else {
02184       original->masq = clone;
02185       clone->masqr = original;
02186       ast_queue_frame(original, &null);
02187       ast_queue_frame(clone, &null);
02188       ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
02189       res = 0;
02190    }
02191    ast_mutex_unlock(&clone->lock);
02192    ast_mutex_unlock(&original->lock);
02193    return res;
02194 }

struct ast_frame* ast_channel_queryoption ( struct ast_channel channel,
int  option,
void *  data,
int *  datalen,
int  block 
) [read]

Checks the value of an option.

Query the value of an option, optionally blocking until a reply is received Works similarly to setoption except only reads the options.

int ast_channel_register ( char *  type,
char *  description,
int  capabilities,
struct ast_channel *(*)(char *type, int format, void *data)  requester 
)

Registers a channel.

Parameters:
type type of channel you are registering
description short description of the channel
capabilities a bit mask of the capabilities of the channel
requester a function pointer that properly responds to a call. See one of the channel drivers for details. Called by a channel module to register the kind of channels it supports. It supplies a brief type, a longer, but still short description, and a routine that creates a channel Returns 0 on success, -1 on failure.

Definition at line 156 of file channel.c.

00158 {
00159    return ast_channel_register_ex(type, description, capabilities, requester, NULL);
00160 }

int ast_channel_register_ex ( char *  type,
char *  description,
int  capabilities,
struct ast_channel *(*)(char *type, int format, void *data)  requester,
int(*)(void *data)  devicestate 
)

Definition at line 162 of file channel.c.

00165 {
00166    struct chanlist *chan, *last=NULL;
00167    if (ast_mutex_lock(&chlock)) {
00168       ast_log(LOG_WARNING, "Unable to lock channel list\n");
00169       return -1;
00170    }
00171    chan = backends;
00172    while (chan) {
00173       if (!strcasecmp(type, chan->type)) {
00174          ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
00175          ast_mutex_unlock(&chlock);
00176          return -1;
00177       }
00178       last = chan;
00179       chan = chan->next;
00180    }
00181    chan = malloc(sizeof(struct chanlist));
00182    if (!chan) {
00183       ast_log(LOG_WARNING, "Out of memory\n");
00184       ast_mutex_unlock(&chlock);
00185       return -1;
00186    }
00187    strncpy(chan->type, type, sizeof(chan->type)-1);
00188    strncpy(chan->description, description, sizeof(chan->description)-1);
00189    chan->capabilities = capabilities;
00190    chan->requester = requester;
00191    chan->devicestate = devicestate;
00192    chan->next = NULL;
00193    if (last)
00194       last->next = chan;
00195    else
00196       backends = chan;
00197    if (option_debug)
00198       ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
00199    else if (option_verbose > 1)
00200       ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
00201    ast_mutex_unlock(&chlock);
00202    return 0;
00203 }

int ast_channel_sendhtml ( struct ast_channel channel,
int  subclass,
char *  data,
int  datalen 
)

Sends HTML on given channel.

Send HTML or URL on link. Returns 0 on success or -1 on failure

Definition at line 2100 of file channel.c.

02101 {
02102    if (chan->pvt->send_html)
02103       return chan->pvt->send_html(chan, subclass, data, datalen);
02104    return -1;
02105 }

int ast_channel_sendurl ( struct ast_channel channel,
char *  url 
)

Sends a URL on a given link.

Send URL on link. Returns 0 on success or -1 on failure

Definition at line 2107 of file channel.c.

02108 {
02109    if (chan->pvt->send_html)
02110       return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
02111    return -1;
02112 }

int ast_channel_setoption ( struct ast_channel channel,
int  option,
void *  data,
int  datalen,
int  block 
)

Sets an option on a channel.

Parameters:
channel channel to set options on
option option to change
data data specific to option
datalen length of the data
block blocking or not Set an option on a channel (see frame.h), optionally blocking awaiting the reply Returns 0 on success and -1 on failure

Definition at line 2756 of file channel.c.

02757 {
02758    int res;
02759    if (chan->pvt->setoption) {
02760       res = chan->pvt->setoption(chan, option, data, datalen);
02761       if (res < 0)
02762          return res;
02763    } else {
02764       errno = ENOSYS;
02765       return -1;
02766    }
02767    if (block) {
02768       /* XXX Implement blocking -- just wait for our option frame reply, discarding
02769          intermediate packets. XXX */
02770       ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
02771       return -1;
02772    }
02773    return 0;
02774 }

void ast_channel_setwhentohangup ( struct ast_channel chan,
time_t  offset 
)

Set when to hang a channel up.

Parameters:
chan channel on which to check for hang up
offset offset in seconds from current time of when to hang up This function sets the absolute time out on a channel (when to hang up).

Definition at line 144 of file channel.c.

00145 {
00146    time_t   myt;
00147 
00148    time(&myt);
00149    if (offset)
00150       chan->whentohangup = myt + offset;
00151    else
00152       chan->whentohangup = 0;
00153    return;
00154 }

int ast_channel_supports_html ( struct ast_channel channel  ) 

Checks for HTML support on a channel.

Returns 0 if channel does not support HTML or non-zero if it does

Definition at line 2093 of file channel.c.

02094 {
02095    if (chan->pvt->send_html)
02096       return 1;
02097    return 0;
02098 }

void ast_channel_undefer_dtmf ( struct ast_channel chan  ) 

Undeos a defer.

Undo defer. ast_read will return any dtmf characters that were queued

Definition at line 451 of file channel.c.

00452 {
00453    if (chan)
00454       chan->deferdtmf = 0;
00455 }

void ast_channel_unregister ( char *  type  ) 

Unregister a channel class.

Definition at line 756 of file channel.c.

00757 {
00758    struct chanlist *chan, *last=NULL;
00759    if (option_debug)
00760       ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type);
00761    if (ast_mutex_lock(&chlock)) {
00762       ast_log(LOG_WARNING, "Unable to lock channel list\n");
00763       return;
00764    }
00765    if (option_verbose > 1)
00766       ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type);
00767 
00768    chan = backends;
00769    while(chan) {
00770       if (!strcasecmp(chan->type, type)) {
00771          if (last)
00772             last->next = chan->next;
00773          else
00774             backends = backends->next;
00775          free(chan);
00776          ast_mutex_unlock(&chlock);
00777          return;
00778       }
00779       last = chan;
00780       chan = chan->next;
00781    }
00782    ast_mutex_unlock(&chlock);
00783 }

struct ast_channel* ast_channel_walk_locked ( struct ast_channel prev  )  [read]

Browse channels in use.

Parameters:
prev where you want to start in the channel list Browse the channels currently in use Returns the next channel in the list, NULL on end. If it returns a channel, that channel *has been locked*!

Definition at line 457 of file channel.c.

00458 {
00459    /* Returns next channel (locked) */
00460    struct ast_channel *l, *ret;
00461    int retries = 0;  
00462 retry:
00463    ret=NULL;
00464    ast_mutex_lock(&chlock);
00465    l = channels;
00466    if (!prev) {
00467       if (l) {
00468          if (ast_mutex_trylock(&l->lock)) {
00469             if (retries < 10)
00470                ast_log(LOG_DEBUG, "Avoiding initial deadlock for '%s'\n", l->name);
00471             else
00472                ast_log(LOG_WARNING, "Avoided initial deadlock for '%s', %d retries!\n", l->name, retries);
00473             ast_mutex_unlock(&chlock);
00474             if (retries < 10) {
00475                usleep(1);
00476                retries++;
00477                goto retry;
00478             } else
00479                return NULL;
00480          }
00481       }
00482       ast_mutex_unlock(&chlock);
00483       return l;
00484    }
00485    while(l) {
00486       if (l == prev)
00487          ret = l->next;
00488       l = l->next;
00489    }
00490    if (ret) {
00491       if (ast_mutex_trylock(&ret->lock)) {
00492          if (retries < 10)
00493             ast_log(LOG_DEBUG, "Avoiding deadlock for '%s'\n", ret->name);
00494          else
00495             ast_log(LOG_WARNING, "Avoided deadlock for '%s', %d retries!\n", ret->name, retries);
00496          ast_mutex_unlock(&chlock);
00497          if (retries < 10) {
00498             usleep(1);
00499             retries++;
00500             goto retry;
00501          } else
00502             return NULL;
00503       }
00504    }
00505    ast_mutex_unlock(&chlock);
00506    return ret;
00507    
00508 }

int ast_check_hangup ( struct ast_channel chan  ) 

Check to see if a channel is needing hang up.

Parameters:
chan channel on which to check for hang up This function determines if the channel is being requested to be hung up. Returns 0 if not, or 1 if hang up is requested (including time-out).

Definition at line 79 of file channel.c.

00080 {
00081 time_t   myt;
00082 
00083      /* if soft hangup flag, return true */
00084    if (chan->_softhangup) return 1;
00085      /* if no private structure, return true */
00086    if (!chan->pvt->pvt) return 1;
00087      /* if no hangup scheduled, just return here */
00088    if (!chan->whentohangup) return 0;
00089    time(&myt); /* get current time */
00090      /* return, if not yet */
00091    if (chan->whentohangup > myt) return 0;
00092    chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
00093    return 1;
00094 }

void ast_deactivate_generator ( struct ast_channel chan  ) 

Deactive an active generator

Definition at line 816 of file channel.c.

00817 {
00818    ast_mutex_lock(&chan->lock);
00819    if (chan->generatordata) {
00820       if (chan->generator && chan->generator->release) 
00821          chan->generator->release(chan, chan->generatordata);
00822       chan->generatordata = NULL;
00823       chan->generator = NULL;
00824       chan->writeinterrupt = 0;
00825       ast_settimeout(chan, 0, NULL, NULL);
00826    }
00827    ast_mutex_unlock(&chan->lock);
00828 }

int ast_device_state ( char *  device  ) 

Asks a channel for device state.

Parameters:
device like a dialstring Asks a channel for device state, data is normaly a number from dialstring used by the low level module Trys the channel devicestate callback if not supported search in the active channels list for the device. Returns an AST_DEVICE_??? state -1 on failure

Definition at line 1938 of file channel.c.

01939 {
01940    char tech[AST_MAX_EXTENSION] = "";
01941    char *number;
01942    struct chanlist *chanls;
01943    int res = 0;
01944    
01945    strncpy(tech, device, sizeof(tech)-1);
01946    number = strchr(tech, '/');
01947    if (!number) {
01948        return AST_DEVICE_INVALID;
01949    }
01950    *number = 0;
01951    number++;
01952       
01953    if (ast_mutex_lock(&chlock)) {
01954       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01955       return -1;
01956    }
01957    chanls = backends;
01958    while(chanls) {
01959       if (!strcasecmp(tech, chanls->type)) {
01960          ast_mutex_unlock(&chlock);
01961          if (!chanls->devicestate) 
01962             return ast_parse_device_state(device);
01963          else {
01964             res = chanls->devicestate(number);
01965             if (res == AST_DEVICE_UNKNOWN)
01966                return ast_parse_device_state(device);
01967             else
01968                return res;
01969          }
01970       }
01971       chanls = chanls->next;
01972    }
01973    ast_mutex_unlock(&chlock);
01974    return AST_DEVICE_INVALID;
01975 }

int ast_do_masquerade ( struct ast_channel chan  ) 

Definition at line 2204 of file channel.c.

02205 {
02206    int x,i;
02207    int res=0;
02208    int origstate;
02209    char *tmp;
02210    struct ast_var_t *varptr;
02211    struct ast_frame *cur, *prev;
02212    struct ast_channel_pvt *p;
02213    struct ast_channel *clone = original->masq;
02214    struct ast_channel_monitor *monitor;
02215    int rformat = original->readformat;
02216    int wformat = original->writeformat;
02217    char newn[100];
02218    char orig[100];
02219    char masqn[100];
02220    char zombn[100];
02221 
02222 #if 1
02223    ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
02224       clone->name, clone->_state, original->name, original->_state);
02225 #endif
02226    /* XXX This is a seriously wacked out operation.  We're essentially putting the guts of
02227       the clone channel into the original channel.  Start by killing off the original
02228       channel's backend.   I'm not sure we're going to keep this function, because 
02229       while the features are nice, the cost is very high in terms of pure nastiness. XXX */
02230 
02231    /* We need the clone's lock, too */
02232    ast_mutex_lock(&clone->lock);
02233 
02234    ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock);
02235 
02236    /* Having remembered the original read/write formats, we turn off any translation on either
02237       one */
02238    free_translation(clone);
02239    free_translation(original);
02240 
02241 
02242    /* Unlink the masquerade */
02243    original->masq = NULL;
02244    clone->masqr = NULL;
02245    
02246    /* Save the original name */
02247    strncpy(orig, original->name, sizeof(orig) - 1);
02248    /* Save the new name */
02249    strncpy(newn, clone->name, sizeof(newn) - 1);
02250    /* Create the masq name */
02251    snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn);
02252       
02253    /* Copy the name from the clone channel */
02254    strncpy(original->name, newn, sizeof(original->name)-1);
02255 
02256    /* Mangle the name of the clone channel */
02257    strncpy(clone->name, masqn, sizeof(clone->name) - 1);
02258    
02259    /* Notify any managers of the change, first the masq then the other */
02260    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
02261    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
02262 
02263    /* Swap the guts */  
02264    p = original->pvt;
02265    original->pvt = clone->pvt;
02266    clone->pvt = p;
02267 
02268    /* Save any pending frames on both sides.  Start by counting
02269     * how many we're going to need... */
02270    prev = NULL;
02271    cur = clone->pvt->readq;
02272    x = 0;
02273    while(cur) {
02274       x++;
02275       prev = cur;
02276       cur = cur->next;
02277    }
02278    /* If we had any, prepend them to the ones already in the queue, and 
02279     * load up the alertpipe */
02280    if (prev) {
02281       prev->next = original->pvt->readq;
02282       original->pvt->readq = clone->pvt->readq;
02283       clone->pvt->readq = NULL;
02284       if (original->pvt->alertpipe[1] > -1) {
02285          for (i=0;i<x;i++)
02286             write(original->pvt->alertpipe[1], &x, sizeof(x));
02287       }
02288    }
02289    clone->_softhangup = AST_SOFTHANGUP_DEV;
02290 
02291 
02292    /* And of course, so does our current state.  Note we need not
02293       call ast_setstate since the event manager doesn't really consider
02294       these separate.  We do this early so that the clone has the proper
02295       state of the original channel. */
02296    origstate = original->_state;
02297    original->_state = clone->_state;
02298    clone->_state = origstate;
02299 
02300    if (clone->pvt->fixup){
02301       res = clone->pvt->fixup(original, clone);
02302       if (res) 
02303          ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
02304    }
02305 
02306    /* Start by disconnecting the original's physical side */
02307    if (clone->pvt->hangup)
02308       res = clone->pvt->hangup(clone);
02309    if (res) {
02310       ast_log(LOG_WARNING, "Hangup failed!  Strange things may happen!\n");
02311       ast_mutex_unlock(&clone->lock);
02312       return -1;
02313    }
02314    
02315    snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig);
02316    /* Mangle the name of the clone channel */
02317    strncpy(clone->name, zombn, sizeof(clone->name) - 1);
02318    manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid);
02319 
02320    /* Update the type. */
02321    original->type = clone->type;
02322 
02323    /* copy the monitor */
02324    monitor = original->monitor;
02325    original->monitor = clone->monitor;
02326    clone->monitor = monitor;  
02327    
02328    /* Keep the same language.  */
02329    strncpy(original->language, clone->language, sizeof(original->language));
02330 
02331    /* Copy the FD's */
02332    for (x=0;x<AST_MAX_FDS;x++) {
02333       original->fds[x] = clone->fds[x];
02334    }
02335    /* Append variables from clone channel into original channel */
02336    /* XXX Is this always correct?  We have to in order to keep MACROS working XXX */
02337    varptr = original->varshead.first;
02338    if (varptr) {
02339       while(varptr->entries.next) {
02340          varptr = varptr->entries.next;
02341       }
02342       varptr->entries.next = clone->varshead.first;
02343    } else {
02344       original->varshead.first = clone->varshead.first;
02345    }
02346    clone->varshead.first = NULL;
02347    /* Presense of ADSI capable CPE follows clone */
02348    original->adsicpe = clone->adsicpe;
02349    /* Bridge remains the same */
02350    /* CDR fields remain the same */
02351    /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */
02352    /* Application and data remain the same */
02353    /* Clone exception  becomes real one, as with fdno */
02354    original->exception = clone->exception;
02355    original->fdno = clone->fdno;
02356    /* Schedule context remains the same */
02357    /* Stream stuff stays the same */
02358    /* Keep the original state.  The fixup code will need to work with it most likely */
02359 
02360    /* dnid and callerid change to become the new, HOWEVER, we also link the original's
02361       fields back into the defunct 'clone' so that they will be freed when
02362       ast_frfree is eventually called */
02363    tmp = original->dnid;
02364    original->dnid = clone->dnid;
02365    clone->dnid = tmp;
02366    
02367    tmp = original->callerid;
02368    original->callerid = clone->callerid;
02369    clone->callerid = tmp;
02370    
02371    /* Restore original timing file descriptor */
02372    original->fds[AST_MAX_FDS - 2] = original->timingfd;
02373    
02374    /* Our native formats are different now */
02375    original->nativeformats = clone->nativeformats;
02376    
02377    /* Context, extension, priority, app data, jump table,  remain the same */
02378    /* pvt switches.  pbx stays the same, as does next */
02379    
02380    /* Set the write format */
02381    ast_set_write_format(original, wformat);
02382 
02383    /* Set the read format */
02384    ast_set_read_format(original, rformat);
02385 
02386    /* Copy the music class */
02387    strncpy(original->musicclass, clone->musicclass, sizeof(original->musicclass) - 1);
02388 
02389    ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat);
02390 
02391    /* Okay.  Last thing is to let the channel driver know about all this mess, so he
02392       can fix up everything as best as possible */
02393    if (original->pvt->fixup) {
02394       res = original->pvt->fixup(clone, original);
02395       if (res) {
02396          ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n",
02397             original->type, original->name);
02398          ast_mutex_unlock(&clone->lock);
02399          return -1;
02400       }
02401    } else
02402       ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)!  Bad things may happen.\n",
02403          original->type, original->name);
02404    
02405    /* Now, at this point, the "clone" channel is totally F'd up.  We mark it as
02406       a zombie so nothing tries to touch it.  If it's already been marked as a
02407       zombie, then free it now (since it already is considered invalid). */
02408    if (clone->zombie) {
02409       ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name);
02410       ast_mutex_unlock(&clone->lock);
02411       ast_channel_free(clone);
02412       manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
02413    } else {
02414       struct ast_frame null_frame = { AST_FRAME_NULL, };
02415       ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name);
02416       clone->zombie=1;
02417       ast_queue_frame(clone, &null_frame);
02418       ast_mutex_unlock(&clone->lock);
02419    }
02420    
02421    /* Signal any blocker */
02422    if (original->blocking)
02423       pthread_kill(original->blocker, SIGURG);
02424    ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n",
02425       original->name, original->_state);
02426    return 0;
02427 }

struct ast_channel* ast_get_channel_by_name_locked ( char *  channame  )  [read]

Get channel by name (locks channel).

Definition at line 510 of file channel.c.

00511 {
00512    struct ast_channel *chan;
00513    chan = ast_channel_walk_locked(NULL);
00514    while(chan) {
00515       if (!strcasecmp(chan->name, channame))
00516          return chan;
00517       ast_mutex_unlock(&chan->lock);
00518       chan = ast_channel_walk_locked(chan);
00519    }
00520    return NULL;
00521 }

unsigned int ast_get_group ( char *  s  ) 

Definition at line 2908 of file channel.c.

02909 {
02910    char *copy;
02911    char *piece;
02912    char *c=NULL;
02913    int start=0, finish=0,x;
02914    unsigned int group = 0;
02915    copy = ast_strdupa(s);
02916    if (!copy) {
02917       ast_log(LOG_ERROR, "Out of memory\n");
02918       return 0;
02919    }
02920    c = copy;
02921    
02922    while((piece = strsep(&c, ","))) {
02923       if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
02924          /* Range */
02925       } else if (sscanf(piece, "%d", &start)) {
02926          /* Just one */
02927          finish = start;
02928       } else {
02929          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.\n", s, piece);
02930          continue;
02931       }
02932       for (x=start;x<=finish;x++) {
02933          if ((x > 31) || (x < 0)) {
02934             ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x);
02935          } else
02936             group |= (1 << x);
02937       }
02938    }
02939    return group;
02940 }

int ast_hangup ( struct ast_channel chan  ) 

Hang up a channel.

Parameters:
chan channel to hang up This function performs a hard hangup on a channel. Unlike the soft-hangup, this function performs all stream stopping, etc, on the channel that needs to end. chan is no longer valid after this call. Returns 0 on success, -1 on failure.

Definition at line 689 of file channel.c.

00690 {
00691    int res = 0;
00692    /* Don't actually hang up a channel that will masquerade as someone else, or
00693       if someone is going to masquerade as us */
00694    ast_mutex_lock(&chan->lock);
00695    if (chan->masq) {
00696       if (ast_do_masquerade(chan)) 
00697          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
00698    }
00699 
00700    if (chan->masq) {
00701       ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
00702       ast_mutex_unlock(&chan->lock);
00703       return 0;
00704    }
00705    /* If this channel is one which will be masqueraded into something, 
00706       mark it as a zombie already, so we know to free it later */
00707    if (chan->masqr) {
00708       chan->zombie=1;
00709       ast_mutex_unlock(&chan->lock);
00710       return 0;
00711    }
00712    free_translation(chan);
00713    if (chan->stream) 
00714       ast_closestream(chan->stream);
00715    if (chan->vstream)
00716       ast_closestream(chan->vstream);
00717    if (chan->sched)
00718       sched_context_destroy(chan->sched);
00719    /* Clear any tone stuff remaining */
00720    if (chan->generatordata)
00721       chan->generator->release(chan, chan->generatordata);
00722    chan->generatordata = NULL;
00723    chan->generator = NULL;
00724    if (chan->cdr) {
00725       /* End the CDR if it hasn't already */
00726       ast_cdr_end(chan->cdr);
00727       /* Post and Free the CDR */
00728       ast_cdr_post(chan->cdr);
00729       ast_cdr_free(chan->cdr);
00730    }
00731    if (chan->blocking) {
00732       ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
00733                "is blocked by thread %ld in procedure %s!  Expect a failure\n",
00734                (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc);
00735       CRASH;
00736    }
00737    if (!chan->zombie) {
00738       if (option_debug)
00739          ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
00740       if (chan->pvt->hangup)
00741          res = chan->pvt->hangup(chan);
00742    } else
00743       if (option_debug)
00744          ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
00745          
00746    ast_mutex_unlock(&chan->lock);
00747    manager_event(EVENT_FLAG_CALL, "Hangup", 
00748          "Channel: %s\r\n"
00749          "Uniqueid: %s\r\n"
00750          "Cause: %i\r\n",
00751          chan->name, chan->uniqueid, chan->hangupcause);
00752    ast_channel_free(chan);
00753    return res;
00754 }

int ast_indicate ( struct ast_channel chan,
int  condition 
)

Indicates condition of channel.

Parameters:
chan channel to change the indication
condition which condition to indicate on the channel Indicate a condition such as AST_CONTROL_BUSY, AST_CONTROL_RINGING, or AST_CONTROL_CONGESTION on a channel Returns 0 on success, -1 on failure

Definition at line 1411 of file channel.c.

01412 {
01413    int res = -1;
01414    /* Stop if we're a zombie or need a soft hangup */
01415    if (chan->zombie || ast_check_hangup(chan)) 
01416       return -1;
01417    ast_mutex_lock(&chan->lock);
01418    if (chan->pvt->indicate)
01419       res = chan->pvt->indicate(chan, condition);
01420    ast_mutex_unlock(&chan->lock);
01421    if (!chan->pvt->indicate || res) {
01422       /*
01423        * Device does not support (that) indication, lets fake
01424        * it by doing our own tone generation. (PM2002)
01425        */
01426       if (condition >= 0) {
01427          const struct tone_zone_sound *ts = NULL;
01428          switch (condition) {
01429           case AST_CONTROL_RINGING:
01430             ts = ast_get_indication_tone(chan->zone, "ring");
01431             break;
01432           case AST_CONTROL_BUSY:
01433             ts = ast_get_indication_tone(chan->zone, "busy");
01434             break;
01435           case AST_CONTROL_CONGESTION:
01436             ts = ast_get_indication_tone(chan->zone, "congestion");
01437             break;
01438          }
01439          if (ts && ts->data[0]) {
01440             ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
01441             ast_playtones_start(chan,0,ts->data, 1);
01442             res = 0;
01443          } else if (condition == AST_CONTROL_PROGRESS) {
01444             /* ast_playtones_stop(chan); */
01445          } else if (condition == AST_CONTROL_PROCEEDING) {
01446             /* Do nothing, really */
01447          } else {
01448             /* not handled */
01449             ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
01450             res = -1;
01451          }
01452       }
01453       else ast_playtones_stop(chan);
01454    }
01455    return res;
01456 }

int ast_parse_device_state ( char *  device  ) 

Search the Channels by Name.

Parameters:
device like a dialstring Search the Device in active channels by compare the channelname against the devicename. Compared are only the first chars to the first '-' char. Returns an AST_DEVICE_UNKNOWN if no channel found or AST_DEVICE_INUSE if a channel is found

Definition at line 1918 of file channel.c.

01919 {
01920    char name[AST_CHANNEL_NAME] = "";
01921    char *cut;
01922    struct ast_channel *chan;
01923 
01924    chan = ast_channel_walk_locked(NULL);
01925    while (chan) {
01926       strncpy(name, chan->name, sizeof(name)-1);
01927       ast_mutex_unlock(&chan->lock);
01928       cut = strchr(name,'-');
01929       if (cut)
01930               *cut = 0;
01931       if (!strcmp(name, device))
01932               return AST_DEVICE_INUSE;
01933       chan = ast_channel_walk_locked(chan);
01934    }
01935    return AST_DEVICE_UNKNOWN;
01936 }

int ast_prod ( struct ast_channel chan  ) 

Definition at line 1549 of file channel.c.

01550 {
01551    struct ast_frame a = { AST_FRAME_VOICE };
01552    char nothing[128];
01553    /* Send an empty audio frame to get things moving */
01554    if (chan->_state != AST_STATE_UP) {
01555       ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
01556       a.subclass = chan->pvt->rawwriteformat;
01557       a.data = nothing + AST_FRIENDLY_OFFSET;
01558       if (ast_write(chan, &a))
01559          ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name);
01560    }
01561    return 0;
01562 }

struct ast_frame* ast_read ( struct ast_channel chan  )  [read]

Reads a frame.

Parameters:
chan channel to read a frame from Read a frame. Returns a frame, or NULL on error. If it returns NULL, you best just stop reading frames and assume the channel has been disconnected.

Definition at line 1192 of file channel.c.

01193 {
01194    struct ast_frame *f = NULL;
01195    int blah;
01196 #ifdef ZAPTEL_OPTIMIZATIONS
01197    int (*func)(void *);
01198    void *data;
01199    int res;
01200 #endif
01201    static struct ast_frame null_frame = 
01202    {
01203       AST_FRAME_NULL,
01204    };
01205    
01206    ast_mutex_lock(&chan->lock);
01207    if (chan->masq) {
01208       if (ast_do_masquerade(chan)) {
01209          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01210          f = NULL;
01211       } else
01212          f =  &null_frame;
01213       ast_mutex_unlock(&chan->lock);
01214       return f;
01215    }
01216 
01217    /* Stop if we're a zombie or need a soft hangup */
01218    if (chan->zombie || ast_check_hangup(chan)) {
01219       if (chan->generator)
01220          ast_deactivate_generator(chan);
01221       ast_mutex_unlock(&chan->lock);
01222       return NULL;
01223    }
01224 
01225    if (!chan->deferdtmf && !ast_strlen_zero(chan->dtmfq)) {
01226       /* We have DTMF that has been deferred.  Return it now */
01227       chan->dtmff.frametype = AST_FRAME_DTMF;
01228       chan->dtmff.subclass = chan->dtmfq[0];
01229       /* Drop first digit */
01230       memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
01231       ast_mutex_unlock(&chan->lock);
01232       return &chan->dtmff;
01233    }
01234    
01235    /* Read and ignore anything on the alertpipe, but read only
01236       one sizeof(blah) per frame that we send from it */
01237    if (chan->pvt->alertpipe[0] > -1) {
01238       read(chan->pvt->alertpipe[0], &blah, sizeof(blah));
01239    }
01240 #ifdef ZAPTEL_OPTIMIZATIONS
01241    if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) {
01242       chan->exception = 0;
01243       blah = -1;
01244       /* IF we can't get event, assume it's an expired as-per the old interface */
01245       res = ioctl(chan->timingfd, ZT_GETEVENT, &blah);
01246       if (res) 
01247          blah = ZT_EVENT_TIMER_EXPIRED;
01248 
01249       if (blah == ZT_EVENT_TIMER_PING) {
01250 #if 0
01251          ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
01252 #endif         
01253          if (!chan->pvt->readq || !chan->pvt->readq->next) {
01254             /* Acknowledge PONG unless we need it again */
01255 #if 0
01256             ast_log(LOG_NOTICE, "Sending a PONG!\n");
01257 #endif            
01258             if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) {
01259                ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno));
01260             }
01261          }
01262       } else if (blah == ZT_EVENT_TIMER_EXPIRED) {
01263          ioctl(chan->timingfd, ZT_TIMERACK, &blah);
01264          func = chan->timingfunc;
01265          data = chan->timingdata;
01266          ast_mutex_unlock(&chan->lock);
01267          if (func) {
01268 #if 0
01269             ast_log(LOG_DEBUG, "Calling private function\n");
01270 #endif         
01271             func(data);
01272          } else {
01273             blah = 0;
01274             ast_mutex_lock(&chan->lock);
01275             ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
01276             chan->timingdata = NULL;
01277             ast_mutex_unlock(&chan->lock);
01278          }
01279          f =  &null_frame;
01280          return f;
01281       } else
01282          ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
01283    }
01284 #endif
01285    /* Check for pending read queue */
01286    if (chan->pvt->readq) {
01287       f = chan->pvt->readq;
01288       chan->pvt->readq = f->next;
01289       /* Interpret hangup and return NULL */
01290       if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
01291          ast_frfree(f);
01292          f = NULL;
01293       }
01294    } else {
01295       chan->blocker = pthread_self();
01296       if (chan->exception) {
01297          if (chan->pvt->exception) 
01298             f = chan->pvt->exception(chan);
01299          else {
01300             ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
01301             f = &null_frame;
01302          }
01303          /* Clear the exception flag */
01304          chan->exception = 0;
01305       } else
01306       if (chan->pvt->read)
01307          f = chan->pvt->read(chan);
01308       else
01309          ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
01310    }
01311 
01312 
01313    if (f && (f->frametype == AST_FRAME_VOICE)) {
01314       if (!(f->subclass & chan->nativeformats)) {
01315          /* This frame can't be from the current native formats -- drop it on the
01316             floor */
01317          ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", chan->name, ast_getformatname(f->subclass), ast_getformatname(chan->nativeformats));
01318          ast_frfree(f);
01319          f = &null_frame;
01320       } else {
01321          if (chan->monitor && chan->monitor->read_stream ) {
01322 #ifndef MONITOR_CONSTANT_DELAY
01323             int jump = chan->outsmpl - chan->insmpl - 2 * f->samples;
01324             if (jump >= 0) {
01325                if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01326                   ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01327                chan->insmpl += jump + 2 * f->samples;
01328             } else
01329                chan->insmpl+= f->samples;
01330 #else
01331             int jump = chan->outsmpl - chan->insmpl;
01332             if (jump - MONITOR_DELAY >= 0) {
01333                if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01334                   ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01335                chan->insmpl += jump;
01336             } else
01337                chan->insmpl += f->samples;
01338 #endif
01339             if (ast_writestream(chan->monitor->read_stream, f) < 0)
01340                ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
01341          }
01342          if (chan->pvt->readtrans) {
01343             f = ast_translate(chan->pvt->readtrans, f, 1);
01344             if (!f)
01345                f = &null_frame;
01346          }
01347       }
01348    }
01349 
01350    /* Make sure we always return NULL in the future */
01351    if (!f) {
01352       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01353       if (chan->generator)
01354          ast_deactivate_generator(chan);
01355       /* End the CDR if appropriate */
01356       if (chan->cdr)
01357          ast_cdr_end(chan->cdr);
01358    } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
01359       if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
01360          chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
01361       else
01362          ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
01363       f = &null_frame;
01364    } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
01365       if (chan->_state == AST_STATE_UP) {
01366          ast_log(LOG_DEBUG, "Dropping duplicate answer!\n");
01367          f = &null_frame;
01368       }
01369       /* Answer the CDR */
01370       ast_setstate(chan, AST_STATE_UP);
01371       ast_cdr_answer(chan->cdr);
01372    } 
01373 
01374    /* Run any generator sitting on the line */
01375    if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
01376       /* Mask generator data temporarily and apply.  If there is a timing function, it
01377          will be calling the generator instead */
01378       void *tmp;
01379       int res;
01380       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
01381       if (chan->timingfunc) {
01382          ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
01383          ast_settimeout(chan, 0, NULL, NULL);
01384       }
01385       tmp = chan->generatordata;
01386       chan->generatordata = NULL;
01387       generate = chan->generator->generate;
01388       res = generate(chan, tmp, f->datalen, f->samples);
01389       chan->generatordata = tmp;
01390       if (res) {
01391          ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
01392          ast_deactivate_generator(chan);
01393       }
01394    } else if (f && (f->frametype == AST_FRAME_CNG)) {
01395       if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) {
01396          ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n");
01397          ast_settimeout(chan, 160, generator_force, chan);
01398       }
01399    }
01400    /* High bit prints debugging */
01401    if (chan->fin & 0x80000000)
01402       ast_frame_dump(chan->name, f, "<<");
01403    if ((chan->fin & 0x7fffffff) == 0x7fffffff)
01404       chan->fin &= 0x80000000;
01405    else
01406       chan->fin++;
01407    ast_mutex_unlock(&chan->lock);
01408    return f;
01409 }

int ast_readstring ( struct ast_channel c,
char *  s,
int  len,
int  timeout,
int  rtimeout,
char *  enders 
)

Reads multiple digits.

Parameters:
c channel to read from
s string to read in to. Must be at least the size of your length
len how many digits to read (maximum)
timeout how long to timeout between digits
rtimeout timeout to wait on the first digit
enders digits to end the string Read in a digit string "s", max length "len", maximum timeout between digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout for the first digit. Returns 0 on normal return, or 1 on a timeout. In the case of a timeout, any digits that were read before the timeout will still be available in s. RETURNS 2 in full version when ctrlfd is available, NOT 1

Definition at line 2012 of file channel.c.

02013 {
02014    int pos=0;
02015    int to = ftimeout;
02016    int d;
02017    /* XXX Merge with full version? XXX */
02018    /* Stop if we're a zombie or need a soft hangup */
02019    if (c->zombie || ast_check_hangup(c)) 
02020       return -1;
02021    if (!len)
02022       return -1;
02023    do {
02024       if (c->stream) {
02025          d = ast_waitstream(c, AST_DIGIT_ANY);
02026          ast_stopstream(c);
02027          usleep(1000);
02028          if (!d)
02029             d = ast_waitfordigit(c, to);
02030       } else {
02031          d = ast_waitfordigit(c, to);
02032       }
02033       if (d < 0)
02034          return -1;
02035       if (d == 0) {
02036          s[pos]='\0';
02037          return 1;
02038       }
02039       if (!strchr(enders, d))
02040          s[pos++] = d;
02041       if (strchr(enders, d) || (pos >= len)) {
02042          s[pos]='\0';
02043          return 0;
02044       }
02045       to = timeout;
02046    } while(1);
02047    /* Never reached */
02048    return 0;
02049 }

int ast_readstring_full ( struct ast_channel c,
char *  s,
int  len,
int  timeout,
int  rtimeout,
char *  enders,
int  audiofd,
int  ctrlfd 
)

Definition at line 2051 of file channel.c.

02052 {
02053    int pos=0;
02054    int to = ftimeout;
02055    int d;
02056    /* Stop if we're a zombie or need a soft hangup */
02057    if (c->zombie || ast_check_hangup(c)) 
02058       return -1;
02059    if (!len)
02060       return -1;
02061    do {
02062       if (c->stream) {
02063          d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
02064          ast_stopstream(c);
02065          usleep(1000);
02066          if (!d)
02067             d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02068       } else {
02069          d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02070       }
02071       if (d < 0)
02072          return -1;
02073       if (d == 0) {
02074          s[pos]='\0';
02075          return 1;
02076       }
02077       if (d == 1) {
02078          s[pos]='\0';
02079          return 2;
02080       }
02081       if (!strchr(enders, d))
02082          s[pos++] = d;
02083       if (strchr(enders, d) || (pos >= len)) {
02084          s[pos]='\0';
02085          return 0;
02086       }
02087       to = timeout;
02088    } while(1);
02089    /* Never reached */
02090    return 0;
02091 }

int ast_recvchar ( struct ast_channel chan,
int  timeout 
)

Definition at line 1458 of file channel.c.

01459 {
01460    int res,ourto,c;
01461    struct ast_frame *f;
01462    
01463    ourto = timeout;
01464    for(;;)
01465       {
01466       if (ast_check_hangup(chan)) return -1;
01467       res = ast_waitfor(chan,ourto);
01468       if (res <= 0) /* if timeout */
01469          {
01470          return 0;
01471          }
01472       ourto = res;
01473       f = ast_read(chan);
01474       if (f == NULL) return -1; /* if hangup */
01475       if ((f->frametype == AST_FRAME_CONTROL) &&
01476           (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
01477       if (f->frametype == AST_FRAME_TEXT)  /* if a text frame */
01478          {
01479          c = *((char *)f->data);  /* get the data */
01480          ast_frfree(f);
01481          return(c);
01482          }
01483       ast_frfree(f);
01484    }
01485 }

struct ast_channel* ast_request ( char *  type,
int  format,
void *  data 
) [read]

Requests a channel.

Parameters:
type type of channel to request
format requested channel format
data data to pass to the channel requester Request a channel of a given type, with data as optional information used by the low level module Returns an ast_channel on success, NULL on failure.

Definition at line 1873 of file channel.c.

01874 {
01875    struct chanlist *chan;
01876    struct ast_channel *c = NULL;
01877    int capabilities;
01878    int fmt;
01879    int res;
01880    if (ast_mutex_lock(&chlock)) {
01881       ast_log(LOG_WARNING, "Unable to lock channel list\n");
01882       return NULL;
01883    }
01884    chan = backends;
01885    while(chan) {
01886       if (!strcasecmp(type, chan->type)) {
01887          capabilities = chan->capabilities;
01888          fmt = format;
01889          res = ast_translator_best_choice(&fmt, &capabilities);
01890          if (res < 0) {
01891             ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
01892             ast_mutex_unlock(&chlock);
01893             return NULL;
01894          }
01895          ast_mutex_unlock(&chlock);
01896          if (chan->requester)
01897             c = chan->requester(type, capabilities, data);
01898          if (c) {
01899             if (c->_state == AST_STATE_DOWN) {
01900                manager_event(EVENT_FLAG_CALL, "Newchannel",
01901                "Channel: %s\r\n"
01902                "State: %s\r\n"
01903                "CallerID: %s\r\n"
01904                "Uniqueid: %s\r\n",
01905                c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid);
01906             }
01907          }
01908          return c;
01909       }
01910       chan = chan->next;
01911    }
01912    if (!chan)
01913       ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
01914    ast_mutex_unlock(&chlock);
01915    return c;
01916 }

struct ast_channel* ast_request_and_dial ( char *  type,
int  format,
void *  data,
int  timeout,
int *  reason,
char *  callerid 
) [read]

Parameters:
type type of channel to request
format requested channel format
data data to pass to the channel requester
timeout maximum amount of time to wait for an answer
why unsuccessful (if unsuceessful) Request a channel of a given type, with data as optional information used by the low level module and attempt to place a call on it Returns an ast_channel on success or no answer, NULL on failure. Check the value of chan->_state to know if the call was answered or not.

Definition at line 1868 of file channel.c.

01869 {
01870    return __ast_request_and_dial(type, format, data, timeout, outstate, callerid, NULL);
01871 }

int ast_safe_sleep ( struct ast_channel chan,
int  ms 
)

Wait for a specied amount of time, looking for hangups.

Parameters:
chan channel to wait for
ms length of time in milliseconds to sleep Waits for a specified amount of time, servicing the channel as required. returns -1 on hangup, otherwise 0.

Definition at line 544 of file channel.c.

00545 {
00546    struct ast_frame *f;
00547    while(ms > 0) {
00548       ms = ast_waitfor(chan, ms);
00549       if (ms <0)
00550          return -1;
00551       if (ms > 0) {
00552          f = ast_read(chan);
00553          if (!f)
00554             return -1;
00555          ast_frfree(f);
00556       }
00557    }
00558    return 0;
00559 }

int ast_safe_sleep_conditional ( struct ast_channel chan,
int  ms,
int(*)(void *)  cond,
void *  data 
)

Wait for a specied amount of time, looking for hangups and a condition argument.

Parameters:
chan channel to wait for
ms length of time in milliseconds to sleep
cond a function pointer for testing continue condition
data argument to be passed to the condition test function Waits for a specified amount of time, servicing the channel as required. If cond returns 0, this function returns. returns -1 on hangup, otherwise 0.

Definition at line 523 of file channel.c.

00525 {
00526    struct ast_frame *f;
00527 
00528    while(ms > 0) {
00529       if( cond && ((*cond)(data) == 0 ) )
00530          return 0;
00531       ms = ast_waitfor(chan, ms);
00532       if (ms <0)
00533          return -1;
00534       if (ms > 0) {
00535          f = ast_read(chan);
00536          if (!f)
00537             return -1;
00538          ast_frfree(f);
00539       }
00540    }
00541    return 0;
00542 }

int ast_senddigit ( struct ast_channel chan,
char  digit 
)

Receives a text character from a channel.

Parameters:
chan channel to act upon
timeout timeout in milliseconds (0 for infinite wait) Read a char of text from a channel Returns 0 on success, -1 on failure

Definition at line 1544 of file channel.c.

01545 {
01546    return do_senddigit(chan, digit);
01547 }

int ast_sendtext ( struct ast_channel chan,
char *  text 
)

Sends text to a channel.

Parameters:
chan channel to act upon
text string of text to send on the channel Write text to a display on a channel Returns 0 on success, -1 on failure

Definition at line 1487 of file channel.c.

01488 {
01489    int res = 0;
01490    /* Stop if we're a zombie or need a soft hangup */
01491    if (chan->zombie || ast_check_hangup(chan)) 
01492       return -1;
01493    CHECK_BLOCKING(chan);
01494    if (chan->pvt->send_text)
01495       res = chan->pvt->send_text(chan, text);
01496    chan->blocking = 0;
01497    return res;
01498 }

void ast_set_callerid ( struct ast_channel chan,
char *  callerid,
int  anitoo 
)

Definition at line 2429 of file channel.c.

02430 {
02431    if (chan->callerid)
02432       free(chan->callerid);
02433    if (anitoo && chan->ani)
02434       free(chan->ani);
02435    if (callerid) {
02436       chan->callerid = strdup(callerid);
02437       if (anitoo)
02438          chan->ani = strdup(callerid);
02439    } else {
02440       chan->callerid = NULL;
02441       if (anitoo)
02442          chan->ani = NULL;
02443    }
02444    if (chan->cdr)
02445       ast_cdr_setcid(chan->cdr, chan);
02446    manager_event(EVENT_FLAG_CALL, "Newcallerid", 
02447             "Channel: %s\r\n"
02448             "CallerID: %s\r\n"
02449             "Uniqueid: %s\r\n",
02450             chan->name, chan->callerid ? 
02451             chan->callerid : "<Unknown>",
02452             chan->uniqueid);
02453 }

int ast_set_read_format ( struct ast_channel chan,
int  format 
)

Sets read format on channel chan.

Parameters:
chan channel to change
format format to change to Set read format for channel to whichever component of "format" is best. Returns 0 on success, -1 on failure

Definition at line 1724 of file channel.c.

01725 {
01726    int fmt;
01727    int native;
01728    int res;
01729    
01730    ast_mutex_lock(&chan->lock);
01731    native = chan->nativeformats;
01732    fmt = fmts;
01733    /* Find a translation path from the native read format to one of the user's read formats */
01734    res = ast_translator_best_choice(&fmt, &native);
01735    if (res < 0) {
01736       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01737          ast_getformatname(chan->nativeformats), ast_getformatname(fmts));
01738       ast_mutex_unlock(&chan->lock);
01739       return -1;
01740    }
01741    
01742    /* Now we have a good choice for both.  We'll write using our native format. */
01743    chan->pvt->rawreadformat = native;
01744    /* User perspective is fmt */
01745    chan->readformat = fmt;
01746    /* Free any read translation we have right now */
01747    if (chan->pvt->readtrans)
01748       ast_translator_free_path(chan->pvt->readtrans);
01749    /* Build a translation path from the raw read format to the user reading format */
01750    chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
01751    if (option_debug)
01752       ast_log(LOG_DEBUG, "Set channel %s to read format %s\n", 
01753          chan->name, ast_getformatname(chan->readformat));
01754    ast_mutex_unlock(&chan->lock);
01755    return 0;
01756 }

int ast_set_write_format ( struct ast_channel chan,
int  format 
)

Sets write format on channel chan.

Parameters:
chan channel to change
format new format for writing Set write format for channel to whichever compoent of "format" is best. Returns 0 on success, -1 on failure

Definition at line 1691 of file channel.c.

01692 {
01693    int fmt;
01694    int native;
01695    int res;
01696    
01697    ast_mutex_lock(&chan->lock);
01698    native = chan->nativeformats;
01699    fmt = fmts;
01700    
01701    res = ast_translator_best_choice(&native, &fmt);
01702    if (res < 0) {
01703       ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01704          ast_getformatname(fmts), ast_getformatname(chan->nativeformats));
01705       ast_mutex_unlock(&chan->lock);
01706       return -1;
01707    }
01708    
01709    /* Now we have a good choice for both.  We'll write using our native format. */
01710    chan->pvt->rawwriteformat = native;
01711    /* User perspective is fmt */
01712    chan->writeformat = fmt;
01713    /* Free any write translation we have right now */
01714    if (chan->pvt->writetrans)
01715       ast_translator_free_path(chan->pvt->writetrans);
01716    /* Build a translation path from the user write format to the raw writing format */
01717    chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
01718    if (option_debug)
01719       ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat));
01720    ast_mutex_unlock(&chan->lock);
01721    return 0;
01722 }

int ast_settimeout ( struct ast_channel c,
int  samples,
int(*)(void *data)  func,
void *  data 
)

Definition at line 1119 of file channel.c.

01120 {
01121    int res = -1;
01122 #ifdef ZAPTEL_OPTIMIZATIONS
01123    if (c->timingfd > -1) {
01124       if (!func) {
01125          samples = 0;
01126          data = 0;
01127       }
01128       ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples);
01129       res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples);
01130       c->timingfunc = func;
01131       c->timingdata = data;
01132    }
01133 #endif   
01134    return res;
01135 }

int ast_shutting_down ( void   ) 

Returns non-zero if Asterisk is being shut down

Definition at line 139 of file channel.c.

00140 {
00141    return shutting_down;
00142 }

int ast_softhangup ( struct ast_channel chan,
int  cause 
)

Softly hangup up a channel.

Parameters:
chan channel to be soft-hung-up Call the protocol layer, but don't destroy the channel structure (use this if you are trying to safely hangup a channel managed by another thread. Returns 0 regardless

Definition at line 668 of file channel.c.

00669 {
00670    int res;
00671    ast_mutex_lock(&chan->lock);
00672    res = ast_softhangup_nolock(chan, cause);
00673    ast_mutex_unlock(&chan->lock);
00674    return res;
00675 }

int ast_softhangup_nolock ( struct ast_channel chan,
int  cause 
)

Definition at line 653 of file channel.c.

00654 {
00655    int res = 0;
00656    struct ast_frame f = { AST_FRAME_NULL };
00657    if (option_debug)
00658       ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name);
00659    /* Inform channel driver that we need to be hung up, if it cares */
00660    chan->_softhangup |= cause;
00661    ast_queue_frame(chan, &f);
00662    /* Interrupt any poll call or such */
00663    if (chan->blocking)
00664       pthread_kill(chan->blocker, SIGURG);
00665    return res;
00666 }

char* ast_state2str ( int  state  ) 

Gives the string form of a given state.

Parameters:
state state to get the name of Give a name to a state Pretty self explanatory. Returns the text form of the binary state given

Definition at line 205 of file channel.c.

00206 {
00207    /* XXX Not reentrant XXX */
00208    static char localtmp[256];
00209    switch(state) {
00210    case AST_STATE_DOWN:
00211       return "Down";
00212    case AST_STATE_RESERVED:
00213       return "Rsrvd";
00214    case AST_STATE_OFFHOOK:
00215       return "OffHook";
00216    case AST_STATE_DIALING:
00217       return "Dialing";
00218    case AST_STATE_RING:
00219       return "Ring";
00220    case AST_STATE_RINGING:
00221       return "Ringing";
00222    case AST_STATE_UP:
00223       return "Up";
00224    case AST_STATE_BUSY:
00225       return "Busy";
00226    default:
00227       snprintf(localtmp, sizeof(localtmp), "Unknown (%d)\n", state);
00228       return localtmp;
00229    }
00230 }

int ast_tonepair ( struct ast_channel chan,
int  freq1,
int  freq2,
int  duration,
int  vol 
)

Play a tone pair for a given amount of time

Definition at line 2890 of file channel.c.

02891 {
02892    struct ast_frame *f;
02893    int res;
02894    if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
02895       return res;
02896 
02897    /* Give us some wiggle room */
02898    while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
02899       f = ast_read(chan);
02900       if (f)
02901          ast_frfree(f);
02902       else
02903          return -1;
02904    }
02905    return 0;
02906 }

int ast_tonepair_start ( struct ast_channel chan,
int  freq1,
int  freq2,
int  duration,
int  vol 
)

Start a tone going

Definition at line 2870 of file channel.c.

02871 {
02872    struct tonepair_def d = { 0, };
02873    d.freq1 = freq1;
02874    d.freq2 = freq2;
02875    d.duration = duration;
02876    if (vol < 1)
02877       d.vol = 8192;
02878    else
02879       d.vol = vol;
02880    if (ast_activate_generator(chan, &tonepair, &d))
02881       return -1;
02882    return 0;
02883 }

void ast_tonepair_stop ( struct ast_channel chan  ) 

Stop a tone from playing

Definition at line 2885 of file channel.c.

02886 {
02887    ast_deactivate_generator(chan);
02888 }

int ast_transfer ( struct ast_channel chan,
char *  dest 
)

Definition at line 1992 of file channel.c.

01993 {
01994    /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
01995       If the remote end does not answer within the timeout, then do NOT hang up, but 
01996       return anyway.  */
01997    int res = -1;
01998    /* Stop if we're a zombie or need a soft hangup */
01999    ast_mutex_lock(&chan->lock);
02000    if (!chan->zombie && !ast_check_hangup(chan)) {
02001       if (chan->pvt->transfer) {
02002          res = chan->pvt->transfer(chan, dest);
02003          if (!res)
02004             res = 1;
02005       } else
02006          res = 0;
02007    }
02008    ast_mutex_unlock(&chan->lock);
02009    return res;
02010 }

int ast_waitfor ( struct ast_channel chan,
int  ms 
)

Wait for input on a channel.

Parameters:
chan channel to wait on
ms length of time to wait on the channel Wait for input on a channel for a given # of milliseconds (<0 for indefinite). Returns < 0 on failure, 0 if nothing ever arrived, and the # of ms remaining otherwise

Definition at line 1078 of file channel.c.

01079 {
01080    struct ast_channel *chan;
01081    int oldms = ms;
01082    chan = ast_waitfor_n(&c, 1, &ms);
01083    if (ms < 0) {
01084       if (oldms < 0)
01085          return 0;
01086       else
01087          return -1;
01088    }
01089    return ms;
01090 }

struct ast_channel* ast_waitfor_n ( struct ast_channel **  chan,
int  n,
int *  ms 
) [read]

Waits for input on a group of channels.

Wait for input on an array of channels for a given # of milliseconds. Return channel with activity, or NULL if none has activity. time "ms" is modified in-place, if applicable

Definition at line 1073 of file channel.c.

01074 {
01075    return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
01076 }

int ast_waitfor_n_fd ( int *  fds,
int  n,
int *  ms,
int *  exception 
)

Waits for input on an fd.

This version works on fd's only. Be careful with it.

Definition at line 869 of file channel.c.

00870 {
00871    /* Wait for x amount of time on a file descriptor to have input.  */
00872    struct timeval start, now;
00873    int res;
00874    int x, y;
00875    int winner = -1;
00876    int spoint;
00877    struct pollfd *pfds;
00878    
00879    pfds = alloca(sizeof(struct pollfd) * n);
00880    if (!pfds) {
00881       ast_log(LOG_WARNING, "alloca failed!  bad things will happen.\n");
00882       return -1;
00883    }
00884    if (*ms > 0)
00885       gettimeofday(&start, NULL);
00886    y = 0;
00887    for (x=0;x<n;x++) {
00888       if (fds[x] > -1) {
00889          pfds[y].fd = fds[x];
00890          pfds[y].events = POLLIN | POLLPRI;
00891          y++;
00892       }
00893    }
00894    res = poll(pfds, y, *ms);
00895    if (res < 0) {
00896       /* Simulate a timeout if we were interrupted */
00897       if (errno != EINTR)
00898          *ms = -1;
00899       else
00900          *ms = 0;
00901       return -1;
00902    }
00903    spoint = 0;
00904    for (x=0;x<n;x++) {
00905       if (fds[x] > -1) {
00906          if ((res = ast_fdisset(pfds, fds[x], y, &spoint))) {
00907             winner = fds[x];
00908             if (exception) {
00909                if (res & POLLPRI)
00910                   *exception = -1;
00911                else
00912                   *exception = 0;
00913             }
00914          }
00915       }
00916    }
00917    if (*ms > 0) {
00918       long passed;
00919       gettimeofday(&now, NULL);
00920       passed = (now.tv_sec - start.tv_sec) * 1000;
00921       passed += (now.tv_usec - start.tv_usec) / 1000;
00922       if (passed <= *ms)
00923          *ms -= passed;
00924       else
00925          *ms = 0;
00926    }
00927    return winner;
00928 }

struct ast_channel* ast_waitfor_nandfds ( struct ast_channel **  chan,
int  n,
int *  fds,
int  nfds,
int *  exception,
int *  outfd,
int *  ms 
) [read]

Waits for activity on a group of channels.

Parameters:
chan an array of pointers to channels
n number of channels that are to be waited upon
fds an array of fds to wait upon
nfds the number of fds to wait upon
exception exception flag
outfd fd that had activity on it
ms how long the wait was Big momma function here. Wait for activity on any of the n channels, or any of the nfds file descriptors. Returns the channel with activity, or NULL on error or if an FD came first. If the FD came first, it will be returned in outfd, otherwise, outfd will be -1

Definition at line 930 of file channel.c.

00932 {
00933    /* Wait for x amount of time on a file descriptor to have input.  */
00934    struct timeval start, end;
00935    struct pollfd *pfds;
00936    int res;
00937    long rms;
00938    int x, y, max;
00939    int spoint;
00940    time_t now = 0;
00941    long whentohangup = 0, havewhen = 0, diff;
00942    struct ast_channel *winner = NULL;
00943 
00944    pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds));
00945    if (!pfds) {
00946       ast_log(LOG_WARNING, "alloca failed!  bad things will happen.\n");
00947       *outfd = -1;
00948       return NULL;
00949    }
00950 
00951    if (outfd)
00952       *outfd = -99999;
00953    if (exception)
00954       *exception = 0;
00955    
00956    /* Perform any pending masquerades */
00957    for (x=0;x<n;x++) {
00958       ast_mutex_lock(&c[x]->lock);
00959       if (c[x]->whentohangup) {
00960          if (!havewhen)
00961             time(&now);
00962          diff = c[x]->whentohangup - now;
00963          if (!havewhen || (diff < whentohangup)) {
00964             havewhen++;
00965             whentohangup = diff;
00966          }
00967       }
00968       if (c[x]->masq) {
00969          if (ast_do_masquerade(c[x])) {
00970             ast_log(LOG_WARNING, "Masquerade failed\n");
00971             *ms = -1;
00972             ast_mutex_unlock(&c[x]->lock);
00973             return NULL;
00974          }
00975       }
00976       ast_mutex_unlock(&c[x]->lock);
00977    }
00978 
00979    rms = *ms;
00980    
00981    if (havewhen) {
00982       if ((*ms < 0) || (whentohangup * 1000 < *ms)) {
00983          rms =  whentohangup * 1000;
00984       }
00985    }
00986    max = 0;
00987    for (x=0;x<n;x++) {
00988       for (y=0;y<AST_MAX_FDS;y++) {
00989          if (c[x]->fds[y] > -1) {
00990             pfds[max].fd = c[x]->fds[y];
00991             pfds[max].events = POLLIN | POLLPRI;
00992             max++;
00993          }
00994       }
00995       CHECK_BLOCKING(c[x]);
00996    }
00997    for (x=0;x<nfds; x++) {
00998       if (fds[x] > -1) {
00999          pfds[max].fd = fds[x];
01000          pfds[max].events = POLLIN | POLLPRI;
01001          max++;
01002       }
01003    }
01004    if (*ms > 0) 
01005       gettimeofday(&start, NULL);
01006    res = poll(pfds, max, rms);
01007    if (res < 0) {
01008       for (x=0;x<n;x++) 
01009          c[x]->blocking = 0;
01010       /* Simulate a timeout if we were interrupted */
01011       if (errno != EINTR)
01012          *ms = -1;
01013       else {
01014          /* Just an interrupt */
01015 #if 0
01016          *ms = 0;
01017 #endif         
01018       }
01019       return NULL;
01020    }
01021 
01022    if (havewhen)
01023       time(&now);
01024    spoint = 0;
01025    for (x=0;x<n;x++) {
01026       c[x]->blocking = 0;
01027       if (havewhen && c[x]->whentohangup && (now > c[x]->whentohangup)) {
01028          c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
01029          if (!winner)
01030             winner = c[x];
01031       }
01032       for (y=0;y<AST_MAX_FDS;y++) {
01033          if (c[x]->fds[y] > -1) {
01034             if ((res = ast_fdisset(pfds, c[x]->fds[y], max, &spoint))) {
01035                if (res & POLLPRI)
01036                   c[x]->exception = -1;
01037                else
01038                   c[x]->exception = 0;
01039                c[x]->fdno = y;
01040                winner = c[x];
01041             }
01042          }
01043       }
01044    }
01045    for (x=0;x<nfds;x++) {
01046       if (fds[x] > -1) {
01047          if ((res = ast_fdisset(pfds, fds[x], max, &spoint))) {
01048             if (outfd)
01049                *outfd = fds[x];
01050             if (exception) {  
01051                if (res & POLLPRI) 
01052                   *exception = -1;
01053                else
01054                   *exception = 0;
01055             }
01056             winner = NULL;
01057          }
01058       }  
01059    }
01060    if (*ms > 0) {
01061       long diff;
01062       gettimeofday(&end, NULL);
01063       diff = (end.tv_sec - start.tv_sec) * 1000;
01064       diff += (end.tv_usec - start.tv_usec) / 1000;
01065       if (diff < *ms)
01066          *ms -= diff;
01067       else
01068          *ms = 0;
01069    }
01070    return winner;
01071 }

int ast_waitfordigit ( struct ast_channel c,
int  ms 
)

Waits for a digit.

Parameters:
c channel to wait for a digit on
ms how many milliseconds to wait Wait for a digit. Returns <0 on error, 0 on no entry, and the digit on success.

Definition at line 1092 of file channel.c.

01093 {
01094    /* XXX Should I be merged with waitfordigit_full XXX */
01095    struct ast_frame *f;
01096    int result = 0;
01097    /* Stop if we're a zombie or need a soft hangup */
01098    if (c->zombie || ast_check_hangup(c)) 
01099       return -1;
01100    /* Wait for a digit, no more than ms milliseconds total. */
01101    while(ms && !result) {
01102       ms = ast_waitfor(c, ms);
01103       if (ms < 0) /* Error */
01104          result = -1; 
01105       else if (ms > 0) {
01106          /* Read something */
01107          f = ast_read(c);
01108          if (f) {
01109             if (f->frametype == AST_FRAME_DTMF) 
01110                result = f->subclass;
01111             ast_frfree(f);
01112          } else
01113             result = -1;
01114       }
01115    }
01116    return result;
01117 }

int ast_waitfordigit_full ( struct ast_channel c,
int  ms,
int  audiofd,
int  ctrlfd 
)

Definition at line 1136 of file channel.c.

01137 {
01138    struct ast_frame *f;
01139    struct ast_channel *rchan;
01140    int outfd;
01141    int res;
01142    /* Stop if we're a zombie or need a soft hangup */
01143    if (c->zombie || ast_check_hangup(c)) 
01144       return -1;
01145    /* Wait for a digit, no more than ms milliseconds total. */
01146    while(ms) {
01147       errno = 0;
01148       rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01149       if ((!rchan) && (outfd < 0) && (ms)) { 
01150          if (errno == 0 || errno == EINTR)
01151             continue;
01152          ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01153          return -1;
01154       } else if (outfd > -1) {
01155          /* The FD we were watching has something waiting */
01156          return 1;
01157       } else if (rchan) {
01158          f = ast_read(c);
01159          if(!f) {
01160             return -1;
01161          }
01162 
01163          switch(f->frametype) {
01164          case AST_FRAME_DTMF:
01165             res = f->subclass;
01166             ast_frfree(f);
01167             return res;
01168          case AST_FRAME_CONTROL:
01169             switch(f->subclass) {
01170             case AST_CONTROL_HANGUP:
01171                ast_frfree(f);
01172                return -1;
01173             case AST_CONTROL_RINGING:
01174             case AST_CONTROL_ANSWER:
01175                /* Unimportant */
01176                break;
01177             default:
01178                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass);
01179             }
01180          case AST_FRAME_VOICE:
01181             /* Write audio if appropriate */
01182             if (audiofd > -1)
01183                write(audiofd, f->data, f->datalen);
01184          }
01185          /* Ignore */
01186          ast_frfree(f);
01187       }
01188    }
01189    return 0; // Time is up
01190 }

int ast_write ( struct ast_channel chan,
struct ast_frame frame 
)

Write a frame to a channel.

Parameters:
chan destination channel of the frame
frame frame that will be written This function writes the given frame to the indicated channel. It returns 0 on success, -1 on failure.

Definition at line 1575 of file channel.c.

01576 {
01577    int res = -1;
01578    struct ast_frame *f = NULL;
01579    /* Stop if we're a zombie or need a soft hangup */
01580    ast_mutex_lock(&chan->lock);
01581    if (chan->zombie || ast_check_hangup(chan))  {
01582       ast_mutex_unlock(&chan->lock);
01583       return -1;
01584    }
01585    /* Handle any pending masquerades */
01586    if (chan->masq) {
01587       if (ast_do_masquerade(chan)) {
01588          ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01589          ast_mutex_unlock(&chan->lock);
01590          return -1;
01591       }
01592    }
01593    if (chan->masqr) {
01594       ast_mutex_unlock(&chan->lock);
01595       return 0;
01596    }
01597    if (chan->generatordata) {
01598       if (chan->writeinterrupt)
01599          ast_deactivate_generator(chan);
01600       else {
01601          ast_mutex_unlock(&chan->lock);
01602          return 0;
01603       }
01604    }
01605    /* High bit prints debugging */
01606    if (chan->fout & 0x80000000)
01607       ast_frame_dump(chan->name, fr, ">>");
01608    CHECK_BLOCKING(chan);
01609    switch(fr->frametype) {
01610    case AST_FRAME_CONTROL:
01611       /* XXX Interpret control frames XXX */
01612       ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
01613       break;
01614    case AST_FRAME_DTMF:
01615       chan->blocking = 0;
01616       ast_mutex_unlock(&chan->lock);
01617       res = do_senddigit(chan,fr->subclass);
01618       ast_mutex_lock(&chan->lock);
01619       CHECK_BLOCKING(chan);
01620       break;
01621    case AST_FRAME_TEXT:
01622       if (chan->pvt->send_text)
01623          res = chan->pvt->send_text(chan, (char *) fr->data);
01624       else
01625          res = 0;
01626       break;
01627    case AST_FRAME_HTML:
01628       if (chan->pvt->send_html)
01629          res = chan->pvt->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen);
01630       else
01631          res = 0;
01632       break;
01633    case AST_FRAME_VIDEO:
01634       /* XXX Handle translation of video codecs one day XXX */
01635       if (chan->pvt->write_video)
01636          res = chan->pvt->write_video(chan, fr);
01637       else
01638          res = 0;
01639       break;
01640    default:
01641       if (chan->pvt->write) {
01642          if (chan->pvt->writetrans) {
01643             f = ast_translate(chan->pvt->writetrans, fr, 0);
01644          } else
01645             f = fr;
01646          if (f) {
01647             res = chan->pvt->write(chan, f);
01648             if( chan->monitor &&
01649                   chan->monitor->write_stream &&
01650                   f && ( f->frametype == AST_FRAME_VOICE ) ) {
01651 #ifndef MONITOR_CONSTANT_DELAY
01652                int jump = chan->insmpl - chan->outsmpl - 2 * f->samples;
01653                if (jump >= 0) {
01654                   if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01655                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01656                   chan->outsmpl += jump + 2 * f->samples;
01657                } else
01658                   chan->outsmpl += f->samples;
01659 #else
01660                int jump = chan->insmpl - chan->outsmpl;
01661                if (jump - MONITOR_DELAY >= 0) {
01662                   if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01663                      ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01664                   chan->outsmpl += jump;
01665                } else
01666                   chan->outsmpl += f->samples;
01667 #endif
01668             if (ast_writestream(chan->monitor->write_stream, f) < 0)
01669                   ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
01670             }
01671          } else
01672             res = 0;
01673       }
01674    }
01675    if (f && (f != fr))
01676       ast_frfree(f);
01677    chan->blocking = 0;
01678    /* Consider a write failure to force a soft hangup */
01679    if (res < 0)
01680       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01681    else {
01682       if ((chan->fout & 0x7fffffff) == 0x7fffffff)
01683          chan->fout &= 0x80000000;
01684       else
01685          chan->fout++;
01686    }
01687    ast_mutex_unlock(&chan->lock);
01688    return res;
01689 }

int ast_write_video ( struct ast_channel chan,
struct ast_frame frame 
)

Write video frame to a channel.

Parameters:
chan destination channel of the frame
frame frame that will be written This function writes the given frame to the indicated channel. It returns 1 on success, 0 if not implemented, and -1 on failure.

Definition at line 1564 of file channel.c.

01565 {
01566    int res;
01567    if (!chan->pvt->write_video)
01568       return 0;
01569    res = ast_write(chan, fr);
01570    if (!res)
01571       res = 1;
01572    return res;
01573 }


Generated on Wed Oct 28 17:00:51 2009 for Asterisk by  doxygen 1.5.6