diff options
author | Patrick McHardy <kaber@trash.net> | 2010-10-08 15:37:02 +0200 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-02-26 22:06:06 +0100 |
commit | ad585875ae53015918c921f0ca0fa9719f39eb3e (patch) | |
tree | 7b25f4091c9e4f0246965ea6d6ce00eb93e04232 /channels/chan_dect.c | |
parent | 33bf1962ce61f8ef4a05e78fbb977c18f0c0110e (diff) |
chan_dect: store PT capabilities in database
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'channels/chan_dect.c')
-rw-r--r-- | channels/chan_dect.c | 310 |
1 files changed, 306 insertions, 4 deletions
diff --git a/channels/chan_dect.c b/channels/chan_dect.c index 910fbc7cb..d870f785d 100644 --- a/channels/chan_dect.c +++ b/channels/chan_dect.c @@ -257,6 +257,226 @@ static struct dect_pt *dect_pt_get_by_ipui(const struct dect_ipui *ipui) return NULL; } +static uint64_t dect_parse_num(const char *str) +{ + uint64_t num; + + if (sscanf(str, "%" PRIx64, &num) != 1) + ast_log(LOG_WARNING, "Could not parse numeric value '%s'\n", str); + + return num; +} + +static void dect_parse_base64(const char *str, uint8_t *dst, unsigned int size) +{ + ast_base64decode(dst, str, size); +} + +static void dect_db_remove(const struct dect_pt *pt) +{ + ast_db_deltree("dect", pt->name); +} + +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); + return ast_db_put("dect", ptkey, value); +} + +static int dect_db_put_numbered(const struct dect_pt *pt, const char *key, + unsigned int index, const char *value) +{ + char nkey[256]; + + snprintf(nkey, sizeof(nkey), "%s_%u", key, index); + return dect_db_put(pt, nkey, value); +} + +static int dect_db_put_base64(const struct dect_pt *pt, const char *key, + const void *data, unsigned int len) +{ + char value[4 * len + 4]; + + ast_base64encode(value, data, len, sizeof(value)); + return dect_db_put(pt, key, value); +} + +static int dect_db_put_num(const struct dect_pt *pt, const char *key, + uint64_t num) +{ + char value[sizeof("ffffffffffffffff")]; + + snprintf(value, sizeof(value), "%" PRIx64, num); + return dect_db_put(pt, key, value); +} + +static int dect_db_put_numbered_num(const struct dect_pt *pt, const char *key, + unsigned int index, uint64_t num) +{ + char value[sizeof("ffffffffffffffff")]; + + snprintf(value, sizeof(value), "%" PRIx64, num); + return dect_db_put_numbered(pt, key, index, value); +} + +static int dect_db_parse_codec_list(struct dect_pt *pt, const char *key, + const char *val) +{ + struct dect_ie_codec_list *cl; + unsigned int i; + const char *tmp; + char num[8]; + + if (strncmp(key, "codec_list/", strlen("codec_list/"))) + return -1; + key += strlen("codec_list/"); + + cl = pt->codec_list; + if (cl == NULL) { + pt->codec_list = (void *)dect_ie_alloc(dh, sizeof(*cl)); + cl = pt->codec_list; + } + + tmp = strchr(val, '_'); + if (tmp == NULL) + return -1; + strncpy(num, tmp + 1, sizeof(num)); + sscanf(num, "%u", &i); + + if (!strncmp(key, "codec_", strlen("codec_"))) + cl->entry[i].codec = dect_parse_num(val); + else if (!strncmp(key, "service_", strlen("service_"))) + cl->entry[i].service = dect_parse_num(val); + else if (!strncmp(key, "slot_", strlen("slot_"))) + cl->entry[i].slot = dect_parse_num(val); + else if (!strncmp(key, "cplane_", strlen("cplane_"))) + cl->entry[i].cplane = dect_parse_num(val); + else + return -1; + return 0; +} + +static void dect_db_store_codec_list(const struct dect_pt *pt) +{ + struct dect_ie_codec_list *cl = pt->codec_list; + unsigned int i; + + for (i = 0; i < cl->num; i++) { + dect_db_put_numbered_num(pt, "codec_list/codec", i, cl->entry[i].codec); + dect_db_put_numbered_num(pt, "codec_list/service", i, cl->entry[i].service); + dect_db_put_numbered_num(pt, "codec_list/slot", i, cl->entry[i].slot); + dect_db_put_numbered_num(pt, "codec_list/cplane", i, cl->entry[i].cplane); + } +} + +static int dect_db_parse_termcap(struct dect_pt *pt, const char *key, + const char *val) +{ + struct dect_ie_terminal_capability *tcap; + + 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; + } + + if (!strcmp(key, "tone_capabilities")) + tcap->tone = dect_parse_num(val); + else if (!strcmp(key, "echo_parameters")) + tcap->echo = dect_parse_num(val); + else if (!strcmp(key, "noise_rejection")) + tcap->noise_rejection = dect_parse_num(val); + else if (!strcmp(key, "volume_ctrl")) + tcap->volume_ctrl = dect_parse_num(val); + else if (!strcmp(key, "slot_capabilities")) + tcap->slot = dect_parse_num(val); + else if (!strcmp(key, "display_capabilities")) + tcap->display = dect_parse_num(val); + else if (!strcmp(key, "display_memory")) + tcap->display_memory = dect_parse_num(val); + else if (!strcmp(key, "display_lines")) + tcap->display_lines = dect_parse_num(val); + else if (!strcmp(key, "display_columns")) + tcap->display_columns = dect_parse_num(val); + else if (!strcmp(key, "display_control")) + tcap->display_control = dect_parse_num(val); + else if (!strcmp(key, "display_charsets")) + tcap->display_charsets = dect_parse_num(val); + else if (!strcmp(key, "scrolling")) + tcap->scrolling = dect_parse_num(val); + else if (!strcmp(key, "profile_indicator")) + tcap->profile_indicator = dect_parse_num(val); + else + return -1; + return 0; +} + +static void dect_db_store_termcap(const struct dect_pt *pt) +{ + 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); + dect_db_put_num(pt, "capabilities/noise_rejection", tc->noise_rejection); + dect_db_put_num(pt, "capabilities/volume_ctrl", tc->volume_ctrl); + dect_db_put_num(pt, "capabilities/slot_capabilities", tc->slot); + dect_db_put_num(pt, "capabilities/display_capabilities", tc->display); + dect_db_put_num(pt, "capabilities/display_memory", tc->display_memory); + dect_db_put_num(pt, "capabilities/display_lines", tc->display_lines); + dect_db_put_num(pt, "capabilities/display_columns", tc->display_columns); + dect_db_put_num(pt, "capabilities/display_control", tc->display_control); + dect_db_put_num(pt, "capabilities/display_charsets", tc->display_charsets); + dect_db_put_num(pt, "capabilities/scrolling", tc->scrolling); + dect_db_put_num(pt, "capabilities/profile_indicator", tc->profile_indicator); +} + +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; + } else if (!strcmp(key, "regexten")) + ast_string_field_set(pt, regexten, val); + else if (!strcmp(key, "context")) + ast_string_field_set(pt, context, val); + else if (!strcmp(key, "language")) + ast_string_field_set(pt, language, val); + else if (!strcmp(key, "cid_num")) + ast_string_field_set(pt, cid_num, val); + else if (!strcmp(key, "cid_name")) + ast_string_field_set(pt, cid_name, val); + else if (!strcmp(key, "ring_pattern")) + ast_string_field_set(pt, ring_pattern, val); + else if (!strcmp(key, "uak")) + dect_parse_base64(val, pt->uak, sizeof(pt->uak)); + else + return -1; + return 0; +} + +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, "regexten", pt->regexten); + dect_db_put(pt, "context", pt->context); + dect_db_put(pt, "language", pt->language); + dect_db_put(pt, "cid_num", pt->cid_num); + dect_db_put(pt, "cid_name", pt->cid_name); + dect_db_put(pt, "ring_pattern", pt->ring_pattern); + 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; @@ -1297,8 +1517,16 @@ static void dect_mm_access_rights_auth_cfm(struct dect_pvt *pvt, bool success, dect_access_rights_requests_disable(); memcpy(pt->uak, pvt->uak, sizeof(pt->uak)); - dect_ie_update(pt->terminal_capability, param->terminal_capability); - dect_ie_update(pt->codec_list, param->codec_list); + dect_db_store_portable(pt); + + if (param->terminal_capability) { + dect_ie_update(pt->terminal_capability, param->terminal_capability); + dect_db_store_termcap(pt); + } + if (param->codec_list) { + dect_ie_update(pt->codec_list, param->codec_list); + dect_db_store_codec_list(pt); + } } static void dect_mm_access_rights_ind(struct dect_handle *dh, @@ -1361,6 +1589,7 @@ static void dect_mm_access_rights_terminate_auth_cfm(struct dect_pvt *pvt, bool return; } + dect_db_remove(pt); dect_destroy_portable(pt); } @@ -1388,6 +1617,7 @@ static void dect_mm_access_rights_terminate_cfm(struct dect_handle *dh, struct dect_pvt *pvt = dect_mm_priv(mme); struct dect_pt *pt = pvt->pt; + dect_db_remove(pt); dect_destroy_portable(pt); } @@ -1455,8 +1685,14 @@ static void dect_mm_locate_auth_cfm(struct dect_pvt *pvt, bool success, if (dect_mm_locate_res(dh, mme, true, &reply) < 0) return; - dect_ie_update(pt->terminal_capability, param->terminal_capability); - dect_ie_update(pt->codec_list, param->codec_list); + if (param->terminal_capability) { + dect_ie_update(pt->terminal_capability, param->terminal_capability); + dect_db_store_termcap(pt); + } + if (param->codec_list) { + dect_ie_update(pt->codec_list, param->codec_list); + dect_db_store_codec_list(pt); + } dect_register_extension(pt, true); } @@ -1643,6 +1879,7 @@ 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: @@ -1664,10 +1901,12 @@ 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, "Extension: %s\n", pt->regexten); ast_cli(a->fd, "Context: %s\n", pt->context); ast_cli(a->fd, "Language: %s\n", pt->language); @@ -1720,11 +1959,32 @@ static char *dect_cli_ari(struct ast_cli_entry *e, int cmd, return CLI_SUCCESS; } +static int dect_db_read(void); +static char *dect_cli_db_reload(struct ast_cli_entry *e, int cmd, + struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "dect reload database"; + e->usage = "Usage: dect reload database\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + + if (a->argc < 3) + return CLI_SHOWUSAGE; + + dect_db_read(); + return CLI_SUCCESS; +} + static struct ast_cli_entry dect_cli_cmds[] = { AST_CLI_DEFINE(dect_cli_debug, "Enable/Disable DECT debugging"), AST_CLI_DEFINE(dect_cli_ari, "Access rights modification"), AST_CLI_DEFINE(dect_cli_show_portables, "Show list of portables"), AST_CLI_DEFINE(dect_cli_show_portable, "Show portable information"), + AST_CLI_DEFINE(dect_cli_db_reload, "Reload database"), }; /* @@ -1852,6 +2112,43 @@ static void dect_io_thread_stop(void) pthread_join(io_thread, NULL); } +static int dect_db_read(void) +{ + struct ast_db_entry *dbt, *dbe; + struct dect_pt *pt; + const char *key, *val; + char *tmp, name[64]; + + 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, '/'); + + if (tmp == NULL) + continue; + *tmp = '\0'; + key = tmp + 1; + val = dbe->data; + + pt = dect_pt_get_by_name(name); + if (pt == NULL) { + pt = dect_init_portable(name, NULL); + if (pt == NULL) + return -1; + } + + if (dect_db_parse_global(pt, key, val) != 0 && + dect_db_parse_termcap(pt, key, val) != 0 && + dect_db_parse_codec_list(pt, key, val) != 0) { + ast_log(LOG_NOTICE, "Unknown database key '%s'\n", key); + return -1; + } + } + + return 0; +} + static int dect_load_module(void) { const char *cluster; @@ -1891,6 +2188,11 @@ static int dect_load_module(void) goto err6; } + if (dect_db_read() < 0) { + ast_log(LOG_ERROR, "Unable to read database\n"); + goto err6; + } + return AST_MODULE_LOAD_SUCCESS; err6: |