Sat Sep 16 07:28:13 2006

Asterisk developer's documentation


chan_local.c File Reference

Local Proxy Channel. More...

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/devicestate.h"
#include "asterisk/features.h"

Go to the source code of this file.

Data Structures

struct  local_pvt

Defines

#define IS_OUTBOUND(a, b)   (a == b->chan ? 1 : 0)

Functions

 AST_MUTEX_DEFINE_STATIC (locallock)
 AST_MUTEX_DEFINE_STATIC (usecnt_lock)
static void check_bridge (struct local_pvt *p, int isoutbound)
char * description ()
 Provides a description of the module.
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module ()
 Initialize the module.
static struct local_pvtlocal_alloc (char *data, int format)
static int local_answer (struct ast_channel *ast)
static int local_call (struct ast_channel *ast, char *dest, int timeout)
static int local_devicestate (void *data)
static int local_digit (struct ast_channel *ast, char digit)
static int local_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int local_hangup (struct ast_channel *ast)
static int local_indicate (struct ast_channel *ast, int condition)
static struct ast_channellocal_new (struct local_pvt *p, int state)
static int local_queue_frame (struct local_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us)
static struct ast_framelocal_read (struct ast_channel *ast)
static struct ast_channellocal_request (const char *type, int format, void *data, int *cause)
static int local_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen)
void local_watcher (char *exten, char *context)
static int local_write (struct ast_channel *ast, struct ast_frame *f)
static int locals_show (int fd, int argc, char **argv)
int reload ()
 Reload stuff.
int unload_module ()
 Cleanup all module structures, sockets, etc.
int usecount ()
 Provides a usecount.

Variables

static struct ast_cli_entry cli_show_locals
static const char desc [] = "Local Proxy Channel"
static struct ast_channel_tech local_tech
static struct local_pvtlocals
static char show_locals_usage []
static const char tdesc [] = "Local Proxy Channel Driver"
static const char type [] = "Local"
static int usecnt = 0
static int watchid


Detailed Description

Local Proxy Channel.

Definition in file chan_local.c.


Define Documentation

#define IS_OUTBOUND ( a,
 )     (a == b->chan ? 1 : 0)

Definition at line 72 of file chan_local.c.


Function Documentation

AST_MUTEX_DEFINE_STATIC ( locallock   ) 

AST_MUTEX_DEFINE_STATIC ( usecnt_lock   ) 

static void check_bridge ( struct local_pvt p,
int  isoutbound 
) [static]

Definition at line 220 of file chan_local.c.

References ast_channel::_bridge, ast_channel::_softhangup, local_pvt::alreadymasqed, ast_channel_masquerade(), ast_mutex_trylock(), ast_mutex_unlock(), local_pvt::chan, ast_channel::lock, local_pvt::nooptimization, local_pvt::owner, and ast_channel::readq.

Referenced by local_write().

00221 {
00222    if (p->alreadymasqed || p->nooptimization)
00223       return;
00224    if (!p->chan || !p->owner)
00225       return;
00226 
00227    /* only do the masquerade if we are being called on the outbound channel,
00228       if it has been bridged to another channel and if there are no pending
00229       frames on the owner channel (because they would be transferred to the
00230       outbound channel during the masquerade)
00231    */
00232    if (isoutbound && p->chan->_bridge /* Not ast_bridged_channel!  Only go one step! */ && !p->owner->readq) {
00233       /* Masquerade bridged channel into owner */
00234       /* Lock everything we need, one by one, and give up if
00235          we can't get everything.  Remember, we'll get another
00236          chance in just a little bit */
00237       if (!ast_mutex_trylock(&(p->chan->_bridge)->lock)) {
00238          if (!p->chan->_bridge->_softhangup) {
00239             if (!ast_mutex_trylock(&p->owner->lock)) {
00240                if (!p->owner->_softhangup) {
00241                   ast_channel_masquerade(p->owner, p->chan->_bridge);
00242                   p->alreadymasqed = 1;
00243                }
00244                ast_mutex_unlock(&p->owner->lock);
00245             }
00246             ast_mutex_unlock(&(p->chan->_bridge)->lock);
00247          }
00248       }
00249    /* We only allow masquerading in one 'direction'... it's important to preserve the state
00250       (group variables, etc.) that live on p->chan->_bridge (and were put there by the dialplan)
00251       when the local channels go away.
00252    */
00253 #if 0
00254    } else if (!isoutbound && p->owner && p->owner->_bridge && p->chan && !p->chan->readq) {
00255       /* Masquerade bridged channel into chan */
00256       if (!ast_mutex_trylock(&(p->owner->_bridge)->lock)) {
00257          if (!p->owner->_bridge->_softhangup) {
00258             if (!ast_mutex_trylock(&p->chan->lock)) {
00259                if (!p->chan->_softhangup) {
00260                   ast_channel_masquerade(p->chan, p->owner->_bridge);
00261                   p->alreadymasqed = 1;
00262                }
00263                ast_mutex_unlock(&p->chan->lock);
00264             }
00265          }
00266          ast_mutex_unlock(&(p->owner->_bridge)->lock);
00267       }
00268 #endif
00269    }
00270 }

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 704 of file chan_local.c.

00705 {
00706    return (char *) desc;
00707 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 699 of file chan_local.c.

References ASTERISK_GPL_KEY.

00700 {
00701    return ASTERISK_GPL_KEY;
00702 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 647 of file chan_local.c.

References ast_channel_register(), ast_cli_register(), ast_log(), ast_park_metermaid_add(), cli_show_locals, local_tech, local_watcher(), LOG_DEBUG, and LOG_ERROR.

00648 {
00649    /* Make sure we can register our channel type */
00650    if (ast_channel_register(&local_tech)) {
00651       ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
00652       return -1;
00653    }
00654    ast_cli_register(&cli_show_locals);
00655 
00656    /* Register watcher for parking lots in res_features */
00657    ast_log(LOG_DEBUG, "Adding metermaid watcher...\n");
00658    watchid = ast_park_metermaid_add(&local_watcher, NULL);
00659    return 0;
00660 }

static struct local_pvt* local_alloc ( char *  data,
int  format 
) [static]

Definition at line 508 of file chan_local.c.

References ast_exists_extension(), ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), free, locals, LOG_NOTICE, and malloc.

Referenced by local_request().

00509 {
00510    struct local_pvt *tmp;
00511    char *c;
00512    char *opts;
00513 
00514    tmp = malloc(sizeof(struct local_pvt));
00515    if (tmp) {
00516       memset(tmp, 0, sizeof(struct local_pvt));
00517       ast_mutex_init(&tmp->lock);
00518       strncpy(tmp->exten, data, sizeof(tmp->exten) - 1);
00519       opts = strchr(tmp->exten, '/');
00520       if (opts) {
00521          *opts='\0';
00522          opts++;
00523          if (strchr(opts, 'n'))
00524             tmp->nooptimization = 1;
00525       }
00526       c = strchr(tmp->exten, '@');
00527       if (c) {
00528          *c = '\0';
00529          c++;
00530          strncpy(tmp->context, c, sizeof(tmp->context) - 1);
00531       } else
00532          strncpy(tmp->context, "default", sizeof(tmp->context) - 1);
00533       tmp->reqformat = format;
00534       if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
00535          ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
00536          ast_mutex_destroy(&tmp->lock);
00537          free(tmp);
00538          tmp = NULL;
00539       } else {
00540          /* Add to list */
00541          ast_mutex_lock(&locallock);
00542          tmp->next = locals;
00543          locals = tmp;
00544          ast_mutex_unlock(&locallock);
00545       }
00546       
00547    }
00548    return tmp;
00549 }

static int local_answer ( struct ast_channel ast  )  [static]

Definition at line 202 of file chan_local.c.

References answer, AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), IS_OUTBOUND, local_queue_frame(), local_pvt::lock, LOG_WARNING, and ast_channel::tech_pvt.

00203 {
00204    struct local_pvt *p = ast->tech_pvt;
00205    int isoutbound;
00206    int res = -1;
00207 
00208    ast_mutex_lock(&p->lock);
00209    isoutbound = IS_OUTBOUND(ast, p);
00210    if (isoutbound) {
00211       /* Pass along answer since somebody answered us */
00212       struct ast_frame answer = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00213       res = local_queue_frame(p, isoutbound, &answer, ast);
00214    } else
00215       ast_log(LOG_WARNING, "Huh?  Local is being asked to answer?\n");
00216    ast_mutex_unlock(&p->lock);
00217    return res;
00218 }

static int local_call ( struct ast_channel ast,
char *  dest,
int  timeout 
) [static]

Definition at line 368 of file chan_local.c.

References ast_channel::accountcode, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_set_callerid(), ast_channel::cdrflags, local_pvt::chan, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_channel::language, local_pvt::launchedpbx, local_pvt::lock, LOG_ERROR, malloc, ast_var_t::name, local_pvt::owner, strdup, ast_channel::tech_pvt, ast_var_t::value, and ast_channel::varshead.

00369 {
00370    struct local_pvt *p = ast->tech_pvt;
00371    int res;
00372    struct ast_var_t *varptr = NULL, *new;
00373    size_t len, namelen;
00374    
00375    ast_mutex_lock(&p->lock);
00376 
00377    ast_set_callerid(p->chan,
00378       p->owner->cid.cid_num, p->owner->cid.cid_name,
00379       p->owner->cid.cid_ani);
00380 
00381    if (p->owner->cid.cid_rdnis)
00382       p->chan->cid.cid_rdnis = strdup(p->owner->cid.cid_rdnis);
00383    else
00384       p->chan->cid.cid_rdnis = NULL;
00385 
00386    p->chan->cid.cid_pres = p->owner->cid.cid_pres;
00387 
00388    strncpy(p->chan->language, p->owner->language, sizeof(p->chan->language) - 1);
00389    strncpy(p->chan->accountcode, p->owner->accountcode, sizeof(p->chan->accountcode) - 1);
00390    p->chan->cdrflags = p->owner->cdrflags;
00391 
00392    /* copy the channel variables from the incoming channel to the outgoing channel */
00393    /* Note that due to certain assumptions, they MUST be in the same order */
00394    AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {
00395       namelen = strlen(varptr->name);
00396       len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
00397       new = malloc(len);
00398       if (new) {
00399          memcpy(new, varptr, len);
00400          new->value = &(new->name[0]) + namelen + 1;
00401          AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
00402       } else {
00403          ast_log(LOG_ERROR, "Out of memory!\n");
00404       }
00405    }
00406 
00407    p->launchedpbx = 1;
00408 
00409    /* Start switch on sub channel */
00410    res = ast_pbx_start(p->chan);
00411    ast_mutex_unlock(&p->lock);
00412    return res;
00413 }

static int local_devicestate ( void *  data  )  [static]

Adds devicestate to extensions (for parking mostly)

Definition at line 133 of file chan_local.c.

References AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, ast_exists_extension(), ast_log(), ast_strdupa, context, exten, LOG_DEBUG, and option_debug.

00134 {
00135    char *exten;
00136    char *context;
00137 
00138    int res = AST_DEVICE_INVALID;
00139       
00140    exten = ast_strdupa(data);
00141    if ((context  = strchr(exten, '@'))) {
00142       *context = '\0';
00143       context = context + 1;
00144    }
00145    if (option_debug > 2)
00146       ast_log(LOG_DEBUG, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
00147    res = ast_exists_extension(NULL, context, exten, 1, NULL);
00148    if (!res)
00149       return AST_DEVICE_NOT_INUSE;
00150    else
00151       return AST_DEVICE_INUSE;
00152 }

static int local_digit ( struct ast_channel ast,
char  digit 
) [static]

Definition at line 334 of file chan_local.c.

References AST_FRAME_DTMF, ast_mutex_lock(), ast_mutex_unlock(), IS_OUTBOUND, local_queue_frame(), local_pvt::lock, ast_frame::subclass, and ast_channel::tech_pvt.

00335 {
00336    struct local_pvt *p = ast->tech_pvt;
00337    int res = -1;
00338    struct ast_frame f = { AST_FRAME_DTMF, };
00339    int isoutbound;
00340 
00341    ast_mutex_lock(&p->lock);
00342    isoutbound = IS_OUTBOUND(ast, p);
00343    f.subclass = digit;
00344    res = local_queue_frame(p, isoutbound, &f, ast);
00345    ast_mutex_unlock(&p->lock);
00346    return res;
00347 }

static int local_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 300 of file chan_local.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), local_pvt::chan, local_pvt::lock, LOG_WARNING, local_pvt::owner, and ast_channel::tech_pvt.

00301 {
00302    struct local_pvt *p = newchan->tech_pvt;
00303    ast_mutex_lock(&p->lock);
00304 
00305    if ((p->owner != oldchan) && (p->chan != oldchan)) {
00306       ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
00307       ast_mutex_unlock(&p->lock);
00308       return -1;
00309    }
00310    if (p->owner == oldchan)
00311       p->owner = newchan;
00312    else
00313       p->chan = newchan;
00314    ast_mutex_unlock(&p->lock);
00315    return 0;
00316 }

static int local_hangup ( struct ast_channel ast  )  [static]

Definition at line 441 of file chan_local.c.

References AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_hangup(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), local_pvt::cancelqueue, local_pvt::chan, free, local_pvt::glaredetect, IS_OUTBOUND, local_pvt::launchedpbx, local_queue_frame(), locals, local_pvt::lock, local_pvt::next, local_pvt::owner, ast_channel::tech_pvt, and usecnt_lock.

00442 {
00443    struct local_pvt *p = ast->tech_pvt;
00444    int isoutbound;
00445    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
00446    struct local_pvt *cur, *prev=NULL;
00447    struct ast_channel *ochan = NULL;
00448    int glaredetect;
00449 
00450    ast_mutex_lock(&p->lock);
00451    isoutbound = IS_OUTBOUND(ast, p);
00452    if (isoutbound) {
00453       p->chan = NULL;
00454       p->launchedpbx = 0;
00455    } else
00456       p->owner = NULL;
00457    ast->tech_pvt = NULL;
00458    
00459    ast_mutex_lock(&usecnt_lock);
00460    usecnt--;
00461    ast_mutex_unlock(&usecnt_lock);
00462    
00463    if (!p->owner && !p->chan) {
00464       /* Okay, done with the private part now, too. */
00465       glaredetect = p->glaredetect;
00466       /* If we have a queue holding, don't actually destroy p yet, but
00467          let local_queue do it. */
00468       if (p->glaredetect)
00469          p->cancelqueue = 1;
00470       ast_mutex_unlock(&p->lock);
00471       /* Remove from list */
00472       ast_mutex_lock(&locallock);
00473       cur = locals;
00474       while(cur) {
00475          if (cur == p) {
00476             if (prev)
00477                prev->next = cur->next;
00478             else
00479                locals = cur->next;
00480             break;
00481          }
00482          prev = cur;
00483          cur = cur->next;
00484       }
00485       ast_mutex_unlock(&locallock);
00486       /* Grab / release lock just in case */
00487       ast_mutex_lock(&p->lock);
00488       ast_mutex_unlock(&p->lock);
00489       /* And destroy */
00490       if (!glaredetect) {
00491          ast_mutex_destroy(&p->lock);
00492          free(p);
00493       }
00494       return 0;
00495    }
00496    if (p->chan && !p->launchedpbx)
00497       /* Need to actually hangup since there is no PBX */
00498       ochan = p->chan;
00499    else
00500       local_queue_frame(p, isoutbound, &f, NULL);
00501    ast_mutex_unlock(&p->lock);
00502    if (ochan)
00503       ast_hangup(ochan);
00504    return 0;
00505 }

static int local_indicate ( struct ast_channel ast,
int  condition 
) [static]

Definition at line 318 of file chan_local.c.

References AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), IS_OUTBOUND, local_queue_frame(), local_pvt::lock, ast_frame::subclass, and ast_channel::tech_pvt.

00319 {
00320    struct local_pvt *p = ast->tech_pvt;
00321    int res = -1;
00322    struct ast_frame f = { AST_FRAME_CONTROL, };
00323    int isoutbound;
00324 
00325    /* Queue up a frame representing the indication as a control frame */
00326    ast_mutex_lock(&p->lock);
00327    isoutbound = IS_OUTBOUND(ast, p);
00328    f.subclass = condition;
00329    res = local_queue_frame(p, isoutbound, &f, ast);
00330    ast_mutex_unlock(&p->lock);
00331    return res;
00332 }

static struct ast_channel* local_new ( struct local_pvt p,
int  state 
) [static]

Definition at line 552 of file chan_local.c.

References ast_best_codec(), ast_channel_alloc(), ast_channel_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RING, ast_update_use_count(), local_pvt::chan, ast_channel::context, local_pvt::context, ast_channel::exten, local_pvt::exten, fmt, local_tech, LOG_WARNING, ast_channel::name, ast_channel::nativeformats, local_pvt::owner, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, local_pvt::reqformat, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, usecnt_lock, and ast_channel::writeformat.

Referenced by local_request().

00553 {
00554    struct ast_channel *tmp, *tmp2;
00555    int randnum = rand() & 0xffff, fmt = 0;
00556 
00557    tmp = ast_channel_alloc(1);
00558    tmp2 = ast_channel_alloc(1);
00559    if (!tmp || !tmp2) {
00560       if (tmp)
00561          ast_channel_free(tmp);
00562       if (tmp2)
00563          ast_channel_free(tmp2);
00564       ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
00565       return NULL;
00566    } 
00567 
00568    tmp2->tech = tmp->tech = &local_tech;
00569    tmp->nativeformats = p->reqformat;
00570    tmp2->nativeformats = p->reqformat;
00571    snprintf(tmp->name, sizeof(tmp->name), "Local/%s@%s-%04x,1", p->exten, p->context, randnum);
00572    snprintf(tmp2->name, sizeof(tmp2->name), "Local/%s@%s-%04x,2", p->exten, p->context, randnum);
00573    tmp->type = type;
00574    tmp2->type = type;
00575    ast_setstate(tmp, state);
00576    ast_setstate(tmp2, AST_STATE_RING);
00577    fmt = ast_best_codec(p->reqformat);
00578    tmp->writeformat = fmt;
00579    tmp2->writeformat = fmt;
00580    tmp->rawwriteformat = fmt;
00581    tmp2->rawwriteformat = fmt;
00582    tmp->readformat = fmt;
00583    tmp2->readformat = fmt;
00584    tmp->rawreadformat = fmt;
00585    tmp2->rawreadformat = fmt;
00586    tmp->tech_pvt = p;
00587    tmp2->tech_pvt = p;
00588    p->owner = tmp;
00589    p->chan = tmp2;
00590    ast_mutex_lock(&usecnt_lock);
00591    usecnt++;
00592    usecnt++;
00593    ast_mutex_unlock(&usecnt_lock);
00594    ast_update_use_count();
00595    ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
00596    ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
00597    ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
00598    tmp->priority = 1;
00599    tmp2->priority = 1;
00600 
00601    return tmp;
00602 }

static int local_queue_frame ( struct local_pvt p,
int  isoutbound,
struct ast_frame f,
struct ast_channel us 
) [static]

Definition at line 154 of file chan_local.c.

References ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), local_pvt::cancelqueue, local_pvt::chan, ast_frame::frametype, free, local_pvt::glaredetect, ast_channel::lock, local_pvt::lock, LOG_WARNING, ast_channel::name, local_pvt::owner, and ast_frame::subclass.

Referenced by local_answer(), local_digit(), local_hangup(), local_indicate(), local_sendhtml(), and local_write().

00155 {
00156    struct ast_channel *other;
00157 retrylock:     
00158    /* Recalculate outbound channel */
00159    if (isoutbound) {
00160       other = p->owner;
00161    } else {
00162       other = p->chan;
00163    }
00164    /* Set glare detection */
00165    p->glaredetect = 1;
00166    if (p->cancelqueue) {
00167       /* We had a glare on the hangup.  Forget all this business,
00168       return and destroy p.  */
00169       ast_mutex_unlock(&p->lock);
00170       ast_mutex_destroy(&p->lock);
00171       free(p);
00172       return -1;
00173    }
00174    if (!other) {
00175       p->glaredetect = 0;
00176       return 0;
00177    }
00178    if (ast_mutex_trylock(&other->lock)) {
00179       /* Failed to lock.  Release main lock and try again */
00180       ast_mutex_unlock(&p->lock);
00181       if (us) {
00182          if (ast_mutex_unlock(&us->lock)) {
00183             ast_log(LOG_WARNING, "%s wasn't locked while sending %d/%d\n",
00184                us->name, f->frametype, f->subclass);
00185             us = NULL;
00186          }
00187       }
00188       /* Wait just a bit */
00189       usleep(1);
00190       /* Only we can destroy ourselves, so we can't disappear here */
00191       if (us)
00192          ast_mutex_lock(&us->lock);
00193       ast_mutex_lock(&p->lock);
00194       goto retrylock;
00195    }
00196    ast_queue_frame(other, f);
00197    ast_mutex_unlock(&other->lock);
00198    p->glaredetect = 0;
00199    return 0;
00200 }

static struct ast_frame * local_read ( struct ast_channel ast  )  [static]

Definition at line 272 of file chan_local.c.

References AST_FRAME_NULL.

00273 {
00274    static struct ast_frame null = { AST_FRAME_NULL, };
00275 
00276    return &null;
00277 }

static struct ast_channel * local_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static]

Definition at line 606 of file chan_local.c.

References AST_STATE_DOWN, local_alloc(), and local_new().

00607 {
00608    struct local_pvt *p;
00609    struct ast_channel *chan = NULL;
00610 
00611    p = local_alloc(data, format);
00612    if (p)
00613       chan = local_new(p, AST_STATE_DOWN);
00614    return chan;
00615 }

static int local_sendhtml ( struct ast_channel ast,
int  subclass,
const char *  data,
int  datalen 
) [static]

Definition at line 349 of file chan_local.c.

References AST_FRAME_HTML, ast_mutex_lock(), ast_mutex_unlock(), ast_frame::data, ast_frame::datalen, IS_OUTBOUND, local_queue_frame(), local_pvt::lock, ast_frame::subclass, and ast_channel::tech_pvt.

00350 {
00351    struct local_pvt *p = ast->tech_pvt;
00352    int res = -1;
00353    struct ast_frame f = { AST_FRAME_HTML, };
00354    int isoutbound;
00355 
00356    ast_mutex_lock(&p->lock);
00357    isoutbound = IS_OUTBOUND(ast, p);
00358    f.subclass = subclass;
00359    f.data = (char *)data;
00360    f.datalen = datalen;
00361    res = local_queue_frame(p, isoutbound, &f, ast);
00362    ast_mutex_unlock(&p->lock);
00363    return res;
00364 }

void local_watcher ( char *  exten,
char *  context 
)

Definition at line 124 of file chan_local.c.

References ast_device_state_changed(), ast_log(), LOG_DEBUG, and option_debug.

Referenced by load_module().

00124                                                {
00125    if (option_debug > 1)
00126       ast_log(LOG_DEBUG, "Got notification of state change for %s@%s\n", exten, context);
00127    ast_device_state_changed("Local/%s@%s", exten, context);
00128    return;
00129 }

static int local_write ( struct ast_channel ast,
struct ast_frame f 
) [static]

Definition at line 279 of file chan_local.c.

References AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), check_bridge(), ast_frame::frametype, IS_OUTBOUND, local_queue_frame(), local_pvt::lock, LOG_DEBUG, ast_channel::name, and ast_channel::tech_pvt.

00280 {
00281    struct local_pvt *p = ast->tech_pvt;
00282    int res = -1;
00283    int isoutbound;
00284 
00285    /* Just queue for delivery to the other side */
00286    ast_mutex_lock(&p->lock);
00287    isoutbound = IS_OUTBOUND(ast, p);
00288    if (f && (f->frametype == AST_FRAME_VOICE)) 
00289       check_bridge(p, isoutbound);
00290    if (!p->alreadymasqed)
00291       res = local_queue_frame(p, isoutbound, f, ast);
00292    else {
00293       ast_log(LOG_DEBUG, "Not posting to queue since already masked on '%s'\n", ast->name);
00294       res = 0;
00295    }
00296    ast_mutex_unlock(&p->lock);
00297    return res;
00298 }

static int locals_show ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 618 of file chan_local.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), local_pvt::context, local_pvt::exten, locals, local_pvt::lock, ast_channel::name, local_pvt::next, local_pvt::owner, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00619 {
00620    struct local_pvt *p;
00621 
00622    if (argc != 3)
00623       return RESULT_SHOWUSAGE;
00624    ast_mutex_lock(&locallock);
00625    p = locals;
00626    while(p) {
00627       ast_mutex_lock(&p->lock);
00628       ast_cli(fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
00629       ast_mutex_unlock(&p->lock);
00630       p = p->next;
00631    }
00632    if (!locals)
00633       ast_cli(fd, "No local channels in use\n");
00634    ast_mutex_unlock(&locallock);
00635    return RESULT_SUCCESS;
00636 }

int reload ( void   ) 

Reload stuff.

This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.

Returns:
The return value is not used.

Definition at line 663 of file chan_local.c.

00664 {
00665    return 0;
00666 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 669 of file chan_local.c.

References ast_channel_unregister(), ast_cli_unregister(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_park_metermaid_remove(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_show_locals, local_tech, locals, LOG_WARNING, local_pvt::next, and local_pvt::owner.

00670 {
00671    struct local_pvt *p;
00672 
00673    /* First, take us out of the channel loop */
00674    ast_cli_unregister(&cli_show_locals);
00675    ast_park_metermaid_remove(watchid);
00676    ast_channel_unregister(&local_tech);
00677    if (!ast_mutex_lock(&locallock)) {
00678       /* Hangup all interfaces if they have an owner */
00679       p = locals;
00680       while(p) {
00681          if (p->owner)
00682             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
00683          p = p->next;
00684       }
00685       locals = NULL;
00686       ast_mutex_unlock(&locallock);
00687    } else {
00688       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
00689       return -1;
00690    }     
00691    return 0;
00692 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 694 of file chan_local.c.

00695 {
00696    return usecnt;
00697 }


Variable Documentation

struct ast_cli_entry cli_show_locals [static]

Initial value:

 {
   { "local", "show", "channels", NULL }, locals_show, 
   "Show status of local channels", show_locals_usage, NULL }

Definition at line 642 of file chan_local.c.

Referenced by load_module(), and unload_module().

const char desc[] = "Local Proxy Channel" [static]

Definition at line 63 of file chan_local.c.

struct ast_channel_tech local_tech [static]

Definition at line 90 of file chan_local.c.

Referenced by load_module(), local_new(), and unload_module().

struct local_pvt * locals [static]

char show_locals_usage[] [static]

Initial value:

 
"Usage: local show channels\n"
"       Provides summary information on active local proxy channels.\n"

Definition at line 638 of file chan_local.c.

const char tdesc[] = "Local Proxy Channel Driver" [static]

Definition at line 65 of file chan_local.c.

const char type[] = "Local" [static]

Definition at line 64 of file chan_local.c.

int usecnt = 0 [static]

Definition at line 69 of file chan_local.c.

int watchid [static]

Definition at line 67 of file chan_local.c.


Generated on Sat Sep 16 07:28:13 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7