#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 |
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 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_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 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.
#define SUB_REAL 0 |
Definition at line 93 of file chan_features.c.
#define SUB_THREEWAY 2 |
Definition at line 95 of file chan_features.c.
static void __reg_module | ( | void | ) | [static] |
Definition at line 579 of file chan_features.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 579 of file chan_features.c.
static struct feature_pvt* features_alloc | ( | char * | data, | |
int | format | |||
) | [static] |
Definition at line 399 of file chan_features.c.
References 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, feature_pvt::dest, init_sub(), LOG_NOTICE, malloc, 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 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().
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::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.
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] |
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::name, 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] |
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] |
Definition at line 500 of file chan_features.c.
References AST_STATE_DOWN, features_alloc(), features_new(), 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::list, feature_pvt::lock, ast_channel::name, 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(), f, 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, 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().
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, feature_pvt::list, 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_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 579 of file chan_features.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 579 of file chan_features.c.
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.