📄 chan_skinny.c
字号:
static int skinny_reset_device(int fd, int argc, char *argv[]){ struct skinny_device *d; struct skinny_req *req; if (argc < 3 || argc > 4) { return RESULT_SHOWUSAGE; } ast_mutex_lock(&devicelock); for (d = devices; d; d = d->next) { int fullrestart = 0; if (!strcasecmp(argv[2], d->id) || !strcasecmp(argv[2], "all")) { if (!(d->session)) continue; if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE))) continue; if (argc == 4 && !strcasecmp(argv[3], "restart")) fullrestart = 1; if (fullrestart) req->data.reset.resetType = 2; else req->data.reset.resetType = 1; if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "%s device %s.\n", (fullrestart) ? "Restarting" : "Resetting", d->id); transmit_response(d->session, req); } } ast_mutex_unlock(&devicelock); return RESULT_SUCCESS;}static char *device2str(int type){ char *tmp; switch (type) { case SKINNY_DEVICE_NONE: return "No Device"; case SKINNY_DEVICE_30SPPLUS: return "30SP Plus"; case SKINNY_DEVICE_12SPPLUS: return "12SP Plus"; case SKINNY_DEVICE_12SP: return "12SP"; case SKINNY_DEVICE_12: return "12"; case SKINNY_DEVICE_30VIP: return "30VIP"; case SKINNY_DEVICE_7910: return "7910"; case SKINNY_DEVICE_7960: return "7960"; case SKINNY_DEVICE_7940: return "7940"; case SKINNY_DEVICE_7935: return "7935"; case SKINNY_DEVICE_ATA186: return "ATA186"; case SKINNY_DEVICE_7941: return "7941"; case SKINNY_DEVICE_7971: return "7971"; case SKINNY_DEVICE_7914: return "7914"; case SKINNY_DEVICE_7985: return "7985"; case SKINNY_DEVICE_7911: return "7911"; case SKINNY_DEVICE_7961GE: return "7961GE"; case SKINNY_DEVICE_7941GE: return "7941GE"; case SKINNY_DEVICE_7931: return "7931"; case SKINNY_DEVICE_7921: return "7921"; case SKINNY_DEVICE_7906: return "7906"; case SKINNY_DEVICE_7962: return "7962"; case SKINNY_DEVICE_7937: return "7937"; case SKINNY_DEVICE_7942: return "7942"; case SKINNY_DEVICE_7945: return "7945"; case SKINNY_DEVICE_7965: return "7965"; case SKINNY_DEVICE_7975: return "7975"; case SKINNY_DEVICE_7905: return "7905"; case SKINNY_DEVICE_7920: return "7920"; case SKINNY_DEVICE_7970: return "7970"; case SKINNY_DEVICE_7912: return "7912"; case SKINNY_DEVICE_7902: return "7902"; case SKINNY_DEVICE_CIPC: return "IP Communicator"; case SKINNY_DEVICE_7961: return "7961"; case SKINNY_DEVICE_7936: return "7936"; case SKINNY_DEVICE_SCCPGATEWAY_AN: return "SCCPGATEWAY_AN"; case SKINNY_DEVICE_SCCPGATEWAY_BRI: return "SCCPGATEWAY_BRI"; case SKINNY_DEVICE_UNKNOWN: return "Unknown"; default: if (!(tmp = ast_threadstorage_get(&device2str_threadbuf, DEVICE2STR_BUFSIZE))) return "Unknown"; snprintf(tmp, DEVICE2STR_BUFSIZE, "UNKNOWN-%d", type); return tmp; }}static int skinny_show_devices(int fd, int argc, char *argv[]){ struct skinny_device *d; struct skinny_line *l; int numlines = 0; if (argc != 3) { return RESULT_SHOWUSAGE; } ast_mutex_lock(&devicelock); ast_cli(fd, "Name DeviceId IP Type R NL\n"); ast_cli(fd, "-------------------- ---------------- --------------- --------------- - --\n"); for (d = devices; d; d = d->next) { numlines = 0; for (l = d->lines; l; l = l->next) { numlines++; } ast_cli(fd, "%-20s %-16s %-15s %-15s %c %2d\n", d->name, d->id, d->session?ast_inet_ntoa(d->session->sin.sin_addr):"", device2str(d->type), d->registered?'Y':'N', numlines); } ast_mutex_unlock(&devicelock); return RESULT_SUCCESS;}static int skinny_show_lines(int fd, int argc, char *argv[]){ struct skinny_device *d; struct skinny_line *l; if (argc != 3) { return RESULT_SHOWUSAGE; } ast_mutex_lock(&devicelock); ast_cli(fd, "Device Name Instance Name Label \n"); ast_cli(fd, "-------------------- -------- -------------------- --------------------\n"); for (d = devices; d; d = d->next) { for (l = d->lines; l; l = l->next) { ast_cli(fd, "%-20s %8d %-20s %-20s\n", d->name, l->instance, l->name, l->label); } } ast_mutex_unlock(&devicelock); return RESULT_SUCCESS;}static char show_devices_usage[] ="Usage: skinny show devices\n"" Lists all devices known to the Skinny subsystem.\n";static char show_lines_usage[] ="Usage: skinny show lines\n"" Lists all lines known to the Skinny subsystem.\n";static char debug_usage[] ="Usage: skinny set debug\n"" Enables dumping of Skinny packets for debugging purposes\n";static char no_debug_usage[] ="Usage: skinny set debug off\n"" Disables dumping of Skinny packets for debugging purposes\n";static char reset_usage[] ="Usage: skinny reset <DeviceId|all> [restart]\n"" Causes a Skinny device to reset itself, optionally with a full restart\n";static struct ast_cli_entry cli_skinny[] = { { { "skinny", "show", "devices", NULL }, skinny_show_devices, "List defined Skinny devices", show_devices_usage }, { { "skinny", "show", "lines", NULL }, skinny_show_lines, "List defined Skinny lines per device", show_lines_usage }, { { "skinny", "set", "debug", NULL }, skinny_do_debug, "Enable Skinny debugging", debug_usage }, { { "skinny", "set", "debug", "off", NULL }, skinny_no_debug, "Disable Skinny debugging", no_debug_usage }, { { "skinny", "reset", NULL }, skinny_reset_device, "Reset Skinny device(s)", reset_usage, complete_skinny_reset },};#if 0static struct skinny_paging_device *build_paging_device(const char *cat, struct ast_variable *v){ return NULL;}#endifstatic struct skinny_device *build_device(const char *cat, struct ast_variable *v){ struct skinny_device *d; struct skinny_line *l; struct skinny_speeddial *sd; struct skinny_addon *a; int lineInstance = 1; int speeddialInstance = 1; int y = 0; if (!(d = ast_calloc(1, sizeof(struct skinny_device)))) { return NULL; } else { ast_copy_string(d->name, cat, sizeof(d->name)); d->lastlineinstance = 1; d->capability = default_capability; d->prefs = default_prefs; d->earlyrtp = 1; while(v) { if (!strcasecmp(v->name, "host")) { if (ast_get_ip(&d->addr, v->value)) { free(d); return NULL; } } else if (!strcasecmp(v->name, "port")) { d->addr.sin_port = htons(atoi(v->value)); } else if (!strcasecmp(v->name, "device")) { ast_copy_string(d->id, v->value, sizeof(d->id)); } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { d->ha = ast_append_ha(v->name, v->value, d->ha); } else if (!strcasecmp(v->name, "context")) { ast_copy_string(context, v->value, sizeof(context)); } else if (!strcasecmp(v->name, "allow")) { ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 1); } else if (!strcasecmp(v->name, "disallow")) { ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 0); } else if (!strcasecmp(v->name, "version")) { ast_copy_string(d->version_id, v->value, sizeof(d->version_id)); } else if (!strcasecmp(v->name, "earlyrtp")) { d->earlyrtp = ast_true(v->value); } else if (!strcasecmp(v->name, "nat")) { nat = ast_true(v->value); } else if (!strcasecmp(v->name, "callerid")) { if (!strcasecmp(v->value, "asreceived")) { cid_num[0] = '\0'; cid_name[0] = '\0'; } else { ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); } } else if (!strcasecmp(v->name, "language")) { ast_copy_string(language, v->value, sizeof(language)); } else if (!strcasecmp(v->name, "accountcode")) { ast_copy_string(accountcode, v->value, sizeof(accountcode)); } else if (!strcasecmp(v->name, "amaflags")) { y = ast_cdr_amaflags2int(v->value); if (y < 0) { ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); } else { amaflags = y; } } else if (!strcasecmp(v->name, "mohinterpret") || !strcasecmp(v->name, "musiconhold")) { ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret)); } else if (!strcasecmp(v->name, "mohsuggest")) { ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest)); } else if (!strcasecmp(v->name, "callgroup")) { cur_callergroup = ast_get_group(v->value); } else if (!strcasecmp(v->name, "pickupgroup")) { cur_pickupgroup = ast_get_group(v->value); } else if (!strcasecmp(v->name, "immediate")) { immediate = ast_true(v->value); } else if (!strcasecmp(v->name, "cancallforward")) { cancallforward = ast_true(v->value); } else if (!strcasecmp(v->name, "mailbox")) { ast_copy_string(mailbox, v->value, sizeof(mailbox)); } else if (!strcasecmp(v->name, "hasvoicemail")) { if (ast_true(v->value) && ast_strlen_zero(mailbox)) { ast_copy_string(mailbox, cat, sizeof(mailbox)); } } else if (!strcasecmp(v->name, "callreturn")) { callreturn = ast_true(v->value); } else if (!strcasecmp(v->name, "callwaiting")) { callwaiting = ast_true(v->value); } else if (!strcasecmp(v->name, "transfer")) { transfer = ast_true(v->value); } else if (!strcasecmp(v->name, "threewaycalling")) { threewaycalling = ast_true(v->value); } else if (!strcasecmp(v->name, "mwiblink")) { mwiblink = ast_true(v->value); } else if (!strcasecmp(v->name, "linelabel")) { ast_copy_string(linelabel, v->value, sizeof(linelabel)); } else if (!strcasecmp(v->name, "speeddial")) { if (!(sd = ast_calloc(1, sizeof(struct skinny_speeddial)))) { return NULL; } else { char *stringp, *exten, *label; stringp = v->value; exten = strsep(&stringp, ","); label = strsep(&stringp, ","); ast_mutex_init(&sd->lock); ast_copy_string(sd->exten, exten, sizeof(sd->exten)); if (label) ast_copy_string(sd->label, label, sizeof(sd->label)); else ast_copy_string(sd->label, exten, sizeof(sd->label)); sd->instance = speeddialInstance++; sd->parent = d; sd->next = d->speeddials; d->speeddials = sd; } } else if (!strcasecmp(v->name, "addon")) { if (!(a = ast_calloc(1, sizeof(struct skinny_addon)))) { return NULL; } else { ast_mutex_init(&a->lock); ast_copy_string(a->type, v->value, sizeof(a->type)); a->next = d->addons; d->addons = a; } } else if (!strcasecmp(v->name, "trunk") || !strcasecmp(v->name, "line")) { if (!(l = ast_calloc(1, sizeof(struct skinny_line)))) { return NULL; } else { ast_mutex_init(&l->lock); ast_copy_string(l->name, v->value, sizeof(l->name)); /* XXX Should we check for uniqueness?? XXX */ ast_copy_string(l->context, context, sizeof(l->context)); ast_copy_string(l->cid_num, cid_num, sizeof(l->cid_num)); ast_copy_string(l->cid_name, cid_name, sizeof(l->cid_name)); ast_copy_string(l->label, linelabel, sizeof(l->label)); ast_copy_string(l->language, language, sizeof(l->language)); ast_copy_string(l->mohinterpret, mohinterpret, sizeof(l->mohinterpret)); ast_copy_string(l->mohsuggest, mohsuggest, sizeof(l->mohsuggest)); ast_copy_string(l->mailbox, mailbox, sizeof(l->mailbox)); if (!ast_strlen_zero(mailbox)) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, d->name, l->name); } l->msgstate = -1; l->capability = d->capability; l->prefs = d->prefs; l->parent = d; if (!strcasecmp(v->name, "trunk")) { l->type = TYPE_TRUNK; } else { l->type = TYPE_LINE; } l->immediate = immediate; l->callgroup = cur_callergroup; l->pickupgroup = cur_pickupgroup; l->callreturn = callreturn; l->cancallforward = cancallforward; l->callwaiting = callwaiting; l->transfer = transfer; l->threewaycalling = threewaycalling; l->mwiblink = mwiblink; l->onhooktime = time(NULL); l->instance = lineInstance++; /* ASSUME we're onhook at this point */ l->hookstate = SKINNY_ONHOOK; l->nat = nat; l->next = d->lines; d->lines = l; } } else { ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno); } v = v->next; } if (!d->lines) { ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n"); return NULL; } if (/*d->addr.sin_addr.s_addr && */!ntohs(d->addr.sin_port)) { d->addr.sin_port = htons(DEFAULT_SKINNY_PORT); }#if 0 /* I don't think we need this anymore at all, since d->ourip is set in skinny_register now */ if (d->addr.sin_addr.s_addr) { /* XXX See note above, in 'host' option. */ if (ast_ouraddrfor(&d->addr.sin_addr, &d->ourip)) { d->ourip = __ourip; } } else { d->ourip = __ourip; }#endif } return d;}static void start_rtp(struct skinny_subchannel *sub){ struct skinny_line *l = sub->parent; struct skinny_device *d = l->parent; int hasvideo = 0; ast_mutex_lock(&sub->lock); /* Allocate the RTP */ sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); if (hasvideo) sub->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); if (sub->rtp && sub->owner) { sub->owner->fds[0] = ast_rtp_fd(sub->rtp); sub->owner->fds[1] = ast_rtcp_fd(sub->rtp); } if (hasvideo && sub->vrtp && sub->owner) { sub->owner->fds[2] = ast_rtp_fd(sub->vrtp); sub->owner->fds[3] = ast_rtcp_fd(sub->vrtp); } if (sub->rtp) { ast_rtp_setnat(sub->rtp, l->nat); } if (sub->vrtp) { ast_rtp_setnat(sub->vrtp, l->nat); } /* Set Frame packetization */ if (sub->rtp) ast_rtp_codec_setpref(sub->rtp, &l->prefs); /* Create the RTP connection */ transmit_connect(d->session, sub); ast_mutex_unlock(&sub->lock);}static void *skinny_newcall(void *data){ struct ast_channel *c = data; struct skinny_subchannel *sub = c->tech_pvt; struct skinny_line *l = sub->parent; struct skinny_device *d = l->parent; struct skinnysession *s = d->session; int res = 0; ast_copy_string(l->lastnumberdialed, c->exten, sizeof(l->lastnumberdialed)); ast_set_callerid(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -