chan_dect: store PT capabilities in database
Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
parent
33bf1962ce
commit
ad585875ae
|
@ -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:
|
||||
|
|
Reference in New Issue