#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"
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 | |
static | AST_LIST_HEAD_STATIC (features, feature_pvt) |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Feature Proxy Channel") | |
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 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) |
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_cli_entry | cli_features [] |
static struct ast_channel_tech | features_tech |
static char | show_features_usage [] |
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 71 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 94 of file chan_features.c.
Referenced by available(), features_hangup(), ss_thread(), zap_show_channel(), zt_bridge(), zt_call(), zt_handle_event(), zt_hangup(), zt_read(), and zt_request().
#define SUB_REAL 0 |
Definition at line 93 of file chan_features.c.
Referenced by __zt_exception(), attempt_transfer(), available(), bump_gains(), chandup(), check_for_conference(), destroy_channel(), disable_dtmf_detect(), do_monitor(), enable_dtmf_detect(), features_hangup(), features_request(), get_alarms(), handle_init_event(), mkintf(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), ss_thread(), update_conf(), zt_answer(), zt_bridge(), zt_call(), zt_confmute(), zt_digit_begin(), zt_digit_end(), zt_disable_ec(), zt_enable_ec(), zt_handle_event(), zt_hangup(), zt_indicate(), zt_new(), zt_read(), zt_request(), zt_ring_phone(), zt_setoption(), zt_train_ec(), and zt_unlink().
#define SUB_THREEWAY 2 |
Definition at line 95 of file chan_features.c.
Referenced by attempt_transfer(), available(), features_hangup(), ss_thread(), zap_show_channel(), zt_answer(), zt_bridge(), zt_handle_event(), and zt_hangup().
static AST_LIST_HEAD_STATIC | ( | features | , | |
feature_pvt | ||||
) | [static] |
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Feature Proxy Channel" | ||||
) |
static struct feature_pvt* features_alloc | ( | char * | data, | |
int | format | |||
) | [static, read] |
Definition at line 399 of file chan_features.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_request(), ast_strdupa, feature_pvt::dest, init_sub(), feature_pvt::lock, LOG_NOTICE, malloc, feature_pvt::subchan, feature_pvt::subs, and feature_pvt::tech.
Referenced by features_request().
00400 { 00401 struct feature_pvt *tmp; 00402 char *dest=NULL; 00403 char *tech; 00404 int x; 00405 int status; 00406 struct ast_channel *chan; 00407 00408 tech = ast_strdupa(data); 00409 if (tech) { 00410 dest = strchr(tech, '/'); 00411 if (dest) { 00412 *dest = '\0'; 00413 dest++; 00414 } 00415 } 00416 if (!tech || !dest) { 00417 ast_log(LOG_NOTICE, "Format for feature channel is Feature/Tech/Dest ('%s' not valid)!\n", 00418 data); 00419 return NULL; 00420 } 00421 AST_LIST_LOCK(&features); 00422 AST_LIST_TRAVERSE(&features, tmp, list) { 00423 if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest)) 00424 break; 00425 } 00426 AST_LIST_UNLOCK(&features); 00427 if (!tmp) { 00428 chan = ast_request(tech, format, dest, &status); 00429 if (!chan) { 00430 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest); 00431 return NULL; 00432 } 00433 tmp = malloc(sizeof(struct feature_pvt)); 00434 if (tmp) { 00435 memset(tmp, 0, sizeof(struct feature_pvt)); 00436 for (x=0;x<3;x++) 00437 init_sub(tmp->subs + x); 00438 ast_mutex_init(&tmp->lock); 00439 ast_copy_string(tmp->tech, tech, sizeof(tmp->tech)); 00440 ast_copy_string(tmp->dest, dest, sizeof(tmp->dest)); 00441 tmp->subchan = chan; 00442 AST_LIST_LOCK(&features); 00443 AST_LIST_INSERT_HEAD(&features, tmp, list); 00444 AST_LIST_UNLOCK(&features); 00445 } 00446 } 00447 return tmp; 00448 }
static int features_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 229 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.
00230 { 00231 struct feature_pvt *p = ast->tech_pvt; 00232 int res = -1; 00233 int x; 00234 00235 ast_mutex_lock(&p->lock); 00236 x = indexof(p, ast, 0); 00237 if (!x && p->subchan) 00238 res = ast_answer(p->subchan); 00239 ast_mutex_unlock(&p->lock); 00240 return res; 00241 }
static int features_call | ( | struct ast_channel * | ast, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 336 of file chan_features.c.
References 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(), language, feature_pvt::lock, LOG_NOTICE, feature_pvt::owner, feature_pvt::subchan, ast_channel::tech_pvt, and update_features().
00337 { 00338 struct feature_pvt *p = ast->tech_pvt; 00339 int res = -1; 00340 int x; 00341 char *dest2; 00342 00343 dest2 = strchr(dest, '/'); 00344 if (dest2) { 00345 ast_mutex_lock(&p->lock); 00346 x = indexof(p, ast, 0); 00347 if (!x && p->subchan) { 00348 p->subchan->cid.cid_num = ast_strdup(p->owner->cid.cid_num); 00349 p->subchan->cid.cid_name = ast_strdup(p->owner->cid.cid_name); 00350 p->subchan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis); 00351 p->subchan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani); 00352 00353 p->subchan->cid.cid_pres = p->owner->cid.cid_pres; 00354 ast_string_field_set(p->subchan, language, p->owner->language); 00355 ast_string_field_set(p->subchan, accountcode, p->owner->accountcode); 00356 p->subchan->cdrflags = p->owner->cdrflags; 00357 res = ast_call(p->subchan, dest2, timeout); 00358 update_features(p, x); 00359 } else 00360 ast_log(LOG_NOTICE, "Uhm yah, not quite there with the call waiting...\n"); 00361 ast_mutex_unlock(&p->lock); 00362 } 00363 return res; 00364 }
static int features_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 305 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.
00306 { 00307 struct feature_pvt *p = ast->tech_pvt; 00308 int res = -1; 00309 int x; 00310 00311 /* Queue up a frame representing the indication as a control frame */ 00312 ast_mutex_lock(&p->lock); 00313 x = indexof(p, ast, 0); 00314 if (!x && p->subchan) 00315 res = ast_senddigit_begin(p->subchan, digit); 00316 ast_mutex_unlock(&p->lock); 00317 00318 return res; 00319 }
static int features_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 321 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.
00322 { 00323 struct feature_pvt *p = ast->tech_pvt; 00324 int res = -1; 00325 int x; 00326 00327 /* Queue up a frame representing the indication as a control frame */ 00328 ast_mutex_lock(&p->lock); 00329 x = indexof(p, ast, 0); 00330 if (!x && p->subchan) 00331 res = ast_senddigit_end(p->subchan, digit, duration); 00332 ast_mutex_unlock(&p->lock); 00333 return res; 00334 }
static int features_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 274 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.
00275 { 00276 struct feature_pvt *p = newchan->tech_pvt; 00277 int x; 00278 00279 ast_mutex_lock(&p->lock); 00280 if (p->owner == oldchan) 00281 p->owner = newchan; 00282 for (x = 0; x < 3; x++) { 00283 if (p->subs[x].owner == oldchan) 00284 p->subs[x].owner = newchan; 00285 } 00286 ast_mutex_unlock(&p->lock); 00287 return 0; 00288 }
static int features_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 366 of file chan_features.c.
References ast_hangup(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), free, indexof(), 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.
00367 { 00368 struct feature_pvt *p = ast->tech_pvt; 00369 int x; 00370 00371 ast_mutex_lock(&p->lock); 00372 x = indexof(p, ast, 0); 00373 if (x > -1) { 00374 restore_channel(p, x); 00375 p->subs[x].owner = NULL; 00376 /* XXX Re-arrange, unconference, etc XXX */ 00377 } 00378 ast->tech_pvt = NULL; 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_LIST_LOCK(&features); 00384 AST_LIST_REMOVE(&features, p, list); 00385 AST_LIST_UNLOCK(&features); 00386 ast_mutex_lock(&p->lock); 00387 /* And destroy */ 00388 if (p->subchan) 00389 ast_hangup(p->subchan); 00390 ast_mutex_unlock(&p->lock); 00391 ast_mutex_destroy(&p->lock); 00392 free(p); 00393 return 0; 00394 } 00395 ast_mutex_unlock(&p->lock); 00396 return 0; 00397 }
static int features_indicate | ( | struct ast_channel * | ast, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 290 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.
00291 { 00292 struct feature_pvt *p = ast->tech_pvt; 00293 int res = -1; 00294 int x; 00295 00296 /* Queue up a frame representing the indication as a control frame */ 00297 ast_mutex_lock(&p->lock); 00298 x = indexof(p, ast, 0); 00299 if (!x && p->subchan) 00300 res = ast_indicate(p->subchan, condition); 00301 ast_mutex_unlock(&p->lock); 00302 return res; 00303 }
static struct ast_channel* features_new | ( | struct feature_pvt * | p, | |
int | state, | |||
int | index | |||
) | [static, read] |
Definition at line 450 of file chan_features.c.
References ast_channel_alloc(), ast_log(), ast_module_ref(), ast_safe_string_alloc(), feature_pvt::dest, features_tech, free, LOG_WARNING, ast_channel::nativeformats, feature_pvt::owner, feature_sub::owner, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, feature_pvt::subchan, feature_pvt::subs, ast_channel::tech, feature_pvt::tech, ast_channel::tech_pvt, and ast_channel::writeformat.
Referenced by features_request().
00451 { 00452 struct ast_channel *tmp; 00453 int x,y; 00454 char *b2 = 0; 00455 if (!p->subchan) { 00456 ast_log(LOG_WARNING, "Called upon channel with no subchan:(\n"); 00457 return NULL; 00458 } 00459 if (p->subs[index].owner) { 00460 ast_log(LOG_WARNING, "Called to put index %d already there!\n", index); 00461 return NULL; 00462 } 00463 /* figure out what you want the name to be */ 00464 for (x=1;x<4;x++) { 00465 if (b2) 00466 free(b2); 00467 b2 = ast_safe_string_alloc("%s/%s-%d", p->tech, p->dest, x); 00468 for (y=0;y<3;y++) { 00469 if (y == index) 00470 continue; 00471 if (p->subs[y].owner && !strcasecmp(p->subs[y].owner->name, b2)) 00472 break; 00473 } 00474 if (y >= 3) 00475 break; 00476 } 00477 tmp = ast_channel_alloc(0, state, 0,0, "", "", "", 0, "Feature/%s", b2); 00478 /* free up the name, it was copied into the channel name */ 00479 if (b2) 00480 free(b2); 00481 if (!tmp) { 00482 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 00483 return NULL; 00484 } 00485 tmp->tech = &features_tech; 00486 tmp->writeformat = p->subchan->writeformat; 00487 tmp->rawwriteformat = p->subchan->rawwriteformat; 00488 tmp->readformat = p->subchan->readformat; 00489 tmp->rawreadformat = p->subchan->rawreadformat; 00490 tmp->nativeformats = p->subchan->readformat; 00491 tmp->tech_pvt = p; 00492 p->subs[index].owner = tmp; 00493 if (!p->owner) 00494 p->owner = tmp; 00495 ast_module_ref(ast_module_info->self); 00496 return tmp; 00497 }
static struct ast_frame * features_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 243 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().
00244 { 00245 struct feature_pvt *p = ast->tech_pvt; 00246 struct ast_frame *f; 00247 int x; 00248 00249 f = &ast_null_frame; 00250 ast_mutex_lock(&p->lock); 00251 x = indexof(p, ast, 0); 00252 if (!x && p->subchan) { 00253 update_features(p, x); 00254 f = ast_read(p->subchan); 00255 } 00256 ast_mutex_unlock(&p->lock); 00257 return f; 00258 }
static struct ast_channel * features_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static, read] |
Definition at line 500 of file chan_features.c.
References AST_STATE_DOWN, features_alloc(), features_new(), feature_sub::owner, SUB_REAL, feature_pvt::subs, and update_features().
00501 { 00502 struct feature_pvt *p; 00503 struct ast_channel *chan = NULL; 00504 00505 p = features_alloc(data, format); 00506 if (p && !p->subs[SUB_REAL].owner) 00507 chan = features_new(p, AST_STATE_DOWN, SUB_REAL); 00508 if (chan) 00509 update_features(p,SUB_REAL); 00510 return chan; 00511 }
static int features_show | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 513 of file chan_features.c.
References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), feature_pvt::dest, feature_pvt::lock, feature_pvt::owner, RESULT_SHOWUSAGE, RESULT_SUCCESS, and feature_pvt::tech.
00514 { 00515 struct feature_pvt *p; 00516 00517 if (argc != 3) 00518 return RESULT_SHOWUSAGE; 00519 00520 if (AST_LIST_EMPTY(&features)) { 00521 ast_cli(fd, "No feature channels in use\n"); 00522 return RESULT_SUCCESS; 00523 } 00524 00525 AST_LIST_LOCK(&features); 00526 AST_LIST_TRAVERSE(&features, p, list) { 00527 ast_mutex_lock(&p->lock); 00528 ast_cli(fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest); 00529 ast_mutex_unlock(&p->lock); 00530 } 00531 AST_LIST_UNLOCK(&features); 00532 return RESULT_SUCCESS; 00533 }
static int features_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 260 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.
00261 { 00262 struct feature_pvt *p = ast->tech_pvt; 00263 int res = -1; 00264 int x; 00265 00266 ast_mutex_lock(&p->lock); 00267 x = indexof(p, ast, 0); 00268 if (!x && p->subchan) 00269 res = ast_write(p->subchan, f); 00270 ast_mutex_unlock(&p->lock); 00271 return res; 00272 }
static int indexof | ( | struct feature_pvt * | p, | |
struct ast_channel * | owner, | |||
int | nullok | |||
) | [inline, static] |
Definition at line 133 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_begin(), features_digit_end(), features_hangup(), features_indicate(), features_read(), and features_write().
00134 { 00135 int x; 00136 if (!owner) { 00137 ast_log(LOG_WARNING, "indexof called on NULL owner??\n"); 00138 return -1; 00139 } 00140 for (x=0; x<3; x++) { 00141 if (owner == p->subs[x].owner) 00142 return x; 00143 } 00144 return -1; 00145 }
static void init_sub | ( | struct feature_sub * | sub | ) | [inline, static] |
Definition at line 125 of file chan_features.c.
References feature_sub::alertpipebackup, feature_sub::inthreeway, feature_sub::pfd, and feature_sub::timingfdbackup.
Referenced by features_alloc().
00126 { 00127 sub->inthreeway = 0; 00128 sub->pfd = -1; 00129 sub->timingfdbackup = -1; 00130 sub->alertpipebackup[0] = sub->alertpipebackup[1] = -1; 00131 }
static int load_module | ( | void | ) | [static] |
Definition at line 545 of file chan_features.c.
References ast_channel_register(), ast_cli_register_multiple(), ast_log(), cli_features, features_tech, and LOG_ERROR.
00546 { 00547 /* Make sure we can register our sip channel type */ 00548 if (ast_channel_register(&features_tech)) { 00549 ast_log(LOG_ERROR, "Unable to register channel class 'Feature'\n"); 00550 return -1; 00551 } 00552 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry)); 00553 return 0; 00554 }
static void restore_channel | ( | struct feature_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 168 of file chan_features.c.
References ast_channel::alertpipe, feature_sub::alertpipebackup, AST_ALERT_FD, AST_TIMING_FD, ast_channel::fds, feature_sub::owner, feature_pvt::subs, ast_channel::timingfd, and feature_sub::timingfdbackup.
Referenced by features_hangup(), and update_features().
00169 { 00170 /* Restore timing/alertpipe */ 00171 p->subs[index].owner->timingfd = p->subs[index].timingfdbackup; 00172 p->subs[index].owner->alertpipe[0] = p->subs[index].alertpipebackup[0]; 00173 p->subs[index].owner->alertpipe[1] = p->subs[index].alertpipebackup[1]; 00174 p->subs[index].owner->fds[AST_ALERT_FD] = p->subs[index].alertpipebackup[0]; 00175 p->subs[index].owner->fds[AST_TIMING_FD] = p->subs[index].timingfdbackup; 00176 }
static int unload_module | ( | void | ) | [static] |
Definition at line 556 of file chan_features.c.
References ast_channel_unregister(), ast_cli_unregister_multiple(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_features, features_tech, free, and feature_pvt::owner.
00557 { 00558 struct feature_pvt *p; 00559 00560 /* First, take us out of the channel loop */ 00561 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry)); 00562 ast_channel_unregister(&features_tech); 00563 00564 if (!AST_LIST_LOCK(&features)) 00565 return -1; 00566 /* Hangup all interfaces if they have an owner */ 00567 AST_LIST_TRAVERSE_SAFE_BEGIN(&features, p, list) { 00568 if (p->owner) 00569 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 00570 AST_LIST_REMOVE_CURRENT(&features, list); 00571 free(p); 00572 } 00573 AST_LIST_TRAVERSE_SAFE_END 00574 AST_LIST_UNLOCK(&features); 00575 00576 return 0; 00577 }
static void update_features | ( | struct feature_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 178 of file chan_features.c.
References ast_channel::alertpipe, 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().
00179 { 00180 int x; 00181 if (p->subs[index].owner) { 00182 for (x=0; x<AST_MAX_FDS; x++) { 00183 if (index) 00184 p->subs[index].owner->fds[x] = -1; 00185 else 00186 p->subs[index].owner->fds[x] = p->subchan->fds[x]; 00187 } 00188 if (!index) { 00189 /* Copy timings from master channel */ 00190 p->subs[index].owner->timingfd = p->subchan->timingfd; 00191 p->subs[index].owner->alertpipe[0] = p->subchan->alertpipe[0]; 00192 p->subs[index].owner->alertpipe[1] = p->subchan->alertpipe[1]; 00193 if (p->subs[index].owner->nativeformats != p->subchan->readformat) { 00194 p->subs[index].owner->nativeformats = p->subchan->readformat; 00195 if (p->subs[index].owner->readformat) 00196 ast_set_read_format(p->subs[index].owner, p->subs[index].owner->readformat); 00197 if (p->subs[index].owner->writeformat) 00198 ast_set_write_format(p->subs[index].owner, p->subs[index].owner->writeformat); 00199 } 00200 } else{ 00201 restore_channel(p, index); 00202 } 00203 } 00204 }
struct ast_cli_entry cli_features[] [static] |
Initial value:
{ { { "feature", "show", "channels", NULL }, features_show, "List status of feature channels", show_features_usage }, }
Definition at line 539 of file chan_features.c.
Referenced by load_module(), and unload_module().
struct ast_channel_tech features_tech [static] |
Definition at line 108 of file chan_features.c.
Referenced by features_new(), load_module(), and unload_module().
char show_features_usage[] [static] |
Initial value:
"Usage: feature show channels\n" " Provides summary information on feature channels.\n"
Definition at line 535 of file chan_features.c.
const char tdesc[] = "Feature Proxy Channel Driver" [static] |
Definition at line 69 of file chan_features.c.