#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/stringfields.h"
Include 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 | |
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 68 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 91 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 90 of file chan_features.c.
Referenced by __unload_module(), __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(), zap_show_channel(), 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 92 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] |
Definition at line 396 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(), LOG_NOTICE, malloc, and feature_pvt::tech.
Referenced by features_request().
00397 { 00398 struct feature_pvt *tmp; 00399 char *dest=NULL; 00400 char *tech; 00401 int x; 00402 int status; 00403 struct ast_channel *chan; 00404 00405 tech = ast_strdupa(data); 00406 if (tech) { 00407 dest = strchr(tech, '/'); 00408 if (dest) { 00409 *dest = '\0'; 00410 dest++; 00411 } 00412 } 00413 if (!tech || !dest) { 00414 ast_log(LOG_NOTICE, "Format for feature channel is Feature/Tech/Dest ('%s' not valid)!\n", 00415 data); 00416 return NULL; 00417 } 00418 AST_LIST_LOCK(&features); 00419 AST_LIST_TRAVERSE(&features, tmp, list) { 00420 if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest)) 00421 break; 00422 } 00423 AST_LIST_UNLOCK(&features); 00424 if (!tmp) { 00425 chan = ast_request(tech, format, dest, &status); 00426 if (!chan) { 00427 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest); 00428 return NULL; 00429 } 00430 tmp = malloc(sizeof(struct feature_pvt)); 00431 if (tmp) { 00432 memset(tmp, 0, sizeof(struct feature_pvt)); 00433 for (x=0;x<3;x++) 00434 init_sub(tmp->subs + x); 00435 ast_mutex_init(&tmp->lock); 00436 ast_copy_string(tmp->tech, tech, sizeof(tmp->tech)); 00437 ast_copy_string(tmp->dest, dest, sizeof(tmp->dest)); 00438 tmp->subchan = chan; 00439 AST_LIST_LOCK(&features); 00440 AST_LIST_INSERT_HEAD(&features, tmp, list); 00441 AST_LIST_UNLOCK(&features); 00442 } 00443 } 00444 return tmp; 00445 }
static int features_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 226 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.
00227 { 00228 struct feature_pvt *p = ast->tech_pvt; 00229 int res = -1; 00230 int x; 00231 00232 ast_mutex_lock(&p->lock); 00233 x = indexof(p, ast, 0); 00234 if (!x && p->subchan) 00235 res = ast_answer(p->subchan); 00236 ast_mutex_unlock(&p->lock); 00237 return res; 00238 }
static int features_call | ( | struct ast_channel * | ast, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 333 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().
00334 { 00335 struct feature_pvt *p = ast->tech_pvt; 00336 int res = -1; 00337 int x; 00338 char *dest2; 00339 00340 dest2 = strchr(dest, '/'); 00341 if (dest2) { 00342 ast_mutex_lock(&p->lock); 00343 x = indexof(p, ast, 0); 00344 if (!x && p->subchan) { 00345 p->subchan->cid.cid_num = ast_strdup(p->owner->cid.cid_num); 00346 p->subchan->cid.cid_name = ast_strdup(p->owner->cid.cid_name); 00347 p->subchan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis); 00348 p->subchan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani); 00349 00350 p->subchan->cid.cid_pres = p->owner->cid.cid_pres; 00351 ast_string_field_set(p->subchan, language, p->owner->language); 00352 ast_string_field_set(p->subchan, accountcode, p->owner->accountcode); 00353 p->subchan->cdrflags = p->owner->cdrflags; 00354 res = ast_call(p->subchan, dest2, timeout); 00355 update_features(p, x); 00356 } else 00357 ast_log(LOG_NOTICE, "Uhm yah, not quite there with the call waiting...\n"); 00358 ast_mutex_unlock(&p->lock); 00359 } 00360 return res; 00361 }
static int features_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 302 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.
00303 { 00304 struct feature_pvt *p = ast->tech_pvt; 00305 int res = -1; 00306 int x; 00307 00308 /* Queue up a frame representing the indication as a control frame */ 00309 ast_mutex_lock(&p->lock); 00310 x = indexof(p, ast, 0); 00311 if (!x && p->subchan) 00312 res = ast_senddigit_begin(p->subchan, digit); 00313 ast_mutex_unlock(&p->lock); 00314 00315 return res; 00316 }
static int features_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 318 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.
00319 { 00320 struct feature_pvt *p = ast->tech_pvt; 00321 int res = -1; 00322 int x; 00323 00324 /* Queue up a frame representing the indication as a control frame */ 00325 ast_mutex_lock(&p->lock); 00326 x = indexof(p, ast, 0); 00327 if (!x && p->subchan) 00328 res = ast_senddigit_end(p->subchan, digit, duration); 00329 ast_mutex_unlock(&p->lock); 00330 return res; 00331 }
static int features_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 271 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.
00272 { 00273 struct feature_pvt *p = newchan->tech_pvt; 00274 int x; 00275 00276 ast_mutex_lock(&p->lock); 00277 if (p->owner == oldchan) 00278 p->owner = newchan; 00279 for (x = 0; x < 3; x++) { 00280 if (p->subs[x].owner == oldchan) 00281 p->subs[x].owner = newchan; 00282 } 00283 ast_mutex_unlock(&p->lock); 00284 return 0; 00285 }
static int features_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 363 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.
00364 { 00365 struct feature_pvt *p = ast->tech_pvt; 00366 int x; 00367 00368 ast_mutex_lock(&p->lock); 00369 x = indexof(p, ast, 0); 00370 if (x > -1) { 00371 restore_channel(p, x); 00372 p->subs[x].owner = NULL; 00373 /* XXX Re-arrange, unconference, etc XXX */ 00374 } 00375 ast->tech_pvt = NULL; 00376 00377 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 00378 ast_mutex_unlock(&p->lock); 00379 /* Remove from list */ 00380 AST_LIST_LOCK(&features); 00381 AST_LIST_REMOVE(&features, p, list); 00382 AST_LIST_UNLOCK(&features); 00383 ast_mutex_lock(&p->lock); 00384 /* And destroy */ 00385 if (p->subchan) 00386 ast_hangup(p->subchan); 00387 ast_mutex_unlock(&p->lock); 00388 ast_mutex_destroy(&p->lock); 00389 free(p); 00390 return 0; 00391 } 00392 ast_mutex_unlock(&p->lock); 00393 return 0; 00394 }
static int features_indicate | ( | struct ast_channel * | ast, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 287 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.
00288 { 00289 struct feature_pvt *p = ast->tech_pvt; 00290 int res = -1; 00291 int x; 00292 00293 /* Queue up a frame representing the indication as a control frame */ 00294 ast_mutex_lock(&p->lock); 00295 x = indexof(p, ast, 0); 00296 if (!x && p->subchan) 00297 res = ast_indicate(p->subchan, condition); 00298 ast_mutex_unlock(&p->lock); 00299 return res; 00300 }
static struct ast_channel* features_new | ( | struct feature_pvt * | p, | |
int | state, | |||
int | index | |||
) | [static] |
Definition at line 447 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().
00448 { 00449 struct ast_channel *tmp; 00450 int x,y; 00451 char *b2 = 0; 00452 if (!p->subchan) { 00453 ast_log(LOG_WARNING, "Called upon channel with no subchan:(\n"); 00454 return NULL; 00455 } 00456 if (p->subs[index].owner) { 00457 ast_log(LOG_WARNING, "Called to put index %d already there!\n", index); 00458 return NULL; 00459 } 00460 /* figure out what you want the name to be */ 00461 for (x=1;x<4;x++) { 00462 if (b2) 00463 free(b2); 00464 b2 = ast_safe_string_alloc("%s/%s-%d", p->tech, p->dest, x); 00465 for (y=0;y<3;y++) { 00466 if (y == index) 00467 continue; 00468 if (p->subs[y].owner && !strcasecmp(p->subs[y].owner->name, b2)) 00469 break; 00470 } 00471 if (y >= 3) 00472 break; 00473 } 00474 tmp = ast_channel_alloc(0, state, 0,0, "", "", "", 0, "Feature/%s", b2); 00475 /* free up the name, it was copied into the channel name */ 00476 if (b2) 00477 free(b2); 00478 if (!tmp) { 00479 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 00480 return NULL; 00481 } 00482 tmp->tech = &features_tech; 00483 tmp->writeformat = p->subchan->writeformat; 00484 tmp->rawwriteformat = p->subchan->rawwriteformat; 00485 tmp->readformat = p->subchan->readformat; 00486 tmp->rawreadformat = p->subchan->rawreadformat; 00487 tmp->nativeformats = p->subchan->readformat; 00488 tmp->tech_pvt = p; 00489 p->subs[index].owner = tmp; 00490 if (!p->owner) 00491 p->owner = tmp; 00492 ast_module_ref(ast_module_info->self); 00493 return tmp; 00494 }
static struct ast_frame * features_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 240 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().
00241 { 00242 struct feature_pvt *p = ast->tech_pvt; 00243 struct ast_frame *f; 00244 int x; 00245 00246 f = &ast_null_frame; 00247 ast_mutex_lock(&p->lock); 00248 x = indexof(p, ast, 0); 00249 if (!x && p->subchan) { 00250 update_features(p, x); 00251 f = ast_read(p->subchan); 00252 } 00253 ast_mutex_unlock(&p->lock); 00254 return f; 00255 }
static struct ast_channel * features_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 497 of file chan_features.c.
References AST_STATE_DOWN, features_alloc(), features_new(), feature_sub::owner, SUB_REAL, feature_pvt::subs, and update_features().
00498 { 00499 struct feature_pvt *p; 00500 struct ast_channel *chan = NULL; 00501 00502 p = features_alloc(data, format); 00503 if (p && !p->subs[SUB_REAL].owner) 00504 chan = features_new(p, AST_STATE_DOWN, SUB_REAL); 00505 if (chan) 00506 update_features(p,SUB_REAL); 00507 return chan; 00508 }
static int features_show | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 510 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.
00511 { 00512 struct feature_pvt *p; 00513 00514 if (argc != 3) 00515 return RESULT_SHOWUSAGE; 00516 00517 if (AST_LIST_EMPTY(&features)) { 00518 ast_cli(fd, "No feature channels in use\n"); 00519 return RESULT_SUCCESS; 00520 } 00521 00522 AST_LIST_LOCK(&features); 00523 AST_LIST_TRAVERSE(&features, p, list) { 00524 ast_mutex_lock(&p->lock); 00525 ast_cli(fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest); 00526 ast_mutex_unlock(&p->lock); 00527 } 00528 AST_LIST_UNLOCK(&features); 00529 return RESULT_SUCCESS; 00530 }
static int features_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 257 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.
00258 { 00259 struct feature_pvt *p = ast->tech_pvt; 00260 int res = -1; 00261 int x; 00262 00263 ast_mutex_lock(&p->lock); 00264 x = indexof(p, ast, 0); 00265 if (!x && p->subchan) 00266 res = ast_write(p->subchan, f); 00267 ast_mutex_unlock(&p->lock); 00268 return res; 00269 }
static int indexof | ( | struct feature_pvt * | p, | |
struct ast_channel * | owner, | |||
int | nullok | |||
) | [inline, static] |
Definition at line 130 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().
00131 { 00132 int x; 00133 if (!owner) { 00134 ast_log(LOG_WARNING, "indexof called on NULL owner??\n"); 00135 return -1; 00136 } 00137 for (x=0; x<3; x++) { 00138 if (owner == p->subs[x].owner) 00139 return x; 00140 } 00141 return -1; 00142 }
static void init_sub | ( | struct feature_sub * | sub | ) | [inline, static] |
Definition at line 122 of file chan_features.c.
References feature_sub::alertpipebackup, feature_sub::inthreeway, feature_sub::pfd, and feature_sub::timingfdbackup.
Referenced by features_alloc().
00123 { 00124 sub->inthreeway = 0; 00125 sub->pfd = -1; 00126 sub->timingfdbackup = -1; 00127 sub->alertpipebackup[0] = sub->alertpipebackup[1] = -1; 00128 }
static int load_module | ( | void | ) | [static] |
Definition at line 542 of file chan_features.c.
References ast_channel_register(), ast_cli_register_multiple(), ast_log(), cli_features, features_tech, and LOG_ERROR.
00543 { 00544 /* Make sure we can register our sip channel type */ 00545 if (ast_channel_register(&features_tech)) { 00546 ast_log(LOG_ERROR, "Unable to register channel class 'Feature'\n"); 00547 return -1; 00548 } 00549 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry)); 00550 return 0; 00551 }
static void restore_channel | ( | struct feature_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 165 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().
00166 { 00167 /* Restore timing/alertpipe */ 00168 p->subs[index].owner->timingfd = p->subs[index].timingfdbackup; 00169 p->subs[index].owner->alertpipe[0] = p->subs[index].alertpipebackup[0]; 00170 p->subs[index].owner->alertpipe[1] = p->subs[index].alertpipebackup[1]; 00171 p->subs[index].owner->fds[AST_ALERT_FD] = p->subs[index].alertpipebackup[0]; 00172 p->subs[index].owner->fds[AST_TIMING_FD] = p->subs[index].timingfdbackup; 00173 }
static int unload_module | ( | void | ) | [static] |
Definition at line 553 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.
00554 { 00555 struct feature_pvt *p; 00556 00557 /* First, take us out of the channel loop */ 00558 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry)); 00559 ast_channel_unregister(&features_tech); 00560 00561 if (!AST_LIST_LOCK(&features)) 00562 return -1; 00563 /* Hangup all interfaces if they have an owner */ 00564 AST_LIST_TRAVERSE_SAFE_BEGIN(&features, p, list) { 00565 if (p->owner) 00566 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 00567 AST_LIST_REMOVE_CURRENT(&features, list); 00568 free(p); 00569 } 00570 AST_LIST_TRAVERSE_SAFE_END 00571 AST_LIST_UNLOCK(&features); 00572 00573 return 0; 00574 }
static void update_features | ( | struct feature_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 175 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().
00176 { 00177 int x; 00178 if (p->subs[index].owner) { 00179 for (x=0; x<AST_MAX_FDS; x++) { 00180 if (index) 00181 p->subs[index].owner->fds[x] = -1; 00182 else 00183 p->subs[index].owner->fds[x] = p->subchan->fds[x]; 00184 } 00185 if (!index) { 00186 /* Copy timings from master channel */ 00187 p->subs[index].owner->timingfd = p->subchan->timingfd; 00188 p->subs[index].owner->alertpipe[0] = p->subchan->alertpipe[0]; 00189 p->subs[index].owner->alertpipe[1] = p->subchan->alertpipe[1]; 00190 if (p->subs[index].owner->nativeformats != p->subchan->readformat) { 00191 p->subs[index].owner->nativeformats = p->subchan->readformat; 00192 if (p->subs[index].owner->readformat) 00193 ast_set_read_format(p->subs[index].owner, p->subs[index].owner->readformat); 00194 if (p->subs[index].owner->writeformat) 00195 ast_set_write_format(p->subs[index].owner, p->subs[index].owner->writeformat); 00196 } 00197 } else{ 00198 restore_channel(p, index); 00199 } 00200 } 00201 }
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 536 of file chan_features.c.
Referenced by load_module(), and unload_module().
struct ast_channel_tech features_tech [static] |
Definition at line 105 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 532 of file chan_features.c.
const char tdesc[] = "Feature Proxy Channel Driver" [static] |
Definition at line 66 of file chan_features.c.