#include "asterisk.h"
#include <fcntl.h>
#include <sys/signal.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.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"
Go to the source code of this file.
Data Structures | |
struct | feature_pvt |
struct | feature_sub |
struct | features |
Defines | |
#define | IS_OUTBOUND(a, b) (a == b->chan ? 1 : 0) |
#define | SUB_CALLWAIT 1 |
#define | SUB_REAL 0 |
#define | SUB_THREEWAY 2 |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
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_begin (struct ast_channel *ast, char digit) |
static int | features_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
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, const void *data, size_t datalen) |
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 char * | features_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
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) |
static int | load_module (void) |
static void | restore_channel (struct feature_pvt *p, int index) |
static int | unload_module (void) |
static void | update_features (struct feature_pvt *p, int index) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Feature Proxy Channel" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_cli_entry | cli_features [] |
static struct ast_channel_tech | features_tech |
static const char | tdesc [] = "Feature Proxy Channel Driver" |
Definition in file chan_features.c.
#define IS_OUTBOUND | ( | a, | |||
b | ) | (a == b->chan ? 1 : 0) |
Definition at line 59 of file chan_features.c.
Referenced by local_answer(), local_digit_begin(), local_digit_end(), local_hangup(), local_indicate(), local_sendhtml(), local_sendtext(), and local_write().
#define SUB_CALLWAIT 1 |
Definition at line 82 of file chan_features.c.
#define SUB_REAL 0 |
Definition at line 81 of file chan_features.c.
#define SUB_THREEWAY 2 |
Definition at line 83 of file chan_features.c.
static void __reg_module | ( | void | ) | [static] |
Definition at line 573 of file chan_features.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 573 of file chan_features.c.
static struct feature_pvt* features_alloc | ( | char * | data, | |
int | format | |||
) | [static] |
Definition at line 387 of file chan_features.c.
References ast_calloc, ast_copy_string(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_request(), ast_strdupa, chan, feature_pvt::dest, init_sub(), LOG_NOTICE, status, and feature_pvt::tech.
Referenced by features_request().
00388 { 00389 struct feature_pvt *tmp; 00390 char *dest=NULL; 00391 char *tech; 00392 int x; 00393 int status; 00394 struct ast_channel *chan; 00395 00396 tech = ast_strdupa(data); 00397 if (tech) { 00398 dest = strchr(tech, '/'); 00399 if (dest) { 00400 *dest = '\0'; 00401 dest++; 00402 } 00403 } 00404 if (!tech || !dest) { 00405 ast_log(LOG_NOTICE, "Format for feature channel is Feature/Tech/Dest ('%s' not valid)!\n", 00406 data); 00407 return NULL; 00408 } 00409 AST_LIST_LOCK(&features); 00410 AST_LIST_TRAVERSE(&features, tmp, list) { 00411 if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest)) 00412 break; 00413 } 00414 AST_LIST_UNLOCK(&features); 00415 if (!tmp) { 00416 chan = ast_request(tech, format, dest, &status); 00417 if (!chan) { 00418 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest); 00419 return NULL; 00420 } 00421 tmp = ast_calloc(1, sizeof(*tmp)); 00422 if (tmp) { 00423 for (x=0;x<3;x++) 00424 init_sub(tmp->subs + x); 00425 ast_mutex_init(&tmp->lock); 00426 ast_copy_string(tmp->tech, tech, sizeof(tmp->tech)); 00427 ast_copy_string(tmp->dest, dest, sizeof(tmp->dest)); 00428 tmp->subchan = chan; 00429 AST_LIST_LOCK(&features); 00430 AST_LIST_INSERT_HEAD(&features, tmp, list); 00431 AST_LIST_UNLOCK(&features); 00432 } 00433 } 00434 return tmp; 00435 }
static int features_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 217 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.
00218 { 00219 struct feature_pvt *p = ast->tech_pvt; 00220 int res = -1; 00221 int x; 00222 00223 ast_mutex_lock(&p->lock); 00224 x = indexof(p, ast, 0); 00225 if (!x && p->subchan) 00226 res = ast_answer(p->subchan); 00227 ast_mutex_unlock(&p->lock); 00228 return res; 00229 }
static int features_call | ( | struct ast_channel * | ast, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 324 of file chan_features.c.
References ast_channel::accountcode, accountcode, ast_call(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, ast_string_field_set, ast_channel::cdrflags, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, indexof(), ast_channel::language, language, feature_pvt::lock, LOG_NOTICE, feature_pvt::owner, feature_pvt::subchan, ast_channel::tech_pvt, and update_features().
00325 { 00326 struct feature_pvt *p = ast->tech_pvt; 00327 int res = -1; 00328 int x; 00329 char *dest2; 00330 00331 dest2 = strchr(dest, '/'); 00332 if (dest2) { 00333 ast_mutex_lock(&p->lock); 00334 x = indexof(p, ast, 0); 00335 if (!x && p->subchan) { 00336 p->subchan->cid.cid_num = ast_strdup(p->owner->cid.cid_num); 00337 p->subchan->cid.cid_name = ast_strdup(p->owner->cid.cid_name); 00338 p->subchan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis); 00339 p->subchan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani); 00340 00341 p->subchan->cid.cid_pres = p->owner->cid.cid_pres; 00342 ast_string_field_set(p->subchan, language, p->owner->language); 00343 ast_string_field_set(p->subchan, accountcode, p->owner->accountcode); 00344 p->subchan->cdrflags = p->owner->cdrflags; 00345 res = ast_call(p->subchan, dest2, timeout); 00346 update_features(p, x); 00347 } else 00348 ast_log(LOG_NOTICE, "Uhm yah, not quite there with the call waiting...\n"); 00349 ast_mutex_unlock(&p->lock); 00350 } 00351 return res; 00352 }
static int features_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 293 of file chan_features.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_senddigit_begin(), indexof(), feature_pvt::lock, feature_pvt::subchan, and ast_channel::tech_pvt.
00294 { 00295 struct feature_pvt *p = ast->tech_pvt; 00296 int res = -1; 00297 int x; 00298 00299 /* Queue up a frame representing the indication as a control frame */ 00300 ast_mutex_lock(&p->lock); 00301 x = indexof(p, ast, 0); 00302 if (!x && p->subchan) 00303 res = ast_senddigit_begin(p->subchan, digit); 00304 ast_mutex_unlock(&p->lock); 00305 00306 return res; 00307 }
static int features_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 309 of file chan_features.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_senddigit_end(), indexof(), feature_pvt::lock, feature_pvt::subchan, and ast_channel::tech_pvt.
00310 { 00311 struct feature_pvt *p = ast->tech_pvt; 00312 int res = -1; 00313 int x; 00314 00315 /* Queue up a frame representing the indication as a control frame */ 00316 ast_mutex_lock(&p->lock); 00317 x = indexof(p, ast, 0); 00318 if (!x && p->subchan) 00319 res = ast_senddigit_end(p->subchan, digit, duration); 00320 ast_mutex_unlock(&p->lock); 00321 return res; 00322 }
static int features_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 262 of file chan_features.c.
References ast_mutex_lock(), ast_mutex_unlock(), feature_pvt::lock, feature_sub::owner, feature_pvt::owner, feature_pvt::subs, and ast_channel::tech_pvt.
00263 { 00264 struct feature_pvt *p = newchan->tech_pvt; 00265 int x; 00266 00267 ast_mutex_lock(&p->lock); 00268 if (p->owner == oldchan) 00269 p->owner = newchan; 00270 for (x = 0; x < 3; x++) { 00271 if (p->subs[x].owner == oldchan) 00272 p->subs[x].owner = newchan; 00273 } 00274 ast_mutex_unlock(&p->lock); 00275 return 0; 00276 }
static int features_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 354 of file chan_features.c.
References ast_free, ast_hangup(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), indexof(), feature_pvt::list, feature_pvt::lock, feature_sub::owner, restore_channel(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, feature_pvt::subchan, feature_pvt::subs, and ast_channel::tech_pvt.
00355 { 00356 struct feature_pvt *p = ast->tech_pvt; 00357 int x; 00358 00359 ast_mutex_lock(&p->lock); 00360 x = indexof(p, ast, 0); 00361 if (x > -1) { 00362 restore_channel(p, x); 00363 p->subs[x].owner = NULL; 00364 /* XXX Re-arrange, unconference, etc XXX */ 00365 } 00366 ast->tech_pvt = NULL; 00367 00368 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 00369 ast_mutex_unlock(&p->lock); 00370 /* Remove from list */ 00371 AST_LIST_LOCK(&features); 00372 AST_LIST_REMOVE(&features, p, list); 00373 AST_LIST_UNLOCK(&features); 00374 ast_mutex_lock(&p->lock); 00375 /* And destroy */ 00376 if (p->subchan) 00377 ast_hangup(p->subchan); 00378 ast_mutex_unlock(&p->lock); 00379 ast_mutex_destroy(&p->lock); 00380 ast_free(p); 00381 return 0; 00382 } 00383 ast_mutex_unlock(&p->lock); 00384 return 0; 00385 }
static int features_indicate | ( | struct ast_channel * | ast, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 278 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.
00279 { 00280 struct feature_pvt *p = ast->tech_pvt; 00281 int res = -1; 00282 int x; 00283 00284 /* Queue up a frame representing the indication as a control frame */ 00285 ast_mutex_lock(&p->lock); 00286 x = indexof(p, ast, 0); 00287 if (!x && p->subchan) 00288 res = ast_indicate(p->subchan, condition); 00289 ast_mutex_unlock(&p->lock); 00290 return res; 00291 }
static struct ast_channel* features_new | ( | struct feature_pvt * | p, | |
int | state, | |||
int | index | |||
) | [static] |
Definition at line 437 of file chan_features.c.
References asprintf, ast_free, ast_log(), feature_pvt::dest, errno, LOG_WARNING, ast_channel::name, feature_sub::owner, feature_pvt::subchan, feature_pvt::subs, and feature_pvt::tech.
Referenced by features_request().
00438 { 00439 struct ast_channel *tmp; 00440 int x,y; 00441 char *b2 = 0; 00442 if (!p->subchan) { 00443 ast_log(LOG_WARNING, "Called upon channel with no subchan:(\n"); 00444 return NULL; 00445 } 00446 if (p->subs[index].owner) { 00447 ast_log(LOG_WARNING, "Called to put index %d already there!\n", index); 00448 return NULL; 00449 } 00450 /* figure out what you want the name to be */ 00451 for (x=1;x<4;x++) { 00452 if (b2) 00453 ast_free(b2); 00454 if (asprintf(&b2, "%s/%s-%d", p->tech, p->dest, x) < 0) { 00455 ast_log(LOG_WARNING, "Unable to create channel name: %s\n", strerror(errno)); 00456 b2 = NULL; 00457 continue; 00458 } 00459 for (y=0;y<3;y++) { 00460 if (y == index) 00461 continue; 00462 if (p->subs[y].owner && !strcasecmp(p->subs[y].owner->name, b2)) 00463 break; 00464 } 00465 if (y >= 3) 00466 break; 00467 } 00468 tmp = ast_channel_alloc(0, state, 0,0, "", "", "", 0, "Feature/%s", b2); 00469 /* free up the name, it was copied into the channel name */ 00470 if (b2) 00471 ast_free(b2); 00472 if (!tmp) { 00473 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 00474 return NULL; 00475 } 00476 tmp->tech = &features_tech; 00477 tmp->writeformat = p->subchan->writeformat; 00478 tmp->rawwriteformat = p->subchan->rawwriteformat; 00479 tmp->readformat = p->subchan->readformat; 00480 tmp->rawreadformat = p->subchan->rawreadformat; 00481 tmp->nativeformats = p->subchan->readformat; 00482 tmp->tech_pvt = p; 00483 p->subs[index].owner = tmp; 00484 if (!p->owner) 00485 p->owner = tmp; 00486 ast_module_ref(ast_module_info->self); 00487 return tmp; 00488 }
static struct ast_frame * features_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 231 of file chan_features.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_read(), f, indexof(), feature_pvt::lock, feature_pvt::subchan, ast_channel::tech_pvt, and update_features().
00232 { 00233 struct feature_pvt *p = ast->tech_pvt; 00234 struct ast_frame *f; 00235 int x; 00236 00237 f = &ast_null_frame; 00238 ast_mutex_lock(&p->lock); 00239 x = indexof(p, ast, 0); 00240 if (!x && p->subchan) { 00241 update_features(p, x); 00242 f = ast_read(p->subchan); 00243 } 00244 ast_mutex_unlock(&p->lock); 00245 return f; 00246 }
static struct ast_channel * features_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 491 of file chan_features.c.
References AST_STATE_DOWN, chan, features_alloc(), features_new(), SUB_REAL, feature_pvt::subs, and update_features().
00492 { 00493 struct feature_pvt *p; 00494 struct ast_channel *chan = NULL; 00495 00496 p = features_alloc(data, format); 00497 if (p && !p->subs[SUB_REAL].owner) 00498 chan = features_new(p, AST_STATE_DOWN, SUB_REAL); 00499 if (chan) 00500 update_features(p,SUB_REAL); 00501 return chan; 00502 }
static char* features_show | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 504 of file chan_features.c.
References ast_cli_args::argc, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, feature_pvt::dest, ast_cli_args::fd, feature_pvt::list, feature_pvt::lock, ast_channel::name, feature_pvt::owner, feature_pvt::tech, and ast_cli_entry::usage.
00505 { 00506 struct feature_pvt *p; 00507 00508 switch (cmd) { 00509 case CLI_INIT: 00510 e->command = "feature show channels"; 00511 e->usage = 00512 "Usage: feature show channels\n" 00513 " Provides summary information on feature channels.\n"; 00514 return NULL; 00515 case CLI_GENERATE: 00516 return NULL; 00517 } 00518 00519 if (a->argc != 3) 00520 return CLI_SHOWUSAGE; 00521 00522 if (AST_LIST_EMPTY(&features)) { 00523 ast_cli(a->fd, "No feature channels in use\n"); 00524 return CLI_SUCCESS; 00525 } 00526 00527 AST_LIST_LOCK(&features); 00528 AST_LIST_TRAVERSE(&features, p, list) { 00529 ast_mutex_lock(&p->lock); 00530 ast_cli(a->fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest); 00531 ast_mutex_unlock(&p->lock); 00532 } 00533 AST_LIST_UNLOCK(&features); 00534 return CLI_SUCCESS; 00535 }
static int features_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 248 of file chan_features.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_write(), f, indexof(), feature_pvt::lock, feature_pvt::subchan, and ast_channel::tech_pvt.
00249 { 00250 struct feature_pvt *p = ast->tech_pvt; 00251 int res = -1; 00252 int x; 00253 00254 ast_mutex_lock(&p->lock); 00255 x = indexof(p, ast, 0); 00256 if (!x && p->subchan) 00257 res = ast_write(p->subchan, f); 00258 ast_mutex_unlock(&p->lock); 00259 return res; 00260 }
static int indexof | ( | struct feature_pvt * | p, | |
struct ast_channel * | owner, | |||
int | nullok | |||
) | [inline, static] |
Definition at line 121 of file chan_features.c.
References ast_log(), LOG_WARNING, feature_sub::owner, feature_pvt::owner, and feature_pvt::subs.
Referenced by features_answer(), features_call(), features_digit_begin(), features_digit_end(), features_hangup(), features_indicate(), features_read(), and features_write().
00122 { 00123 int x; 00124 if (!owner) { 00125 ast_log(LOG_WARNING, "indexof called on NULL owner??\n"); 00126 return -1; 00127 } 00128 for (x=0; x<3; x++) { 00129 if (owner == p->subs[x].owner) 00130 return x; 00131 } 00132 return -1; 00133 }
static void init_sub | ( | struct feature_sub * | sub | ) | [inline, static] |
Definition at line 113 of file chan_features.c.
References feature_sub::alertpipebackup, feature_sub::inthreeway, feature_sub::pfd, and feature_sub::timingfdbackup.
Referenced by features_alloc().
00114 { 00115 sub->inthreeway = 0; 00116 sub->pfd = -1; 00117 sub->timingfdbackup = -1; 00118 sub->alertpipebackup[0] = sub->alertpipebackup[1] = -1; 00119 }
static int load_module | ( | void | ) | [static] |
Definition at line 541 of file chan_features.c.
References ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, cli_features, features_tech, and LOG_ERROR.
00542 { 00543 /* Make sure we can register our sip channel type */ 00544 if (ast_channel_register(&features_tech)) { 00545 ast_log(LOG_ERROR, "Unable to register channel class 'Feature'\n"); 00546 return AST_MODULE_LOAD_FAILURE; 00547 } 00548 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry)); 00549 return AST_MODULE_LOAD_SUCCESS; 00550 }
static void restore_channel | ( | struct feature_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 156 of file chan_features.c.
References ast_channel::alertpipe, feature_sub::alertpipebackup, AST_ALERT_FD, ast_channel_set_fd(), AST_TIMING_FD, feature_sub::owner, feature_pvt::subs, ast_channel::timingfd, and feature_sub::timingfdbackup.
Referenced by features_hangup(), and update_features().
00157 { 00158 /* Restore timing/alertpipe */ 00159 p->subs[index].owner->timingfd = p->subs[index].timingfdbackup; 00160 p->subs[index].owner->alertpipe[0] = p->subs[index].alertpipebackup[0]; 00161 p->subs[index].owner->alertpipe[1] = p->subs[index].alertpipebackup[1]; 00162 ast_channel_set_fd(p->subs[index].owner, AST_ALERT_FD, p->subs[index].alertpipebackup[0]); 00163 ast_channel_set_fd(p->subs[index].owner, AST_TIMING_FD, p->subs[index].timingfdbackup); 00164 }
static int unload_module | ( | void | ) | [static] |
Definition at line 552 of file chan_features.c.
References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_features, features_tech, feature_pvt::list, and feature_pvt::owner.
00553 { 00554 struct feature_pvt *p; 00555 00556 /* First, take us out of the channel loop */ 00557 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry)); 00558 ast_channel_unregister(&features_tech); 00559 00560 if (!AST_LIST_LOCK(&features)) 00561 return -1; 00562 /* Hangup all interfaces if they have an owner */ 00563 while ((p = AST_LIST_REMOVE_HEAD(&features, list))) { 00564 if (p->owner) 00565 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 00566 ast_free(p); 00567 } 00568 AST_LIST_UNLOCK(&features); 00569 00570 return 0; 00571 }
static void update_features | ( | struct feature_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 166 of file chan_features.c.
References ast_channel::alertpipe, ast_channel_set_fd(), AST_MAX_FDS, ast_set_read_format(), ast_set_write_format(), ast_channel::fds, ast_channel::nativeformats, feature_sub::owner, ast_channel::readformat, restore_channel(), feature_pvt::subchan, feature_pvt::subs, ast_channel::timingfd, and ast_channel::writeformat.
Referenced by features_call(), features_read(), and features_request().
00167 { 00168 int x; 00169 if (p->subs[index].owner) { 00170 for (x=0; x<AST_MAX_FDS; x++) { 00171 if (index) 00172 ast_channel_set_fd(p->subs[index].owner, x, -1); 00173 else 00174 ast_channel_set_fd(p->subs[index].owner, x, p->subchan->fds[x]); 00175 } 00176 if (!index) { 00177 /* Copy timings from master channel */ 00178 p->subs[index].owner->timingfd = p->subchan->timingfd; 00179 p->subs[index].owner->alertpipe[0] = p->subchan->alertpipe[0]; 00180 p->subs[index].owner->alertpipe[1] = p->subchan->alertpipe[1]; 00181 if (p->subs[index].owner->nativeformats != p->subchan->readformat) { 00182 p->subs[index].owner->nativeformats = p->subchan->readformat; 00183 if (p->subs[index].owner->readformat) 00184 ast_set_read_format(p->subs[index].owner, p->subs[index].owner->readformat); 00185 if (p->subs[index].owner->writeformat) 00186 ast_set_write_format(p->subs[index].owner, p->subs[index].owner->writeformat); 00187 } 00188 } else{ 00189 restore_channel(p, index); 00190 } 00191 } 00192 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Feature Proxy Channel" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 573 of file chan_features.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 573 of file chan_features.c.
struct ast_cli_entry cli_features[] [static] |
Initial value:
{ { .handler = features_show , .summary = "List status of feature channels" ,__VA_ARGS__ }, }
Definition at line 537 of file chan_features.c.
struct ast_channel_tech features_tech [static] |
const char tdesc[] = "Feature Proxy Channel Driver" [static] |
Definition at line 57 of file chan_features.c.