diff options
Diffstat (limited to 'channels/chan_dect.c')
-rw-r--r-- | channels/chan_dect.c | 330 |
1 files changed, 159 insertions, 171 deletions
diff --git a/channels/chan_dect.c b/channels/chan_dect.c index d870f785d..737074ef5 100644 --- a/channels/chan_dect.c +++ b/channels/chan_dect.c @@ -74,6 +74,7 @@ struct dect_pt { AST_LIST_ENTRY(dect_pt) list; char name[64]; char fullname[64]; + char ipei[DECT_IPEI_STRING_LEN + 1]; struct dect_ipui ipui; struct dect_tpui tpui; @@ -257,6 +258,118 @@ static struct dect_pt *dect_pt_get_by_ipui(const struct dect_ipui *ipui) return NULL; } +static struct dect_pt *dect_init_portable(const char *name) +{ + struct dect_pt *pt; + + pt = ast_calloc(1, sizeof(*pt)); + if (pt == NULL) + return NULL; + + if (name != NULL) { + ast_copy_string(pt->name, name, sizeof(pt->name)); + snprintf(pt->fullname, sizeof(pt->fullname), "DECT/%s", pt->name); + } + + ast_string_field_init(pt, 512); + ast_string_field_set(pt, context, dect_cfg.context); + ast_string_field_set(pt, regexten, ""); + ast_string_field_set(pt, language, dect_cfg.language); + ast_string_field_set(pt, cid_num, ""); + ast_string_field_set(pt, cid_name, ""); + ast_string_field_set(pt, ring_pattern, "0"); + + AST_LIST_INSERT_TAIL(&dect_pt_list, pt, list); + return pt; +} + +static int dect_alloc_extension(unsigned int *exten) +{ + const struct dect_pt *pt; + uint32_t bitmap[1024]; + unsigned int pext; + + memset(bitmap, 0, sizeof(bitmap)); + AST_LIST_TRAVERSE(&dect_pt_list, pt, list) { + pext = strtoul(pt->regexten, NULL, 0); + if (pext < dect_cfg.regexten_base || + pext >= 8 * sizeof(bitmap)) + continue; + pext -= dect_cfg.regexten_base; + + bitmap[pext / 32] |= 1 << (pext % 32); + } + + for (pext = 0; pext < 8 * sizeof(bitmap); pext++) { + if (!(bitmap[pext / 32] & (1 << (pext % 32)))) { + *exten = dect_cfg.regexten_base + pext; + return 1; + } + } + + return 0; +} + +static void dect_register_extension(const struct dect_pt *pt, bool onoff) +{ + struct pbx_find_info q = { .stacklen = 0 }; + char *ext, *extenp, *context; + char exten[256]; + + if (ast_strlen_zero(dect_cfg.regcontext)) + return; + + ast_copy_string(exten, S_OR(pt->regexten, pt->name), sizeof(exten)); + extenp = exten; + while ((ext = strsep(&extenp, "&")) != NULL) { + context = strchr(ext, '@'); + if (context != NULL) { + *context++ = '\0'; + if (!ast_context_find(context)) { + ast_log(LOG_WARNING, "Context %s for PT %s does not exist", + context, pt->name); + continue; + } + } else + context = dect_cfg.regcontext; + + if (onoff) { + if (!ast_exists_extension(NULL, context, ext, 1, NULL)) { + ast_add_extension(context, 1, ext, 1, NULL, NULL, "Dial", + (char *)pt->fullname, NULL, "DECT"); + } + } else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1, + NULL, "", E_MATCH)) { + ast_context_remove_extension(context, ext, 1, NULL); + } + } +} + +static void dect_init_tpui(struct dect_tpui *tpui, unsigned int exten) +{ + tpui->ia.digits[0] = exten > 10000 ? exten / 10000 % 10 : 0xb; + tpui->ia.digits[1] = exten > 1000 ? exten / 1000 % 10 : 0xb; + tpui->ia.digits[2] = exten > 100 ? exten / 100 % 10 : 0xb; + tpui->ia.digits[3] = exten > 10 ? exten / 10 % 10 : 0xb; + tpui->ia.digits[4] = exten > 1 ? exten / 1 % 10 : 0xb; +} + +static void dect_pt_set_extension(struct dect_pt *pt, unsigned int exten) +{ + ast_string_field_build(pt, cid_num, "%u", exten); + ast_string_field_build(pt, regexten, "%u", exten); + dect_init_tpui(&pt->tpui, exten); +} + +static void dect_pt_set_ipui(struct dect_pt *pt, const struct dect_ipui *ipui) +{ + pt->ipui = *ipui; + dect_format_ipei_string(&ipui->pun.n.ipei, pt->ipei); +} + +/* + * Database functions + */ static uint64_t dect_parse_num(const char *str) { uint64_t num; @@ -274,14 +387,14 @@ static void dect_parse_base64(const char *str, uint8_t *dst, unsigned int size) static void dect_db_remove(const struct dect_pt *pt) { - ast_db_deltree("dect", pt->name); + ast_db_deltree("dect", pt->ipei); } static int dect_db_put(const struct dect_pt *pt, const char *key, const char *value) { char ptkey[256]; - snprintf(ptkey, sizeof(ptkey), "%s/%s", pt->name, key); + snprintf(ptkey, sizeof(ptkey), "%s/%s", pt->ipei, key); return ast_db_put("dect", ptkey, value); } @@ -343,7 +456,8 @@ static int dect_db_parse_codec_list(struct dect_pt *pt, const char *key, if (tmp == NULL) return -1; strncpy(num, tmp + 1, sizeof(num)); - sscanf(num, "%u", &i); + if (sscanf(num, "%u", &i) != 1) + return -1; if (!strncmp(key, "codec_", strlen("codec_"))) cl->entry[i].codec = dect_parse_num(val); @@ -360,7 +474,7 @@ static int dect_db_parse_codec_list(struct dect_pt *pt, const char *key, static void dect_db_store_codec_list(const struct dect_pt *pt) { - struct dect_ie_codec_list *cl = pt->codec_list; + const struct dect_ie_codec_list *cl = pt->codec_list; unsigned int i; for (i = 0; i < cl->num; i++) { @@ -374,44 +488,44 @@ static void dect_db_store_codec_list(const struct dect_pt *pt) static int dect_db_parse_termcap(struct dect_pt *pt, const char *key, const char *val) { - struct dect_ie_terminal_capability *tcap; + struct dect_ie_terminal_capability *tc; if (strncmp(key, "capabilities/", strlen("capabilities/"))) return -1; key += strlen("capabilities/"); - tcap = pt->terminal_capability; - if (tcap == NULL) { - pt->terminal_capability = (void *)dect_ie_alloc(dh, sizeof(*tcap)); - tcap = pt->terminal_capability; + tc = pt->terminal_capability; + if (tc == NULL) { + pt->terminal_capability = (void *)dect_ie_alloc(dh, sizeof(*tc)); + tc = pt->terminal_capability; } if (!strcmp(key, "tone_capabilities")) - tcap->tone = dect_parse_num(val); + tc->tone = dect_parse_num(val); else if (!strcmp(key, "echo_parameters")) - tcap->echo = dect_parse_num(val); + tc->echo = dect_parse_num(val); else if (!strcmp(key, "noise_rejection")) - tcap->noise_rejection = dect_parse_num(val); + tc->noise_rejection = dect_parse_num(val); else if (!strcmp(key, "volume_ctrl")) - tcap->volume_ctrl = dect_parse_num(val); + tc->volume_ctrl = dect_parse_num(val); else if (!strcmp(key, "slot_capabilities")) - tcap->slot = dect_parse_num(val); + tc->slot = dect_parse_num(val); else if (!strcmp(key, "display_capabilities")) - tcap->display = dect_parse_num(val); + tc->display = dect_parse_num(val); else if (!strcmp(key, "display_memory")) - tcap->display_memory = dect_parse_num(val); + tc->display_memory = dect_parse_num(val); else if (!strcmp(key, "display_lines")) - tcap->display_lines = dect_parse_num(val); + tc->display_lines = dect_parse_num(val); else if (!strcmp(key, "display_columns")) - tcap->display_columns = dect_parse_num(val); + tc->display_columns = dect_parse_num(val); else if (!strcmp(key, "display_control")) - tcap->display_control = dect_parse_num(val); + tc->display_control = dect_parse_num(val); else if (!strcmp(key, "display_charsets")) - tcap->display_charsets = dect_parse_num(val); + tc->display_charsets = dect_parse_num(val); else if (!strcmp(key, "scrolling")) - tcap->scrolling = dect_parse_num(val); + tc->scrolling = dect_parse_num(val); else if (!strcmp(key, "profile_indicator")) - tcap->profile_indicator = dect_parse_num(val); + tc->profile_indicator = dect_parse_num(val); else return -1; return 0; @@ -419,7 +533,7 @@ static int dect_db_parse_termcap(struct dect_pt *pt, const char *key, static void dect_db_store_termcap(const struct dect_pt *pt) { - struct dect_ie_terminal_capability *tc = pt->terminal_capability; + const struct dect_ie_terminal_capability *tc = pt->terminal_capability; dect_db_put_num(pt, "capabilities/tone_capabilities", tc->tone); dect_db_put_num(pt, "capabilities/echo_parameters", tc->echo); @@ -439,12 +553,11 @@ static void dect_db_store_termcap(const struct dect_pt *pt) static int dect_db_parse_global(struct dect_pt *pt, const char *key, const char *val) { - if (!strcmp(key, "ipei")) { - if (!dect_parse_ipei_string(&pt->ipui.pun.n.ipei, val)) - return -1; - pt->ipui.put = DECT_IPUI_N; + if (!strcmp(key, "name")) { + ast_copy_string(pt->name, val, sizeof(pt->name)); + snprintf(pt->fullname, sizeof(pt->fullname), "DECT/%s", pt->name); } else if (!strcmp(key, "regexten")) - ast_string_field_set(pt, regexten, val); + dect_pt_set_extension(pt, strtoul(val, NULL, 0)); else if (!strcmp(key, "context")) ast_string_field_set(pt, context, val); else if (!strcmp(key, "language")) @@ -464,10 +577,7 @@ static int dect_db_parse_global(struct dect_pt *pt, const char *key, static void dect_db_store_portable(const struct dect_pt *pt) { - char buf[DECT_IPEI_STRING_LEN + 1]; - - dect_format_ipei_string(&pt->ipui.pun.n.ipei, buf); - dect_db_put(pt, "ipei", buf); + dect_db_put(pt, "name", pt->name); dect_db_put(pt, "regexten", pt->regexten); dect_db_put(pt, "context", pt->context); dect_db_put(pt, "language", pt->language); @@ -477,121 +587,6 @@ static void dect_db_store_portable(const struct dect_pt *pt) dect_db_put_base64(pt, "uak", pt->uak, sizeof(pt->uak)); } -static void dect_init_tpui(struct dect_tpui *tpui, unsigned int exten) -{ - tpui->ia.digits[0] = exten > 10000 ? exten / 10000 % 10 : 0xb; - tpui->ia.digits[1] = exten > 1000 ? exten / 1000 % 10 : 0xb; - tpui->ia.digits[2] = exten > 100 ? exten / 100 % 10 : 0xb; - tpui->ia.digits[3] = exten > 10 ? exten / 10 % 10 : 0xb; - tpui->ia.digits[4] = exten > 1 ? exten / 1 % 10 : 0xb; -} - -static struct dect_pt *dect_init_portable(const char *name, - const struct ast_variable *v) -{ - struct dect_pt *pt; - - pt = ast_calloc(1, sizeof(*pt)); - if (pt == NULL) - return NULL; - ast_copy_string(pt->name, name, sizeof(pt->name)); - snprintf(pt->fullname, sizeof(pt->fullname), "DECT/%s", pt->name); - - ast_string_field_init(pt, 512); - ast_string_field_set(pt, context, dect_cfg.context); - ast_string_field_set(pt, regexten, ""); - ast_string_field_set(pt, language, dect_cfg.language); - ast_string_field_set(pt, cid_num, ""); - ast_string_field_set(pt, cid_name, ""); - ast_string_field_set(pt, ring_pattern, "0"); - pt->ipui.put = DECT_IPUI_N; - - for (; v != NULL; v = v->next) { - if (!strcasecmp(v->name, "emc")) { - pt->ipui.pun.n.ipei.emc = strtoul(v->value, NULL, 16); - } else if (!strcasecmp(v->name, "psn")) { - pt->ipui.pun.n.ipei.psn = strtoul(v->value, NULL, 16); - } else if (!strcasecmp(v->name, "context")) { - ast_string_field_set(pt, context, v->value); - } else if (!strcasecmp(v->name, "regexten")) { - ast_string_field_set(pt, regexten, v->value); - } else if (!strcasecmp(v->name, "language")) { - ast_string_field_set(pt, language, v->value); - } else if (!strcasecmp(v->name, "cid_number")) { - ast_string_field_set(pt, cid_num, v->value); - } else if (!strcasecmp(v->name, "cid_name")) { - ast_string_field_set(pt, cid_name, v->value); - } else if (!strcasecmp(v->name, "ring_pattern")) { - ast_string_field_set(pt, ring_pattern, v->value); - } - } - - AST_LIST_INSERT_TAIL(&dect_pt_list, pt, list); - return pt; -} - -static int dect_alloc_extension(unsigned int *exten) -{ - const struct dect_pt *pt; - uint32_t bitmap[1024]; - unsigned int pext; - - memset(bitmap, 0, sizeof(bitmap)); - AST_LIST_TRAVERSE(&dect_pt_list, pt, list) { - pext = strtoul(pt->regexten, NULL, 0); - if (pext < dect_cfg.regexten_base || - pext >= 8 * sizeof(bitmap)) - continue; - pext -= dect_cfg.regexten_base; - - bitmap[pext / 32] |= 1 << (pext % 32); - } - - for (pext = 0; pext < 8 * sizeof(bitmap); pext++) { - if (!(bitmap[pext / 32] & (1 << (pext % 32)))) { - *exten = dect_cfg.regexten_base + pext; - return 1; - } - } - - return 0; -} - -static void dect_register_extension(const struct dect_pt *pt, bool onoff) -{ - struct pbx_find_info q = { .stacklen = 0 }; - char *ext, *extenp, *context; - char exten[256]; - - if (ast_strlen_zero(dect_cfg.regcontext)) - return; - - ast_copy_string(exten, S_OR(pt->regexten, pt->name), sizeof(exten)); - extenp = exten; - while ((ext = strsep(&extenp, "&")) != NULL) { - context = strchr(ext, '@'); - if (context != NULL) { - *context++ = '\0'; - if (!ast_context_find(context)) { - ast_log(LOG_WARNING, "Context %s for PT %s does not exist", - context, pt->name); - continue; - } - } else - context = dect_cfg.regcontext; - - if (onoff) { - if (!ast_exists_extension(NULL, context, ext, 1, NULL)) { - ast_add_extension(context, 1, ext, 1, NULL, NULL, "Dial", - (char *)pt->fullname, NULL, "DECT"); - } - } else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1, - NULL, "", E_MATCH)) { - ast_context_remove_extension(context, ext, 1, NULL); - } - } -} - static int dect_init_call(struct dect_pvt *pvt, enum ast_channel_state state, const char *exten) { @@ -1499,17 +1494,14 @@ static void dect_mm_access_rights_auth_cfm(struct dect_pvt *pvt, bool success, } snprintf(name, sizeof(name), "DECT-PT-%u", exten); - pt = dect_init_portable(name, NULL); + pt = dect_init_portable(name); if (pt == NULL) { dect_mm_access_rights_reject(mme, DECT_REJECT_INSUFFICIENT_MEMORY); return; } - ast_string_field_build(pt, cid_num, "%u", exten); - ast_string_field_build(pt, regexten, "%u", exten); - - memcpy(&pt->ipui, ¶m->portable_identity->ipui, sizeof(pt->ipui)); - dect_init_tpui(&pt->tpui, exten); + dect_pt_set_ipui(pt, ¶m->portable_identity->ipui); + dect_pt_set_extension(pt, exten); } if (dect_mm_access_rights_res(dh, mme, true, &reply) < 0) @@ -1792,16 +1784,6 @@ static int dect_load_config(void) } } - /* Phone configuration */ - cat = NULL; - while ((cat = ast_category_browse(cfg, cat)) != NULL) { - if (!strcasecmp(cat, "general")) - continue; - pt = dect_init_portable(cat, ast_variable_browse(cfg, cat)); - if (pt == NULL) - return AST_MODULE_LOAD_DECLINE; - dect_register_extension(pt, true); - } return 0; } @@ -1879,7 +1861,6 @@ static char *dect_cli_show_portable(struct ast_cli_entry *e, int cmd, { struct dect_pt *pt; char cidbuf[256], codbuf[256]; - char ipeibuf[DECT_IPEI_STRING_LEN + 1]; switch (cmd) { case CLI_INIT: @@ -1901,12 +1882,11 @@ static char *dect_cli_show_portable(struct ast_cli_entry *e, int cmd, return CLI_FAILURE; } - dect_format_ipei_string(&pt->ipui.pun.n.ipei, ipeibuf); ast_callerid_merge(cidbuf, sizeof(cidbuf), pt->cid_name, pt->cid_num, "<unspecified>"); dect_codecs_merge(codbuf, sizeof(codbuf), pt); - ast_cli(a->fd, "IPEI: %s\n", ipeibuf); + ast_cli(a->fd, "IPEI: %s\n", pt->ipei); ast_cli(a->fd, "Extension: %s\n", pt->regexten); ast_cli(a->fd, "Context: %s\n", pt->context); ast_cli(a->fd, "Language: %s\n", pt->language); @@ -2115,15 +2095,19 @@ static void dect_io_thread_stop(void) static int dect_db_read(void) { struct ast_db_entry *dbt, *dbe; + struct dect_ipui ipui; struct dect_pt *pt; const char *key, *val; - char *tmp, name[64]; + char *tmp, ipei[64]; + + memset(&ipui, 0, sizeof(ipui)); + ipui.put = DECT_IPUI_N; dbt = ast_db_gettree("dect", NULL); for (dbe = dbt; dbe != NULL; dbe = dbe->next) { key = dbe->key + strlen("/dect/"); - strncpy(name, key, sizeof(name)); - tmp = strchr(name, '/'); + strncpy(ipei, key, sizeof(ipei)); + tmp = strchr(ipei, '/'); if (tmp == NULL) continue; @@ -2131,11 +2115,15 @@ static int dect_db_read(void) key = tmp + 1; val = dbe->data; - pt = dect_pt_get_by_name(name); + if (!dect_parse_ipei_string(&ipui.pun.n.ipei, ipei)) + continue; + + pt = dect_pt_get_by_ipui(&ipui); if (pt == NULL) { - pt = dect_init_portable(name, NULL); + pt = dect_init_portable(NULL); if (pt == NULL) return -1; + dect_pt_set_ipui(pt, &ipui); } if (dect_db_parse_global(pt, key, val) != 0 && |