#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_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_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_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) |
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_pvt * | locals |
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 |
Definition in file chan_local.c.
#define IS_OUTBOUND | ( | a, | |||
b | ) | (a == b->chan ? 1 : 0) |
Definition at line 72 of file chan_local.c.
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.
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; }
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.
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.
Definition at line 663 of file chan_local.c.
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).
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.
Definition at line 694 of file chan_local.c.
00695 { 00696 return usecnt; 00697 }
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().
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.