Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:09 2007

Asterisk developer's documentation :: Codename Pineapple


chan_local.c File Reference


Detailed Description

Local Proxy Channel.

Author:
Mark Spencer <markster@digium.com>

Definition in file chan_local.c.

#include "asterisk.h"
#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/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/stringfields.h"
#include "asterisk/devicestate.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)
#define LOCAL_ALREADY_MASQED   (1 << 2)
#define LOCAL_CANCEL_QUEUE   (1 << 1)
#define LOCAL_GLARE_DETECT   (1 << 0)
#define LOCAL_LAUNCHED_PBX   (1 << 3)
#define LOCAL_NO_OPTIMIZATION   (1 << 4)

Functions

static AST_LIST_HEAD_STATIC (locals, local_pvt)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Local Proxy Channel")
static void check_bridge (struct local_pvt *p, int isoutbound)
static int load_module (void)
 Load module into PBX, register channel.
static struct local_pvtlocal_alloc (const char *data, int format)
 Create a call structure.
static int local_answer (struct ast_channel *ast)
static int local_call (struct ast_channel *ast, char *dest, int timeout)
 Initiate new call, part of PBX interface dest is the dial string.
static int local_devicestate (void *data)
 Adds devicestate to local channels.
static int local_digit_begin (struct ast_channel *ast, char digit)
static int local_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static int local_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int local_hangup (struct ast_channel *ast)
 Hangup a call through the local proxy channel.
static int local_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen)
static struct ast_channellocal_new (struct local_pvt *p, int state)
 Start new local channel.
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)
 Part of PBX interface.
static int local_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen)
static int local_sendtext (struct ast_channel *ast, const char *text)
static int local_write (struct ast_channel *ast, struct ast_frame *f)
static int locals_show (int fd, int argc, char **argv)
 CLI command "local show channels".
static int unload_module (void)
 Unload the local proxy channel from Asterisk.

Variables

static struct ast_cli_entry cli_local []
static const struct ast_channel_tech local_tech
static const char show_locals_usage []
static const char tdesc [] = "Local Proxy Channel Driver"


Define Documentation

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

Definition at line 67 of file chan_local.c.

#define LOCAL_ALREADY_MASQED   (1 << 2)
 

Already masqueraded

Definition at line 120 of file chan_local.c.

Referenced by check_bridge(), and local_write().

#define LOCAL_CANCEL_QUEUE   (1 << 1)
 

Cancel queue

Definition at line 119 of file chan_local.c.

Referenced by local_hangup(), and local_queue_frame().

#define LOCAL_GLARE_DETECT   (1 << 0)
 

Detect glare on hangup

Definition at line 118 of file chan_local.c.

Referenced by local_hangup(), and local_queue_frame().

#define LOCAL_LAUNCHED_PBX   (1 << 3)
 

PBX was launched

Definition at line 121 of file chan_local.c.

Referenced by local_call(), and local_hangup().

#define LOCAL_NO_OPTIMIZATION   (1 << 4)
 

Do not optimize using masquerading

Definition at line 122 of file chan_local.c.

Referenced by check_bridge(), and local_alloc().


Function Documentation

static AST_LIST_HEAD_STATIC locals  ,
local_pvt 
[static]
 

AST_MODULE_INFO_STANDARD ASTERISK_GPL_KEY  ,
"Local Proxy Channel" 
 

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

Definition at line 221 of file chan_local.c.

References ast_channel::_bridge, ast_channel::_softhangup, ast_channel_masquerade(), AST_LIST_EMPTY, ast_mutex_trylock(), ast_mutex_unlock(), ast_set_flag, ast_test_flag, local_pvt::chan, LOCAL_ALREADY_MASQED, LOCAL_NO_OPTIMIZATION, ast_channel::lock, and local_pvt::owner.

Referenced by local_write().

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

static int load_module void   )  [static]
 

Load module into PBX, register channel.

Definition at line 674 of file chan_local.c.

References ast_channel_register(), ast_cli_register_multiple(), ast_log(), cli_local, local_tech, and LOG_ERROR.

00675 {
00676    /* Make sure we can register our channel type */
00677    if (ast_channel_register(&local_tech)) {
00678       ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
00679       return -1;
00680    }
00681    ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
00682    return 0;
00683 }

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

Create a call structure.

Definition at line 535 of file chan_local.c.

References ast_calloc, ast_exists_extension(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_set_flag, free, LOCAL_NO_OPTIMIZATION, locals, and LOG_NOTICE.

Referenced by local_request().

00536 {
00537    struct local_pvt *tmp = NULL;
00538    char *c = NULL, *opts = NULL;
00539 
00540    if (!(tmp = ast_calloc(1, sizeof(*tmp))))
00541       return NULL;
00542 
00543    /* Initialize private structure information */
00544    ast_mutex_init(&tmp->lock);
00545    ast_copy_string(tmp->exten, data, sizeof(tmp->exten));
00546 
00547    /* Look for options */
00548    if ((opts = strchr(tmp->exten, '/'))) {
00549       *opts++ = '\0';
00550       if (strchr(opts, 'n'))
00551          ast_set_flag(tmp, LOCAL_NO_OPTIMIZATION);
00552    }
00553 
00554    /* Look for a context */
00555    if ((c = strchr(tmp->exten, '@')))
00556       *c++ = '\0';
00557 
00558    ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context));
00559 
00560    tmp->reqformat = format;
00561 
00562    if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
00563       ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
00564       ast_mutex_destroy(&tmp->lock);
00565       free(tmp);
00566       tmp = NULL;
00567    } else {
00568       /* Add to list */
00569       AST_LIST_LOCK(&locals);
00570       AST_LIST_INSERT_HEAD(&locals, tmp, list);
00571       AST_LIST_UNLOCK(&locals);
00572    }
00573    
00574    return tmp;
00575 }

static int local_answer struct ast_channel ast  )  [static]
 

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

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

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

Initiate new call, part of PBX interface dest is the dial string.

Definition at line 432 of file chan_local.c.

References accountcode, ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_set_flag, ast_strdup, ast_string_field_set, 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, language, len, LOCAL_LAUNCHED_PBX, local_pvt::lock, ast_var_t::name, local_pvt::owner, ast_channel::tech_pvt, ast_var_t::value, and ast_channel::varshead.

00433 {
00434    struct local_pvt *p = ast->tech_pvt;
00435    int res;
00436    struct ast_var_t *varptr = NULL, *new;
00437    size_t len, namelen;
00438 
00439    if (!p)
00440       return -1;
00441    
00442    ast_mutex_lock(&p->lock);
00443 
00444    p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
00445    p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
00446    p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
00447    p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
00448    p->chan->cid.cid_pres = p->owner->cid.cid_pres;
00449    ast_string_field_set(p->chan, language, p->owner->language);
00450    ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
00451    p->chan->cdrflags = p->owner->cdrflags;
00452 
00453    /* copy the channel variables from the incoming channel to the outgoing channel */
00454    /* Note that due to certain assumptions, they MUST be in the same order */
00455    AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {
00456       namelen = strlen(varptr->name);
00457       len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
00458       if ((new = ast_calloc(1, len))) {
00459          memcpy(new, varptr, len);
00460          new->value = &(new->name[0]) + namelen + 1;
00461          AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
00462       }
00463    }
00464 
00465    ast_set_flag(p, LOCAL_LAUNCHED_PBX);
00466 
00467    /* Start switch on sub channel */
00468    res = ast_pbx_start(p->chan);
00469    ast_mutex_unlock(&p->lock);
00470    return res;
00471 }

static int local_devicestate void *  data  )  [static]
 

Adds devicestate to local channels.

Definition at line 127 of file chan_local.c.

References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_exists_extension(), ast_log(), ast_strdupa, local_pvt::context, local_pvt::exten, LOG_DEBUG, LOG_WARNING, and option_debug.

00128 {
00129    char *exten = ast_strdupa(data);
00130    char *context = NULL, *opts = NULL;
00131    int res;
00132 
00133    if (!(context = strchr(exten, '@'))) {
00134       ast_log(LOG_WARNING, "Someone used Local/%s somewhere without a @context. This is bad.\n", exten);
00135       return AST_DEVICE_INVALID; 
00136    }
00137 
00138    *context++ = '\0';
00139 
00140    /* Strip options if they exist */
00141    if ((opts = strchr(context, '/')))
00142       *opts = '\0';
00143 
00144    if (option_debug > 2)
00145       ast_log(LOG_DEBUG, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
00146    res = ast_exists_extension(NULL, context, exten, 1, NULL);
00147    if (!res)      
00148       return AST_DEVICE_INVALID;
00149    else
00150       return AST_DEVICE_UNKNOWN;
00151 }

static int local_digit_begin struct ast_channel ast,
char  digit
[static]
 

Definition at line 352 of file chan_local.c.

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

00353 {
00354    struct local_pvt *p = ast->tech_pvt;
00355    int res = -1;
00356    struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
00357    int isoutbound;
00358 
00359    if (!p)
00360       return -1;
00361 
00362    ast_mutex_lock(&p->lock);
00363    isoutbound = IS_OUTBOUND(ast, p);
00364    f.subclass = digit;
00365    res = local_queue_frame(p, isoutbound, &f, ast);
00366    ast_mutex_unlock(&p->lock);
00367 
00368    return res;
00369 }

static int local_digit_end struct ast_channel ast,
char  digit,
unsigned int  duration
[static]
 

Definition at line 371 of file chan_local.c.

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

00372 {
00373    struct local_pvt *p = ast->tech_pvt;
00374    int res = -1;
00375    struct ast_frame f = { AST_FRAME_DTMF_END, };
00376    int isoutbound;
00377 
00378    if (!p)
00379       return -1;
00380 
00381    ast_mutex_lock(&p->lock);
00382    isoutbound = IS_OUTBOUND(ast, p);
00383    f.subclass = digit;
00384    f.len = duration;
00385    res = local_queue_frame(p, isoutbound, &f, ast);
00386    ast_mutex_unlock(&p->lock);
00387    
00388    return res;
00389 }

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

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

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

static int local_hangup struct ast_channel ast  )  [static]
 

Hangup a call through the local proxy channel.

Definition at line 474 of file chan_local.c.

References ast_clear_flag, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_hangup(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_module_user_remove, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_test_flag, local_pvt::chan, free, IS_OUTBOUND, LOCAL_CANCEL_QUEUE, LOCAL_GLARE_DETECT, LOCAL_LAUNCHED_PBX, local_queue_frame(), locals, local_pvt::lock, local_pvt::owner, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), ast_channel::tech_pvt, local_pvt::u_chan, and local_pvt::u_owner.

00475 {
00476    struct local_pvt *p = ast->tech_pvt;
00477    int isoutbound;
00478    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
00479    struct ast_channel *ochan = NULL;
00480    int glaredetect = 0;
00481 
00482    if (!p)
00483       return -1;
00484 
00485    ast_mutex_lock(&p->lock);
00486    isoutbound = IS_OUTBOUND(ast, p);
00487    if (isoutbound) {
00488       const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
00489       if ((status) && (p->owner))
00490          pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
00491       p->chan = NULL;
00492       ast_clear_flag(p, LOCAL_LAUNCHED_PBX);
00493       ast_module_user_remove(p->u_chan);
00494    } else {
00495       p->owner = NULL;
00496       ast_module_user_remove(p->u_owner);
00497    }
00498    
00499    ast->tech_pvt = NULL;
00500    
00501    if (!p->owner && !p->chan) {
00502       /* Okay, done with the private part now, too. */
00503       glaredetect = ast_test_flag(p, LOCAL_GLARE_DETECT);
00504       /* If we have a queue holding, don't actually destroy p yet, but
00505          let local_queue do it. */
00506       if (glaredetect)
00507          ast_set_flag(p, LOCAL_CANCEL_QUEUE);
00508       ast_mutex_unlock(&p->lock);
00509       /* Remove from list */
00510       AST_LIST_LOCK(&locals);
00511       AST_LIST_REMOVE(&locals, p, list);
00512       AST_LIST_UNLOCK(&locals);
00513       /* Grab / release lock just in case */
00514       ast_mutex_lock(&p->lock);
00515       ast_mutex_unlock(&p->lock);
00516       /* And destroy */
00517       if (!glaredetect) {
00518          ast_mutex_destroy(&p->lock);
00519          free(p);
00520       }
00521       return 0;
00522    }
00523    if (p->chan && !ast_test_flag(p, LOCAL_LAUNCHED_PBX))
00524       /* Need to actually hangup since there is no PBX */
00525       ochan = p->chan;
00526    else
00527       local_queue_frame(p, isoutbound, &f, NULL);
00528    ast_mutex_unlock(&p->lock);
00529    if (ochan)
00530       ast_hangup(ochan);
00531    return 0;
00532 }

static int local_indicate struct ast_channel ast,
int  condition,
const void *  data,
size_t  datalen
[static]
 

Definition at line 323 of file chan_local.c.

References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, ast_moh_start(), ast_moh_stop(), 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.

00324 {
00325    struct local_pvt *p = ast->tech_pvt;
00326    int res = 0;
00327    struct ast_frame f = { AST_FRAME_CONTROL, };
00328    int isoutbound;
00329 
00330    if (!p)
00331       return -1;
00332 
00333    /* If this is an MOH hold or unhold, do it on the Local channel versus real channel */
00334    if (condition == AST_CONTROL_HOLD) {
00335       ast_moh_start(ast, data, NULL);
00336    } else if (condition == AST_CONTROL_UNHOLD) {
00337       ast_moh_stop(ast);
00338    } else {
00339       /* Queue up a frame representing the indication as a control frame */
00340       ast_mutex_lock(&p->lock);
00341       isoutbound = IS_OUTBOUND(ast, p);
00342       f.subclass = condition;
00343       f.data = (void*)data;
00344       f.datalen = datalen;
00345       res = local_queue_frame(p, isoutbound, &f, ast);
00346       ast_mutex_unlock(&p->lock);
00347    }
00348 
00349    return res;
00350 }

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

Start new local channel.

Definition at line 578 of file chan_local.c.

References ast_best_codec(), ast_channel_alloc(), ast_channel_free(), ast_log(), ast_module_user_add, ast_random(), AST_STATE_RING, local_pvt::chan, ast_channel::context, local_pvt::context, ast_channel::exten, local_pvt::exten, fmt, local_tech, LOG_WARNING, 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, local_pvt::u_chan, local_pvt::u_owner, and ast_channel::writeformat.

Referenced by local_request().

00579 {
00580    struct ast_channel *tmp = NULL, *tmp2 = NULL;
00581    int randnum = ast_random() & 0xffff, fmt = 0;
00582 
00583    /* Allocate two new Asterisk channels */
00584    if (!(tmp = ast_channel_alloc(1, state, 0, 0, "Local/%s@%s-%04x,1", p->exten, p->context, randnum)) 
00585          || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, "Local/%s@%s-%04x,2", p->exten, p->context, randnum))) {
00586       if (tmp)
00587          ast_channel_free(tmp);
00588       if (tmp2)
00589          ast_channel_free(tmp2);
00590       ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
00591       return NULL;
00592    } 
00593 
00594    tmp2->tech = tmp->tech = &local_tech;
00595 
00596    tmp->nativeformats = p->reqformat;
00597    tmp2->nativeformats = p->reqformat;
00598 
00599    /* Determine our read/write format and set it on each channel */
00600    fmt = ast_best_codec(p->reqformat);
00601    tmp->writeformat = fmt;
00602    tmp2->writeformat = fmt;
00603    tmp->rawwriteformat = fmt;
00604    tmp2->rawwriteformat = fmt;
00605    tmp->readformat = fmt;
00606    tmp2->readformat = fmt;
00607    tmp->rawreadformat = fmt;
00608    tmp2->rawreadformat = fmt;
00609 
00610    tmp->tech_pvt = p;
00611    tmp2->tech_pvt = p;
00612 
00613    p->owner = tmp;
00614    p->chan = tmp2;
00615    p->u_owner = ast_module_user_add(p->owner);
00616    p->u_chan = ast_module_user_add(p->chan);
00617 
00618    ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
00619    ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
00620    ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
00621    tmp->priority = 1;
00622    tmp2->priority = 1;
00623 
00624    return tmp;
00625 }

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

Definition at line 153 of file chan_local.c.

References ast_clear_flag, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), ast_set_flag, ast_test_flag, local_pvt::chan, ast_frame::frametype, free, LOCAL_CANCEL_QUEUE, LOCAL_GLARE_DETECT, ast_channel::lock, local_pvt::lock, LOG_WARNING, local_pvt::owner, and ast_frame::subclass.

Referenced by local_answer(), local_digit_begin(), local_digit_end(), local_hangup(), local_indicate(), local_sendhtml(), local_sendtext(), and local_write().

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

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

Definition at line 271 of file chan_local.c.

References ast_null_frame.

00272 {
00273    return &ast_null_frame;
00274 }

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

Part of PBX interface.

Definition at line 629 of file chan_local.c.

References AST_STATE_DOWN, local_pvt::chan, local_alloc(), and local_new().

00630 {
00631    struct local_pvt *p = NULL;
00632    struct ast_channel *chan = NULL;
00633 
00634    /* Allocate a new private structure and then Asterisk channel */
00635    if ((p = local_alloc(data, format)))
00636       chan = local_new(p, AST_STATE_DOWN);
00637 
00638    return chan;
00639 }

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

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

00411 {
00412    struct local_pvt *p = ast->tech_pvt;
00413    int res = -1;
00414    struct ast_frame f = { AST_FRAME_HTML, };
00415    int isoutbound;
00416 
00417    if (!p)
00418       return -1;
00419    
00420    ast_mutex_lock(&p->lock);
00421    isoutbound = IS_OUTBOUND(ast, p);
00422    f.subclass = subclass;
00423    f.data = (char *)data;
00424    f.datalen = datalen;
00425    res = local_queue_frame(p, isoutbound, &f, ast);
00426    ast_mutex_unlock(&p->lock);
00427    return res;
00428 }

static int local_sendtext struct ast_channel ast,
const char *  text
[static]
 

Definition at line 391 of file chan_local.c.

References <