📄 chan_features.c
字号:
struct feature_pvt *p = ast->tech_pvt; int res = -1; int x; /* Queue up a frame representing the indication as a control frame */ ast_mutex_lock(&p->lock); x = indexof(p, ast, 0); if (!x && p->subchan) res = ast_indicate(p->subchan, condition); ast_mutex_unlock(&p->lock); return res;}static int features_digit_begin(struct ast_channel *ast, char digit){ struct feature_pvt *p = ast->tech_pvt; int res = -1; int x; /* Queue up a frame representing the indication as a control frame */ ast_mutex_lock(&p->lock); x = indexof(p, ast, 0); if (!x && p->subchan) res = ast_senddigit_begin(p->subchan, digit); ast_mutex_unlock(&p->lock); return res;}static int features_digit_end(struct ast_channel *ast, char digit, unsigned int duration){ struct feature_pvt *p = ast->tech_pvt; int res = -1; int x; /* Queue up a frame representing the indication as a control frame */ ast_mutex_lock(&p->lock); x = indexof(p, ast, 0); if (!x && p->subchan) res = ast_senddigit_end(p->subchan, digit, duration); ast_mutex_unlock(&p->lock); return res;}static int features_call(struct ast_channel *ast, char *dest, int timeout){ struct feature_pvt *p = ast->tech_pvt; int res = -1; int x; char *dest2; dest2 = strchr(dest, '/'); if (dest2) { ast_mutex_lock(&p->lock); x = indexof(p, ast, 0); if (!x && p->subchan) { p->subchan->cid.cid_num = ast_strdup(p->owner->cid.cid_num); p->subchan->cid.cid_name = ast_strdup(p->owner->cid.cid_name); p->subchan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis); p->subchan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani); p->subchan->cid.cid_pres = p->owner->cid.cid_pres; ast_string_field_set(p->subchan, language, p->owner->language); ast_string_field_set(p->subchan, accountcode, p->owner->accountcode); p->subchan->cdrflags = p->owner->cdrflags; res = ast_call(p->subchan, dest2, timeout); update_features(p, x); } else ast_log(LOG_NOTICE, "Uhm yah, not quite there with the call waiting...\n"); ast_mutex_unlock(&p->lock); } return res;}static int features_hangup(struct ast_channel *ast){ struct feature_pvt *p = ast->tech_pvt; int x; ast_mutex_lock(&p->lock); x = indexof(p, ast, 0); if (x > -1) { restore_channel(p, x); p->subs[x].owner = NULL; /* XXX Re-arrange, unconference, etc XXX */ } ast->tech_pvt = NULL; if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { ast_mutex_unlock(&p->lock); /* Remove from list */ AST_LIST_LOCK(&features); AST_LIST_REMOVE(&features, p, list); AST_LIST_UNLOCK(&features); ast_mutex_lock(&p->lock); /* And destroy */ if (p->subchan) ast_hangup(p->subchan); ast_mutex_unlock(&p->lock); ast_mutex_destroy(&p->lock); free(p); return 0; } ast_mutex_unlock(&p->lock); return 0;}static struct feature_pvt *features_alloc(char *data, int format){ struct feature_pvt *tmp; char *dest=NULL; char *tech; int x; int status; struct ast_channel *chan; tech = ast_strdupa(data); if (tech) { dest = strchr(tech, '/'); if (dest) { *dest = '\0'; dest++; } } if (!tech || !dest) { ast_log(LOG_NOTICE, "Format for feature channel is Feature/Tech/Dest ('%s' not valid)!\n", data); return NULL; } AST_LIST_LOCK(&features); AST_LIST_TRAVERSE(&features, tmp, list) { if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest)) break; } AST_LIST_UNLOCK(&features); if (!tmp) { chan = ast_request(tech, format, dest, &status); if (!chan) { ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest); return NULL; } tmp = malloc(sizeof(struct feature_pvt)); if (tmp) { memset(tmp, 0, sizeof(struct feature_pvt)); for (x=0;x<3;x++) init_sub(tmp->subs + x); ast_mutex_init(&tmp->lock); ast_copy_string(tmp->tech, tech, sizeof(tmp->tech)); ast_copy_string(tmp->dest, dest, sizeof(tmp->dest)); tmp->subchan = chan; AST_LIST_LOCK(&features); AST_LIST_INSERT_HEAD(&features, tmp, list); AST_LIST_UNLOCK(&features); } } return tmp;}static struct ast_channel *features_new(struct feature_pvt *p, int state, int index){ struct ast_channel *tmp; int x,y; char *b2 = 0; if (!p->subchan) { ast_log(LOG_WARNING, "Called upon channel with no subchan:(\n"); return NULL; } if (p->subs[index].owner) { ast_log(LOG_WARNING, "Called to put index %d already there!\n", index); return NULL; } /* figure out what you want the name to be */ for (x=1;x<4;x++) { if (b2) free(b2); b2 = ast_safe_string_alloc("%s/%s-%d", p->tech, p->dest, x); for (y=0;y<3;y++) { if (y == index) continue; if (p->subs[y].owner && !strcasecmp(p->subs[y].owner->name, b2)) break; } if (y >= 3) break; } tmp = ast_channel_alloc(0, state, 0,0, "", "", "", 0, "Feature/%s", b2); /* free up the name, it was copied into the channel name */ if (b2) free(b2); if (!tmp) { ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); return NULL; } tmp->tech = &features_tech; tmp->writeformat = p->subchan->writeformat; tmp->rawwriteformat = p->subchan->rawwriteformat; tmp->readformat = p->subchan->readformat; tmp->rawreadformat = p->subchan->rawreadformat; tmp->nativeformats = p->subchan->readformat; tmp->tech_pvt = p; p->subs[index].owner = tmp; if (!p->owner) p->owner = tmp; ast_module_ref(ast_module_info->self); return tmp;}static struct ast_channel *features_request(const char *type, int format, void *data, int *cause){ struct feature_pvt *p; struct ast_channel *chan = NULL; p = features_alloc(data, format); if (p && !p->subs[SUB_REAL].owner) chan = features_new(p, AST_STATE_DOWN, SUB_REAL); if (chan) update_features(p,SUB_REAL); return chan;}static int features_show(int fd, int argc, char **argv){ struct feature_pvt *p; if (argc != 3) return RESULT_SHOWUSAGE; if (AST_LIST_EMPTY(&features)) { ast_cli(fd, "No feature channels in use\n"); return RESULT_SUCCESS; } AST_LIST_LOCK(&features); AST_LIST_TRAVERSE(&features, p, list) { ast_mutex_lock(&p->lock); ast_cli(fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest); ast_mutex_unlock(&p->lock); } AST_LIST_UNLOCK(&features); return RESULT_SUCCESS;}static char show_features_usage[] = "Usage: feature show channels\n"" Provides summary information on feature channels.\n";static struct ast_cli_entry cli_features[] = { { { "feature", "show", "channels", NULL }, features_show, "List status of feature channels", show_features_usage },};static int load_module(void){ /* Make sure we can register our sip channel type */ if (ast_channel_register(&features_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'Feature'\n"); return -1; } ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry)); return 0;}static int unload_module(void){ struct feature_pvt *p; /* First, take us out of the channel loop */ ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry)); ast_channel_unregister(&features_tech); if (!AST_LIST_LOCK(&features)) return -1; /* Hangup all interfaces if they have an owner */ AST_LIST_TRAVERSE_SAFE_BEGIN(&features, p, list) { if (p->owner) ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); AST_LIST_REMOVE_CURRENT(&features, list); free(p); } AST_LIST_TRAVERSE_SAFE_END AST_LIST_UNLOCK(&features); return 0;}AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Feature Proxy Channel");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -