Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:30 2009

## 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 dependency graph for chan_local.c:

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_pvt * | local_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_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_channel * | local_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_frame * | local_read (struct ast_channel *ast)
static struct ast_channel * | local_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)
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_pvt * | locals
static char | show_locals_usage []
static const char | tdesc [] = "Local Proxy Channel Driver"
static const char | type [] = "Local"
static int | usecnt = 0

## Detailed Description

Local Proxy Channel.

Definition in file chan_local.c.

## Define Documentation

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

Definition at line 68 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 187 of file chan_local.c.

References ast_channel::_bridge, ast_channel::_softhangup, local_pvt::alreadymasqed, ast_bridged_channel(), 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().

    00188 {
    00189    if (p->alreadymasqed || p->nooptimization)
    00190       return;
    00191    if (!p->chan || !p->owner || (p->chan->_bridge != ast_bridged_channel(p->chan)))
    00192       return;
    00193
    00194    /* only do the masquerade if we are being called on the outbound channel,
    00195       if it has been bridged to another channel and if there are no pending
    00196       frames on the owner channel (because they would be transferred to the
    00197       outbound channel during the masquerade)
    00198    */
    00199    if (isoutbound && p->chan->_bridge /* Not ast_bridged_channel!  Only go one step! */ && !p->owner->readq) {
    00200       /* Masquerade bridged channel into owner */
    00201       /* Lock everything we need, one by one, and give up if
    00202          we can't get everything.  Remember, we'll get another
    00203          chance in just a little bit */
    00204       if (!ast_mutex_trylock(&(p->chan->_bridge)->lock)) {
    00205          if (!p->chan->_bridge->_softhangup) {
    00206             if (!ast_mutex_trylock(&p->owner->lock)) {
    00207                if (!p->owner->_softhangup) {
    00208                   ast_channel_masquerade(p->owner, p->chan->_bridge);
    00209                   p->alreadymasqed = 1;
    00210                }
    00211                ast_mutex_unlock(&p->owner->lock);
    00212             }
    00213             ast_mutex_unlock(&(p->chan->_bridge)->lock);
    00214          }
    00215       }
    00216    /* We only allow masquerading in one 'direction'... it's important to preserve the state
    00217       (group variables, etc.) that live on p->chan->_bridge (and were put there by the dialplan)
    00218       when the local channels go away.
    00219    */
    00220 #if 0
    00221    } else if (!isoutbound && p->owner && p->owner->_bridge && p->chan && !p->chan->readq) {
    00222       /* Masquerade bridged channel into chan */
    00223       if (!ast_mutex_trylock(&(p->owner->_bridge)->lock)) {
    00224          if (!p->owner->_bridge->_softhangup) {
    00225             if (!ast_mutex_trylock(&p->chan->lock)) {
    00226                if (!p->chan->_softhangup) {
    00227                   ast_channel_masquerade(p->chan, p->owner->_bridge);
    00228                   p->alreadymasqed = 1;
    00229                }
    00230                ast_mutex_unlock(&p->chan->lock);
    00231             }
    00232          }
    00233          ast_mutex_unlock(&(p->owner->_bridge)->lock);
    00234       }
    00235 #endif
    00236    }
    00237 }

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 690 of file chan_local.c.

    00691 {
    00692    return (char *) desc;
    00693 }

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 685 of file chan_local.c.

References ASTERISK_GPL_KEY.

    00686 {
    00687    return ASTERISK_GPL_KEY;
    00688 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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 638 of file chan_local.c.

References ast_channel_register(), ast_cli_register(), ast_log(), and LOG_ERROR.

    00639 {
    00640    /* Make sure we can register our channel type */
    00641    if (ast_channel_register(&local_tech)) {
    00642       ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
    00643       return -1;
    00644    }
    00645    ast_cli_register(&cli_show_locals);
    00646    return 0;
    00647 }

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

Definition at line 499 of file chan_local.c.

References ast_exists_extension(), ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), local_pvt::context, local_pvt::exten, free, locals, local_pvt::lock, LOG_NOTICE, malloc, local_pvt::next, local_pvt::nooptimization, and local_pvt::reqformat.

Referenced by local_request().

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

static int local_answer | ( | struct ast_channel * | ast | ) | `[static]`

Definition at line 165 of file chan_local.c.

References 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.

    00166 {
    00167    struct local_pvt *p = ast->tech_pvt;
    00168    int isoutbound;
    00169    int res = -1;
    00170
    00171    if (!p)
    00172       return -1;
    00173
    00174    ast_mutex_lock(&p->lock);
    00175    isoutbound = IS_OUTBOUND(ast, p);
    00176    if (isoutbound) {
    00177       /* Pass along answer since somebody answered us */
    00178       struct ast_frame answer = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
    00179       res = local_queue_frame(p, isoutbound, &answer, ast);
    00180    } else
    00181       ast_log(LOG_WARNING, "Huh?  Local is being asked to answer?\n");
    00182    if (!res)
    00183       ast_mutex_unlock(&p->lock);
    00184    return res;
    00185 }

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

Definition at line 352 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, and ast_channel::varshead.

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

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

Definition at line 312 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.

    00313 {
    00314    struct local_pvt *p = ast->tech_pvt;
    00315    int res = -1;
    00316    struct ast_frame f = { AST_FRAME_DTMF, };
    00317    int isoutbound;
    00318
    00319    if (!p)
    00320       return -1;
    00321
    00322    ast_mutex_lock(&p->lock);
    00323    isoutbound = IS_OUTBOUND(ast, p);
    00324    f.subclass = digit;
    00325    if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
    00326       ast_mutex_unlock(&p->lock);
    00327    return res;
    00328 }

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

Definition at line 271 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.

    00272 {
    00273    struct local_pvt *p = newchan->tech_pvt;
    00274
    00275    if (!p)
    00276       return -1;
    00277
    00278    ast_mutex_lock(&p->lock);
    00279
    00280    if ((p->owner != oldchan) && (p->chan != oldchan)) {
    00281       ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
    00282       ast_mutex_unlock(&p->lock);
    00283       return -1;
    00284    }
    00285    if (p->owner == oldchan)
    00286       p->owner = newchan;
    00287    else
    00288       p->chan = newchan;
    00289    ast_mutex_unlock(&p->lock);
    00290    return 0;
    00291 }

static int local_hangup | ( | struct ast_channel * | ast | ) | `[static]`

Definition at line 428 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.

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

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

Definition at line 293 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.

    00294 {
    00295    struct local_pvt *p = ast->tech_pvt;
    00296    int res = -1;
    00297    struct ast_frame f = { AST_FRAME_CONTROL, };
    00298    int isoutbound;
    00299
    00300    if (!p)
    00301       return -1;
    00302
    00303    /* Queue up a frame representing the indication as a control frame */
    00304    ast_mutex_lock(&p->lock);
    00305    isoutbound = IS_OUTBOUND(ast, p);
    00306    f.subclass = condition;
    00307    if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
    00308       ast_mutex_unlock(&p->lock);
    00309    return res;
    00310 }

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

Definition at line 543 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, 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().

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

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

Definition at line 117 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().

    00118 {
    00119    struct ast_channel *other;
    00120 retrylock:
    00121    /* Recalculate outbound channel */
    00122    if (isoutbound) {
    00123       other = p->owner;
    00124    } else {
    00125       other = p->chan;
    00126    }
    00127    /* Set glare detection */
    00128    p->glaredetect = 1;
    00129    if (p->cancelqueue) {
    00130       /* We had a glare on the hangup.  Forget all this business,
    00131       return and destroy p.  */
    00132       ast_mutex_unlock(&p->lock);
    00133       ast_mutex_destroy(&p->lock);
    00134       free(p);
    00135       return -1;
    00136    }
    00137    if (!other) {
    00138       p->glaredetect = 0;
    00139       return 0;
    00140    }
    00141    if (ast_mutex_trylock(&other->lock)) {
    00142       /* Failed to lock.  Release main lock and try again */
    00143       ast_mutex_unlock(&p->lock);
    00144       if (us) {
    00145          if (ast_mutex_unlock(&us->lock)) {
    00146             ast_log(LOG_WARNING, "%s wasn't locked while sending %d/%d\n",
    00147                us->name, f->frametype, f->subclass);
    00148             us = NULL;
    00149          }
    00150       }
    00151       /* Wait just a bit */
    00152       usleep(1);
    00153       /* Only we can destroy ourselves, so we can't disappear here */
    00154       if (us)
    00155          ast_mutex_lock(&us->lock);
    00156       ast_mutex_lock(&p->lock);
    00157       goto retrylock;
    00158    }
    00159    ast_queue_frame(other, f);
    00160    ast_mutex_unlock(&other->lock);
    00161    p->glaredetect = 0;
    00162    return 0;
    00163 }

static struct ast_frame * local_read | ( | struct ast_channel * | ast | ) | `[static, read]`

Definition at line 239 of file chan_local.c.

References AST_FRAME_NULL.

    00240 {
    00241    static struct ast_frame null = { AST_FRAME_NULL, };
    00242
    00243    return &null;
    00244 }

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

Definition at line 597 of file chan_local.c.

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

    00598 {
    00599    struct local_pvt *p;
    00600    struct ast_channel *chan = NULL;
    00601
    00602    p = local_alloc(data, format);
    00603    if (p)
    00604       chan = local_new(p, AST_STATE_DOWN);
    00605    return chan;
    00606 }

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

Definition at line 330 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.

    00331 {
    00332    struct local_pvt *p = ast->tech_pvt;
    00333    int res = -1;
    00334    struct ast_frame f = { AST_FRAME_HTML, };
    00335    int isoutbound;
    00336
    00337    if (!p)
    00338       return -1;
    00339
    00340    ast_mutex_lock(&p->lock);
    00341    isoutbound = IS_OUTBOUND(ast, p);
    00342    f.subclass = subclass;
    00343    f.data = (char *)data;
    00344    f.datalen = datalen;
    00345    if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
    00346       ast_mutex_unlock(&p->lock);
    00347    return res;
    00348 }

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

Definition at line 246 of file chan_local.c.

References local_pvt::alreadymasqed, 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.

    00247 {
    00248    struct local_pvt *p = ast->tech_pvt;
    00249    int res = -1;
    00250    int isoutbound;
    00251
    00252    if (!p)
    00253       return -1;
    00254
    00255    /* Just queue for delivery to the other side */
    00256    ast_mutex_lock(&p->lock);
    00257    isoutbound = IS_OUTBOUND(ast, p);
    00258    if (f && (f->frametype == AST_FRAME_VOICE))
    00259       check_bridge(p, isoutbound);
    00260    if (!p->alreadymasqed)
    00261       res = local_queue_frame(p, isoutbound, f, ast);
    00262    else {
    00263       ast_log(LOG_DEBUG, "Not posting to queue since already masked on '%s'\n", ast->name);
    00264       res = 0;
    00265    }
    00266    if (!res)
    00267       ast_mutex_unlock(&p->lock);
    00268    return res;
    00269 }

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

Definition at line 609 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.

    00610 {
    00611    struct local_pvt *p;
    00612
    00613    if (argc != 3)
    00614       return RESULT_SHOWUSAGE;
    00615    ast_mutex_lock(&locallock);
    00616    p = locals;
    00617    while(p) {
    00618       ast_mutex_lock(&p->lock);
    00619       ast_cli(fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
    00620       ast_mutex_unlock(&p->lock);
    00621       p = p->next;
    00622    }
    00623    if (!locals)
    00624       ast_cli(fd, "No local channels in use\n");
    00625    ast_mutex_unlock(&locallock);
    00626    return RESULT_SUCCESS;
    00627 }

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 650 of file chan_local.c.

    00651 {
    00652    return 0;
    00653 }

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 656 of file chan_local.c.

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

    00657 {
    00658    struct local_pvt *p;
    00659
    00660    /* First, take us out of the channel loop */
    00661    ast_cli_unregister(&cli_show_locals);
    00662    ast_channel_unregister(&local_tech);
    00663    if (!ast_mutex_lock(&locallock)) {
    00664       /* Hangup all interfaces if they have an owner */
    00665       p = locals;
    00666       while(p) {
    00667          if (p->owner)
    00668             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
    00669          p = p->next;
    00670       }
    00671       locals = NULL;
    00672       ast_mutex_unlock(&locallock);
    00673    } else {
    00674       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
    00675       return -1;
    00676    }
    00677    return 0;
    00678 }

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 680 of file chan_local.c.

    00681 {
    00682    return usecnt;
    00683 }

## 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 633 of file chan_local.c.

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

Definition at line 61 of file chan_local.c.

struct ast_channel_tech local_tech`[static]`

Definition at line 85 of file chan_local.c.

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 629 of file chan_local.c.

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

Definition at line 63 of file chan_local.c.

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

Definition at line 62 of file chan_local.c.

int usecnt = 0`[static]`

Definition at line 65 of file chan_local.c.