#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_features.c:
Go to the source code of this file.
Data Structures | |
struct | feature_pvt |
struct | feature_sub |
Defines | |
#define | IS_OUTBOUND(a, b) (a == b->chan ? 1 : 0) |
#define | SUB_CALLWAIT 1 |
#define | SUB_REAL 0 |
#define | SUB_THREEWAY 2 |
Functions | |
AST_MUTEX_DEFINE_STATIC (featurelock) | |
AST_MUTEX_DEFINE_STATIC (usecnt_lock) | |
char * | description () |
Provides a description of the module. | |
static struct feature_pvt * | features_alloc (char *data, int format) |
static int | features_answer (struct ast_channel *ast) |
static int | features_call (struct ast_channel *ast, char *dest, int timeout) |
static int | features_digit (struct ast_channel *ast, char digit) |
static int | features_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static int | features_hangup (struct ast_channel *ast) |
static int | features_indicate (struct ast_channel *ast, int condition) |
static struct ast_channel * | features_new (struct feature_pvt *p, int state, int index) |
static struct ast_frame * | features_read (struct ast_channel *ast) |
static struct ast_channel * | features_request (const char *type, int format, void *data, int *cause) |
static int | features_show (int fd, int argc, char **argv) |
static int | features_write (struct ast_channel *ast, struct ast_frame *f) |
static int | indexof (struct feature_pvt *p, struct ast_channel *owner, int nullok) |
static void | init_sub (struct feature_sub *sub) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module () |
Initialize the module. | |
int | reload () |
Reload stuff. | |
static void | restore_channel (struct feature_pvt *p, int index) |
int | unload_module () |
Cleanup all module structures, sockets, etc. | |
static void | update_features (struct feature_pvt *p, int index) |
int | usecount () |
Provides a usecount. | |
Variables | |
static struct ast_cli_entry | cli_show_features |
static const char | desc [] = "Feature Proxy Channel" |
static struct feature_pvt * | features |
static const struct ast_channel_tech | features_tech |
static char | show_features_usage [] |
static const char | tdesc [] = "Feature Proxy Channel Driver" |
static const char | type [] = "Feature" |
static int | usecnt = 0 |
Definition in file chan_features.c.
|
Definition at line 70 of file chan_features.c. Referenced by local_answer(), local_digit(), local_hangup(), local_indicate(), local_sendhtml(), and local_write(). |
|
Definition at line 94 of file chan_features.c. Referenced by available(), features_hangup(), ss_thread(), zt_bridge(), zt_call(), zt_handle_event(), zt_hangup(), and zt_read(). |
|
|
Definition at line 95 of file chan_features.c. Referenced by attempt_transfer(), available(), features_hangup(), ss_thread(), zt_answer(), zt_bridge(), zt_handle_event(), and zt_hangup(). |
|
|
|
|
|
Provides a description of the module.
Definition at line 602 of file chan_features.c. References desc. 00603 { 00604 return (char *) desc; 00605 }
|
|
Definition at line 410 of file chan_features.c. References ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_strdupa, feature_pvt::dest, features, init_sub(), LOG_NOTICE, malloc, feature_pvt::next, and feature_pvt::tech. Referenced by features_request(). 00411 { 00412 struct feature_pvt *tmp; 00413 char *dest=NULL; 00414 char *tech; 00415 int x; 00416 int status; 00417 struct ast_channel *chan; 00418 00419 tech = ast_strdupa(data); 00420 if (tech) { 00421 dest = strchr(tech, '/'); 00422 if (dest) { 00423 *dest = '\0'; 00424 dest++; 00425 } 00426 } 00427 if (!tech || !dest) { 00428 ast_log(LOG_NOTICE, "Format for feature channel is Feature/Tech/Dest ('%s' not valid)!\n", 00429 data); 00430 return NULL; 00431 } 00432 ast_mutex_lock(&featurelock); 00433 tmp = features; 00434 while(tmp) { 00435 if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest)) 00436 break; 00437 tmp = tmp->next; 00438 } 00439 ast_mutex_unlock(&featurelock); 00440 if (!tmp) { 00441 chan = ast_request(tech, format, dest, &status); 00442 if (!chan) { 00443 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest); 00444 return NULL; 00445 } 00446 tmp = malloc(sizeof(struct feature_pvt)); 00447 if (tmp) { 00448 memset(tmp, 0, sizeof(struct feature_pvt)); 00449 for (x=0;x<3;x++) 00450 init_sub(tmp->subs + x); 00451 ast_mutex_init(&tmp->lock); 00452 strncpy(tmp->tech, tech, sizeof(tmp->tech) - 1); 00453 strncpy(tmp->dest, dest, sizeof(tmp->dest) - 1); 00454 tmp->subchan = chan; 00455 ast_mutex_lock(&featurelock); 00456 tmp->next = features; 00457 features = tmp; 00458 ast_mutex_unlock(&featurelock); 00459 } 00460 } 00461 return tmp; 00462 }
|
|
Definition at line 227 of file chan_features.c. References ast_answer(), ast_mutex_lock(), ast_mutex_unlock(), indexof(), feature_pvt::lock, feature_pvt::subchan, and ast_channel::tech_pvt. 00228 { 00229 struct feature_pvt *p = ast->tech_pvt; 00230 int res = -1; 00231 int x; 00232 00233 ast_mutex_lock(&p->lock); 00234 x = indexof(p, ast, 0); 00235 if (!x && p->subchan) 00236 res = ast_answer(p->subchan); 00237 ast_mutex_unlock(&p->lock); 00238 return res; 00239 }
|
|
|
Definition at line 304 of file chan_features.c. References ast_mutex_lock(), ast_mutex_unlock(), ast_senddigit(), indexof(), feature_pvt::lock, feature_pvt::subchan, and ast_channel::tech_pvt. 00305 { 00306 struct feature_pvt *p = ast->tech_pvt; 00307 int res = -1; 00308 int x; 00309 00310 /* Queue up a frame representing the indication as a control frame */ 00311 ast_mutex_lock(&p->lock); 00312 x = indexof(p, ast, 0); 00313 if (!x && p->subchan) 00314 res = ast_senddigit(p->subchan, digit); 00315 ast_mutex_unlock(&p->lock); 00316 return res; 00317 }
|
|
Definition at line 273 of file chan_features.c. References ast_mutex_lock(), feature_pvt::lock, feature_sub::owner, feature_pvt::owner, feature_pvt::subs, and ast_channel::tech_pvt. 00274 { 00275 struct feature_pvt *p = newchan->tech_pvt; 00276 int x; 00277 00278 ast_mutex_lock(&p->lock); 00279 if (p->owner == oldchan) 00280 p->owner = newchan; 00281 for (x = 0; x < 3; x++) { 00282 if (p->subs[x].owner == oldchan) 00283 p->subs[x].owner = newchan; 00284 } 00285 ast_mutex_unlock(&p->lock); 00286 return 0; 00287 }
|
|
Definition at line 364 of file chan_features.c. References ast_hangup(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), features, free, indexof(), feature_pvt::lock, feature_pvt::next, feature_sub::owner, restore_channel(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, feature_pvt::subchan, feature_pvt::subs, and ast_channel::tech_pvt. 00365 { 00366 struct feature_pvt *p = ast->tech_pvt; 00367 struct feature_pvt *cur, *prev=NULL; 00368 int x; 00369 00370 ast_mutex_lock(&p->lock); 00371 x = indexof(p, ast, 0); 00372 if (x > -1) { 00373 restore_channel(p, x); 00374 p->subs[x].owner = NULL; 00375 /* XXX Re-arrange, unconference, etc XXX */ 00376 } 00377 ast->tech_pvt = NULL; 00378 00379 00380 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 00381 ast_mutex_unlock(&p->lock); 00382 /* Remove from list */ 00383 ast_mutex_lock(&featurelock); 00384 cur = features; 00385 while(cur) { 00386 if (cur == p) { 00387 if (prev) 00388 prev->next = cur->next; 00389 else 00390 features = cur->next; 00391 break; 00392 } 00393 prev = cur; 00394 cur = cur->next; 00395 } 00396 ast_mutex_unlock(&featurelock); 00397 ast_mutex_lock(&p->lock); 00398 /* And destroy */ 00399 if (p->subchan) 00400 ast_hangup(p->subchan); 00401 ast_mutex_unlock(&p->lock); 00402 ast_mutex_destroy(&p->lock); 00403 free(p); 00404 return 0; 00405 } 00406 ast_mutex_unlock(&p->lock); 00407 return 0; 00408 }
|
|
Definition at line 289 of file chan_features.c. References ast_indicate(), ast_mutex_lock(), ast_mutex_unlock(), indexof(), feature_pvt::lock, feature_pvt::subchan, and ast_channel::tech_pvt. 00290 { 00291 struct feature_pvt *p = ast->tech_pvt; 00292 int res = -1; 00293 int x; 00294 00295 /* Queue up a frame representing the indication as a control frame */ 00296 ast_mutex_lock(&p->lock); 00297 x = indexof(p, ast, 0); 00298 if (!x && p->subchan) 00299 res = ast_indicate(p->subchan, condition); 00300 ast_mutex_unlock(&p->lock); 00301 return res; 00302 }
|
|
Definition at line 464 of file chan_features.c. References ast_channel_alloc(), ast_log(), feature_pvt::dest, features_tech, LOG_WARNING, ast_channel::name, feature_sub::owner, feature_pvt::subchan, feature_pvt::subs, feature_pvt::tech, and ast_channel::tech. Referenced by features_request(). 00465 { 00466 struct ast_channel *tmp; 00467 int x,y; 00468 if (!p->subchan) { 00469 ast_log(LOG_WARNING, "Called upon channel with no subchan:(\n"); 00470 return NULL; 00471 } 00472 if (p->subs[index].owner) { 00473 ast_log(LOG_WARNING, "Called to put index %d already there!\n", index); 00474 return NULL; 00475 } 00476 tmp = ast_channel_alloc(0); 00477 if (!tmp) { 00478 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 00479 return NULL; 00480 } 00481 tmp->tech = &features_tech; 00482 for (x=1;x<4;x++) { 00483 snprintf(tmp->name, sizeof(tmp->name), "Feature/%s/%s-%d", p->tech, p->dest, x); 00484 for (y=0;y<3;y++) { 00485 if (y == index) 00486 continue; 00487 if (p->subs[y].owner && !strcasecmp(p->subs[y].owner->name, tmp->name)) 00488 break; 00489 } 00490 if (y >= 3) 00491 break; 00492 } 00493 tmp->type = type; 00494 ast_setstate(tmp, state); 00495 tmp->writeformat = p->subchan->writeformat; 00496 tmp->rawwriteformat = p->subchan->rawwriteformat; 00497 tmp->readformat = p->subchan->readformat; 00498 tmp->rawreadformat = p->subchan->rawreadformat; 00499 tmp->nativeformats = p->subchan->readformat; 00500 tmp->tech_pvt = p; 00501 p->subs[index].owner = tmp; 00502 if (!p->owner) 00503 p->owner = tmp; 00504 ast_mutex_lock(&usecnt_lock); 00505 usecnt++; 00506 ast_mutex_unlock(&usecnt_lock); 00507 ast_update_use_count(); 00508 return tmp; 00509 }
|
|
Definition at line 241 of file chan_features.c. References AST_FRAME_NULL, ast_mutex_lock(), ast_mutex_unlock(), ast_read(), indexof(), feature_pvt::lock, feature_pvt::subchan, ast_channel::tech_pvt, and update_features(). 00242 { 00243 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00244 struct feature_pvt *p = ast->tech_pvt; 00245 struct ast_frame *f; 00246 int x; 00247 00248 f = &null_frame; 00249 ast_mutex_lock(&p->lock); 00250 x = indexof(p, ast, 0); 00251 if (!x && p->subchan) { 00252 update_features(p, x); 00253 f = ast_read(p->subchan); 00254 } 00255 ast_mutex_unlock(&p->lock); 00256 return f; 00257 }
|
|
Definition at line 512 of file chan_features.c. References AST_STATE_DOWN, features_alloc(), features_new(), SUB_REAL, feature_pvt::subs, and update_features(). 00513 { 00514 struct feature_pvt *p; 00515 struct ast_channel *chan = NULL; 00516 00517 p = features_alloc(data, format); 00518 if (p && !p->subs[SUB_REAL].owner) 00519 chan = features_new(p, AST_STATE_DOWN, SUB_REAL); 00520 if (chan) 00521 update_features(p,SUB_REAL); 00522 return chan; 00523 }
|
|
Definition at line 525 of file chan_features.c. References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), feature_pvt::dest, features, feature_pvt::lock, ast_channel::name, feature_pvt::next, feature_pvt::owner, RESULT_SHOWUSAGE, RESULT_SUCCESS, and feature_pvt::tech. 00526 { 00527 struct feature_pvt *p; 00528 00529 if (argc != 3) 00530 return RESULT_SHOWUSAGE; 00531 ast_mutex_lock(&featurelock); 00532 p = features; 00533 while(p) { 00534 ast_mutex_lock(&p->lock); 00535 ast_cli(fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest); 00536 ast_mutex_unlock(&p->lock); 00537 p = p->next; 00538 } 00539 if (!features) 00540 ast_cli(fd, "No feature channels in use\n"); 00541 ast_mutex_unlock(&featurelock); 00542 return RESULT_SUCCESS; 00543 }
|
|
Definition at line 259 of file chan_features.c. References ast_mutex_lock(), ast_mutex_unlock(), ast_write(), indexof(), feature_pvt::lock, feature_pvt::subchan, and ast_channel::tech_pvt. 00260 { 00261 struct feature_pvt *p = ast->tech_pvt; 00262 int res = -1; 00263 int x; 00264 00265 ast_mutex_lock(&p->lock); 00266 x = indexof(p, ast, 0); 00267 if (!x && p->subchan) 00268 res = ast_write(p->subchan, f); 00269 ast_mutex_unlock(&p->lock); 00270 return res; 00271 }
|
|
Definition at line 131 of file chan_features.c. References ast_log(), LOG_WARNING, feature_sub::owner, and feature_pvt::subs. Referenced by features_answer(), features_call(), features_digit(), features_hangup(), features_indicate(), features_read(), and features_write(). 00132 { 00133 int x; 00134 if (!owner) { 00135 ast_log(LOG_WARNING, "indexof called on NULL owner??\n"); 00136 return -1; 00137 } 00138 for (x=0; x<3; x++) { 00139 if (owner == p->subs[x].owner) 00140 return x; 00141 } 00142 return -1; 00143 }
|
|
Definition at line 123 of file chan_features.c. References feature_sub::alertpipebackup, feature_sub::inthreeway, feature_sub::pfd, and feature_sub::timingfdbackup. Referenced by features_alloc(). 00124 { 00125 sub->inthreeway = 0; 00126 sub->pfd = -1; 00127 sub->timingfdbackup = -1; 00128 sub->alertpipebackup[0] = sub->alertpipebackup[1] = -1; 00129 }
|
|
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 597 of file chan_features.c. References ASTERISK_GPL_KEY. 00598 { 00599 return ASTERISK_GPL_KEY; 00600 }
|
|
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 553 of file chan_features.c. References ast_channel_register(), ast_cli_register(), ast_log(), cli_show_features, features_tech, LOG_ERROR, and type. 00554 { 00555 /* Make sure we can register our sip channel type */ 00556 if (ast_channel_register(&features_tech)) { 00557 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type); 00558 return -1; 00559 } 00560 ast_cli_register(&cli_show_features); 00561 return 0; 00562 }
|
|
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 564 of file chan_features.c.
|
|
Definition at line 166 of file chan_features.c. References ast_channel::alertpipe, feature_sub::alertpipebackup, AST_MAX_FDS, ast_channel::fds, feature_sub::owner, feature_pvt::subs, ast_channel::timingfd, and feature_sub::timingfdbackup. Referenced by features_hangup(). 00167 { 00168 /* Restore timing/alertpipe */ 00169 p->subs[index].owner->timingfd = p->subs[index].timingfdbackup; 00170 p->subs[index].owner->alertpipe[0] = p->subs[index].alertpipebackup[0]; 00171 p->subs[index].owner->alertpipe[1] = p->subs[index].alertpipebackup[1]; 00172 p->subs[index].owner->fds[AST_MAX_FDS-1] = p->subs[index].alertpipebackup[0]; 00173 p->subs[index].owner->fds[AST_MAX_FDS-2] = p->subs[index].timingfdbackup; 00174 }
|
|
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 569 of file chan_features.c. References ast_channel_unregister(), ast_cli_unregister(), ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_show_features, features, features_tech, free, feature_pvt::next, and feature_pvt::owner. 00570 { 00571 struct feature_pvt *p, *prev; 00572 /* First, take us out of the channel loop */ 00573 ast_cli_unregister(&cli_show_features); 00574 ast_channel_unregister(&features_tech); 00575 if (!ast_mutex_lock(&featurelock)) { 00576 /* Hangup all interfaces if they have an owner */ 00577 for (p = features; p; p = p->next) { 00578 prev = p; 00579 if (p->owner) 00580 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 00581 free(prev); 00582 } 00583 features = NULL; 00584 ast_mutex_unlock(&featurelock); 00585 } else { 00586 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 00587 return -1; 00588 } 00589 return 0; 00590 }
|
|
|
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 592 of file chan_features.c. References usecnt. 00593 { 00594 return usecnt; 00595 }
|
|
Initial value: { { "feature", "show", "channels", NULL }, features_show, "Show status of feature channels", show_features_usage, NULL } Definition at line 549 of file chan_features.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 63 of file chan_features.c. |
|
Referenced by ast_feature_interpret(), features_alloc(), features_hangup(), features_show(), unload_module(), and zt_new(). |
|
Definition at line 107 of file chan_features.c. Referenced by features_new(), load_module(), and unload_module(). |
|
Initial value: "Usage: feature show channels\n" " Provides summary information on feature channels.\n" Definition at line 545 of file chan_features.c. |
|
Definition at line 65 of file chan_features.c. |
|
Definition at line 64 of file chan_features.c. |
|
Definition at line 67 of file chan_features.c. |