aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_dect.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-10-08 15:37:02 +0200
committerPatrick McHardy <kaber@trash.net>2011-02-26 22:06:06 +0100
commitad585875ae53015918c921f0ca0fa9719f39eb3e (patch)
tree7b25f4091c9e4f0246965ea6d6ce00eb93e04232 /channels/chan_dect.c
parent33bf1962ce61f8ef4a05e78fbb977c18f0c0110e (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.c310
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: