dect
/
asterisk
Archived
13
0
Fork 0

chan_dect: store PT capabilities in database

Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Patrick McHardy 2010-10-08 15:37:02 +02:00
parent 33bf1962ce
commit ad585875ae
1 changed files with 306 additions and 4 deletions

View File

@ -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: