mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
Solve problems found in the first round of internal test
The major changes are for more TR-104 compliant. - Changes those static objects to dynamic ones although they can have only one instance - Make some paraters' values compliant to the data model
This commit is contained in:
parent
6566c2baf7
commit
85eca6e6dc
8 changed files with 311 additions and 94 deletions
|
|
@ -109,7 +109,6 @@ int init_call_log()
|
|||
// Check if there are any new call logs since the last time
|
||||
if (stat(CALL_LOG_FILE, &cur_stat) == 0) {
|
||||
if (memcmp(&cur_stat, &prev_stat, sizeof(cur_stat)) == 0) {
|
||||
TR104_DEBUG("There are no new call log since the last time. Exit.\n");
|
||||
return 0;
|
||||
} else {
|
||||
prev_stat = cur_stat;
|
||||
|
|
@ -280,3 +279,29 @@ __ret:
|
|||
return res;
|
||||
#undef CHECK_RESULT
|
||||
}
|
||||
|
||||
// Get the UCI section name of a codec, e.g. G.711ALaw --> alaw
|
||||
const char *get_codec_uci_name(const char *codec)
|
||||
{
|
||||
if (codec && *codec) {
|
||||
for (int i = 0; i < codecs_num; i++) {
|
||||
if (!strcasecmp(supported_codecs[i].codec, codec))
|
||||
return supported_codecs[i].uci_name;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get the codec name in TR-104 from UCI section name, e.g. alaw --> G.711ALaw
|
||||
const char *get_codec_name(const char *codec_profile)
|
||||
{
|
||||
if (codec_profile && *codec_profile) {
|
||||
for (int i = 0; i < codecs_num; i++) {
|
||||
if (!strcasecmp(supported_codecs[i].uci_name, codec_profile))
|
||||
return supported_codecs[i].codec;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,3 +64,5 @@ extern char *KeyingMethods[];
|
|||
|
||||
int init_supported_codecs();
|
||||
int init_call_log();
|
||||
const char *get_codec_uci_name(const char *codec);
|
||||
const char *get_codec_name(const char *codec_profile);
|
||||
|
|
|
|||
|
|
@ -61,29 +61,43 @@ static int browseServicesVoiceServiceCodecProfileInst(struct dmctx *dmctx, DMNOD
|
|||
char *inst = NULL, *inst_last = NULL;
|
||||
struct dmmap_dup *p;
|
||||
LIST_HEAD(dup_list);
|
||||
int i;
|
||||
int i, j;
|
||||
int has_codec_profile = 0;
|
||||
|
||||
// Initialize supported codecs if it has not been done
|
||||
if (codecs_num <= 0)
|
||||
init_supported_codecs();
|
||||
|
||||
// Populate all supported codecs in UCI
|
||||
for (i = 0; i < codecs_num; i++) {
|
||||
struct codec_info *codec = &supported_codecs[i];
|
||||
char *value = NULL;
|
||||
// Populate all supported codecs to UCI if there is none
|
||||
for (j = 0; j < 2; j++) {
|
||||
for (i = 0; i < codecs_num; i++) {
|
||||
struct codec_info *codec = &supported_codecs[i];
|
||||
char *value = NULL;
|
||||
|
||||
dmuci_get_option_value_string(TR104_UCI_PACKAGE, codec->uci_name, "name", &value);
|
||||
if (!value || !*value) {
|
||||
char str[16];
|
||||
// Not found. Add this codec in the UCI
|
||||
dmuci_set_value(TR104_UCI_PACKAGE, codec->uci_name, "", "codec_profile");
|
||||
TR104_DEBUG("Created a UCI section: %s\n", str);
|
||||
dmuci_set_value(TR104_UCI_PACKAGE, codec->uci_name, "name", codec->codec);
|
||||
snprintf(str, sizeof(str), "%u", codec->ptime_default);
|
||||
dmuci_set_value(TR104_UCI_PACKAGE, codec->uci_name, "ptime", str);
|
||||
} else {
|
||||
dmfree(value);
|
||||
dmuci_get_option_value_string(TR104_UCI_PACKAGE, codec->uci_name, "name", &value);
|
||||
if (!value || !*value) {
|
||||
if (j == 1) {
|
||||
char str[16];
|
||||
// Not found. Add this codec in the UCI
|
||||
dmuci_set_value(TR104_UCI_PACKAGE, codec->uci_name, "", "codec_profile");
|
||||
TR104_DEBUG("Created a UCI section: %s\n", str);
|
||||
dmuci_set_value(TR104_UCI_PACKAGE, codec->uci_name, "name", codec->codec);
|
||||
snprintf(str, sizeof(str), "%u", codec->ptime_default);
|
||||
dmuci_set_value(TR104_UCI_PACKAGE, codec->uci_name, "ptime", str);
|
||||
}
|
||||
} else {
|
||||
dmfree(value);
|
||||
if (j == 0) {
|
||||
// At least there is one codec profile configured in UCI
|
||||
has_codec_profile = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't add any profile if there is any in UCI which has been configured
|
||||
if (has_codec_profile)
|
||||
break;
|
||||
}
|
||||
|
||||
synchronize_specific_config_sections_with_dmmap("asterisk", "codec_profile", "dmmap_asterisk", &dup_list);
|
||||
|
|
@ -149,7 +163,7 @@ static int delObjServicesVoiceServiceVoIPProfile(char *refparam, struct dmctx *c
|
|||
return 0;
|
||||
}
|
||||
|
||||
int addObjServicesVoiceServiceCodecProfile(char *refparam, struct dmctx *ctx, void *data, char **instance)
|
||||
static int addObjServicesVoiceServiceCodecProfile(char *refparam, struct dmctx *ctx, void *data, char **instance)
|
||||
{
|
||||
char *inst, *value, *v;
|
||||
struct uci_section *dmmap = NULL, *s = NULL;
|
||||
|
|
@ -164,7 +178,7 @@ int addObjServicesVoiceServiceCodecProfile(char *refparam, struct dmctx *ctx, vo
|
|||
return 0;
|
||||
}
|
||||
|
||||
int delObjServicesVoiceServiceCodecProfile(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
|
||||
static int delObjServicesVoiceServiceCodecProfile(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
|
||||
{
|
||||
struct uci_section *s = NULL, *ss = NULL, *dmmap_section = NULL;
|
||||
int found = 0;
|
||||
|
|
@ -256,7 +270,7 @@ DMOBJ tServicesVoiceServiceObj[] = {
|
|||
{"CallControl", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tServicesVoiceServiceCallControlObj, NULL, NULL, BBFDM_BOTH},
|
||||
{"CallLog", &DMREAD, NULL, NULL, NULL, browseServicesVoiceServiceCallLogInst, NULL, NULL, NULL, NULL, tServicesVoiceServiceCallLogParams, NULL, BBFDM_BOTH},
|
||||
{"VoIPProfile", &DMWRITE, addObjServicesVoiceServiceVoIPProfile, delObjServicesVoiceServiceVoIPProfile, NULL, browseServicesVoiceServiceVoIPProfileInst, NULL, NULL, NULL, tServicesVoiceServiceVoIPProfileObj, tServicesVoiceServiceVoIPProfileParams, NULL, BBFDM_BOTH},
|
||||
{"CodecProfile", &DMWRITE, NULL, NULL, NULL, browseServicesVoiceServiceCodecProfileInst, NULL, NULL, NULL, NULL, tServicesVoiceServiceCodecProfileParams, NULL, BBFDM_BOTH},
|
||||
{"CodecProfile", &DMWRITE, addObjServicesVoiceServiceCodecProfile, delObjServicesVoiceServiceCodecProfile, NULL, browseServicesVoiceServiceCodecProfileInst, NULL, NULL, NULL, NULL, tServicesVoiceServiceCodecProfileParams, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,46 @@ static int browseServicesVoiceServiceCallControlOutgoingMapInst(struct dmctx *dm
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*#Device.Services.VoiceService.{i}.CallControl.NumberingPlan.{i}.!UCI:asterisk/tel_advanced/dmmap_asterisk*/
|
||||
static int browseServicesVoiceServiceCallControlNumberingPlanInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||
{
|
||||
char *inst = NULL, *max_inst = NULL;
|
||||
struct dmmap_dup *p;
|
||||
LIST_HEAD(dup_list);
|
||||
|
||||
synchronize_specific_config_sections_with_dmmap("asterisk", "tel_advanced", "dmmap_asterisk", &dup_list);
|
||||
list_for_each_entry(p, &dup_list, list) {
|
||||
|
||||
inst = handle_update_instance(1, dmctx, &max_inst, update_instance_alias, 5,
|
||||
p->dmmap_section, "numberingplaninstance", "numberingplanalias", "dmmap_asterisk", "tel_advanced");
|
||||
|
||||
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP)
|
||||
break;
|
||||
}
|
||||
free_dmmap_config_dup_list(&dup_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*#Device.Services.VoiceService.{i}.CallControl.CallingFeatures.Set.{i}.!UCI:asterisk/advanced_features/dmmap_asterisk*/
|
||||
static int browseServicesVoiceServiceCallControlCallingFeaturesSetInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||
{
|
||||
char *inst = NULL, *max_inst = NULL;
|
||||
struct dmmap_dup *p;
|
||||
LIST_HEAD(dup_list);
|
||||
|
||||
synchronize_specific_config_sections_with_dmmap("asterisk", "advanced_features", "dmmap_asterisk", &dup_list);
|
||||
list_for_each_entry(p, &dup_list, list) {
|
||||
|
||||
inst = handle_update_instance(1, dmctx, &max_inst, update_instance_alias, 5,
|
||||
p->dmmap_section, "setinstance", "setalias", "dmmap_asterisk", "advanced_features");
|
||||
|
||||
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP)
|
||||
break;
|
||||
}
|
||||
free_dmmap_config_dup_list(&dup_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*#Device.Services.VoiceService.{i}.CallControl.CallingFeatures.Set.SCREJ.{i}.!UCI:asterisk/call_filter_rule_incoming/dmmap_asterisk*/
|
||||
static int browseServicesVoiceServiceCallControlCallingFeaturesSetSCREJInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||
{
|
||||
|
|
@ -143,50 +183,13 @@ static int delObjServicesVoiceServiceCallControlNumberingPlan(char *refparam, st
|
|||
|
||||
static int addObjServicesVoiceServiceCallControlCallingFeaturesSet(char *refparam, struct dmctx *ctx, void *data, char **instance)
|
||||
{
|
||||
char *inst, *value, *v;
|
||||
struct uci_section *dmmap = NULL, *s = NULL;
|
||||
|
||||
check_create_dmmap_package("dmmap_asterisk");
|
||||
inst = get_last_instance_bbfdm("dmmap_asterisk", "advanced_features", "setinstance");
|
||||
dmuci_add_section_and_rename("asterisk", "advanced_features", &s, &value);
|
||||
|
||||
dmuci_add_section_bbfdm("dmmap_asterisk", "advanced_features", &dmmap, &v);
|
||||
dmuci_set_value_by_section(dmmap, "section_name", section_name(s));
|
||||
*instance = update_instance(inst, 4, dmmap, "setinstance", "dmmap_asterisk", "advanced_features");
|
||||
TR104_DEBUG("VoiceService.1.CallControl.CallingFeatures.Set. has only one instance so it can't be added or deleted\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int delObjServicesVoiceServiceCallControlCallingFeaturesSet(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
|
||||
{
|
||||
struct uci_section *s = NULL, *ss = NULL, *dmmap_section = NULL;
|
||||
int found = 0;
|
||||
|
||||
switch (del_action) {
|
||||
case DEL_INST:
|
||||
get_dmmap_section_of_config_section("dmmap_asterisk", "advanced_features", section_name((struct uci_section *)data), &dmmap_section);
|
||||
if (dmmap_section != NULL)
|
||||
dmuci_delete_by_section(dmmap_section, NULL, NULL);
|
||||
dmuci_delete_by_section((struct uci_section *)data, NULL, NULL);
|
||||
break;
|
||||
case DEL_ALL:
|
||||
uci_foreach_sections("asterisk", "advanced_features", s) {
|
||||
if (found != 0) {
|
||||
get_dmmap_section_of_config_section("dmmap_asterisk", "advanced_features", section_name(ss), &dmmap_section);
|
||||
if (dmmap_section != NULL)
|
||||
dmuci_delete_by_section(dmmap_section, NULL, NULL);
|
||||
dmuci_delete_by_section(ss, NULL, NULL);
|
||||
}
|
||||
ss = s;
|
||||
found++;
|
||||
}
|
||||
if (ss != NULL) {
|
||||
get_dmmap_section_of_config_section("dmmap_asterisk", "advanced_features", section_name(ss), &dmmap_section);
|
||||
if (dmmap_section != NULL)
|
||||
dmuci_delete_by_section(dmmap_section, NULL, NULL);
|
||||
dmuci_delete_by_section(ss, NULL, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
TR104_DEBUG("VoiceService.1.CallControl.CallingFeatures.Set. has only one instance so it can't be added or deleted\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -294,42 +297,114 @@ static int set_ServicesVoiceServiceCallControlLine_DirectoryNumber(char *refpara
|
|||
}
|
||||
|
||||
/*#Device.Services.VoiceService.{i}.CallControl.Line.{i}.Provider!UCI:asterisk/tel_line,@i-1/sip_account*/
|
||||
#define SIP_CLIENT_PATH "Device.Services.VoiceService.1.SIP.Client."
|
||||
#define SIP_CLIENT_PATH_LEN strlen(SIP_CLIENT_PATH)
|
||||
static int get_ServicesVoiceServiceCallControlLine_Provider(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "sip_account", value);
|
||||
char *tmp = NULL;
|
||||
|
||||
*value = "";
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "sip_account", &tmp);
|
||||
if (tmp && strlen(tmp) > 3 && strncmp(tmp, "sip", 3) == 0) {
|
||||
dmasprintf(value, SIP_CLIENT_PATH"%d", atoi(tmp + 3) + 1);
|
||||
dmfree(tmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ServicesVoiceServiceCallControlLine_Provider(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (dm_validate_string(value, -1, 256, NULL, 0, NULL, 0))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
if (strlen(value) > SIP_CLIENT_PATH_LEN &&
|
||||
strncmp(value, SIP_CLIENT_PATH, SIP_CLIENT_PATH_LEN) == 0 &&
|
||||
atoi(value + SIP_CLIENT_PATH_LEN) > 0) {
|
||||
return 0;
|
||||
}
|
||||
return FAULT_9007;
|
||||
case VALUESET:
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "sip_account", value);
|
||||
dmasprintf(&tmp, "sip%d", atoi(value + SIP_CLIENT_PATH_LEN) - 1);
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "sip_account", tmp);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*#Device.Services.VoiceService.{i}.CallControl.IncomingMap.{i}.Line!UCI:asterisk/sip_service_provider,@i-1/call_lines*/
|
||||
#define CALL_CONTROL_LINE "Device.Services.VoiceService.1.CallControl.Line."
|
||||
#define CALL_CONTROL_LINE_LEN strlen(CALL_CONTROL_LINE)
|
||||
static int get_ServicesVoiceServiceCallControlIncomingMap_Line(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "call_lines", value);
|
||||
char *tmp = NULL;
|
||||
char buf[256] = "";
|
||||
|
||||
*value = "";
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "call_lines", &tmp);
|
||||
if (tmp && *tmp) {
|
||||
char *token, *saveptr;
|
||||
int len = 0;
|
||||
for (token = strtok_r(tmp, " ", &saveptr); token; token = strtok_r(NULL, " ", &saveptr)) {
|
||||
int line_index = atoi(token);
|
||||
if (line_index >= 0 && len < sizeof(buf)) {
|
||||
int res = snprintf(buf + len, sizeof(buf) - len, "%s"CALL_CONTROL_LINE"%d",
|
||||
len == 0 ? "" : ",", line_index + 1);
|
||||
if (res <= 0) {
|
||||
TR104_DEBUG("buf might be too small\n");
|
||||
dmfree(tmp);
|
||||
return FAULT_9002;
|
||||
}
|
||||
len += res;
|
||||
}
|
||||
}
|
||||
if (buf[0] != '\0')
|
||||
*value = dmstrdup(buf);
|
||||
dmfree(tmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ServicesVoiceServiceCallControlIncomingMap_Line(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
char *token, *saveptr, *dup;
|
||||
char buf[256] = "";
|
||||
int len = 0;
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (dm_validate_string(value, -1, 256, NULL, 0, NULL, 0))
|
||||
return FAULT_9007;
|
||||
// Duplicate the original value because strtok_r() might truncate it if there are multiple lines to set
|
||||
if ((dup = dmstrdup(value)) == NULL)
|
||||
return FAULT_9002;
|
||||
for (token = strtok_r(dup, ", ", &saveptr); token; token = strtok_r(NULL, ", ", &saveptr)) {
|
||||
if (strlen(token) <= CALL_CONTROL_LINE_LEN ||
|
||||
strncmp(token, CALL_CONTROL_LINE, CALL_CONTROL_LINE_LEN) != 0 ||
|
||||
atoi(token + CALL_CONTROL_LINE_LEN) <= 0) {
|
||||
TR104_DEBUG("wrong CallControl.Line format: [%s]\n", token);
|
||||
dmfree(dup);
|
||||
return FAULT_9007;
|
||||
}
|
||||
}
|
||||
dmfree(dup);
|
||||
break;
|
||||
case VALUESET:
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "call_lines", value);
|
||||
for (token = strtok_r(value, ", ", &saveptr); token; token = strtok_r(NULL, ", ", &saveptr)) {
|
||||
int inst = atoi(token + CALL_CONTROL_LINE_LEN);
|
||||
if (inst > 0 && len < sizeof(buf)) {
|
||||
int res = snprintf(buf + len, sizeof(buf) - len, "%s%d", len == 0 ? "" : " ", inst - 1);
|
||||
if (res <= 0) {
|
||||
TR104_DEBUG("buf might be too small\n");
|
||||
return FAULT_9002;
|
||||
}
|
||||
len += res;
|
||||
}
|
||||
}
|
||||
if (buf[0] != '\0')
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "call_lines", buf);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -458,7 +533,7 @@ DMOBJ tServicesVoiceServiceCallControlObj[] = {
|
|||
{"Line", &DMWRITE, addObjServicesVoiceServiceCallControlLine, delObjServicesVoiceServiceCallControlLine, NULL, browseServicesVoiceServiceCallControlLineInst, NULL, NULL, NULL, NULL, tServicesVoiceServiceCallControlLineParams, NULL, BBFDM_BOTH},
|
||||
{"IncomingMap", &DMWRITE, addObjServicesVoiceServiceCallControlIncomingMap, delObjServicesVoiceServiceCallControlIncomingMap, NULL, browseServicesVoiceServiceCallControlIncomingMapInst, NULL, NULL, NULL, NULL, tServicesVoiceServiceCallControlIncomingMapParams, NULL, BBFDM_BOTH},
|
||||
{"OutgoingMap", &DMWRITE, addObjServicesVoiceServiceCallControlOutgoingMap, delObjServicesVoiceServiceCallControlOutgoingMap, NULL, browseServicesVoiceServiceCallControlOutgoingMapInst, NULL, NULL, NULL, NULL, tServicesVoiceServiceCallControlOutgoingMapParams, NULL, BBFDM_BOTH},
|
||||
{"NumberingPlan", &DMWRITE, addObjServicesVoiceServiceCallControlNumberingPlan, delObjServicesVoiceServiceCallControlNumberingPlan, NULL, NULL, NULL, NULL, NULL, NULL, tServicesVoiceServiceCallControlNumberingPlanParams, NULL, BBFDM_BOTH},
|
||||
{"NumberingPlan", &DMWRITE, addObjServicesVoiceServiceCallControlNumberingPlan, delObjServicesVoiceServiceCallControlNumberingPlan, NULL, browseServicesVoiceServiceCallControlNumberingPlanInst, NULL, NULL, NULL, NULL, tServicesVoiceServiceCallControlNumberingPlanParams, NULL, BBFDM_BOTH},
|
||||
{"CallingFeatures", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tServicesVoiceServiceCallControlCallingFeaturesObj, NULL, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
|
@ -498,7 +573,7 @@ DMLEAF tServicesVoiceServiceCallControlNumberingPlanParams[] = {
|
|||
/* *** Device.Services.VoiceService.{i}.CallControl.CallingFeatures. *** */
|
||||
DMOBJ tServicesVoiceServiceCallControlCallingFeaturesObj[] = {
|
||||
/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextdynamicobj, nextobj, leaf, linker, bbfdm_type*/
|
||||
{"Set", &DMWRITE, addObjServicesVoiceServiceCallControlCallingFeaturesSet, delObjServicesVoiceServiceCallControlCallingFeaturesSet, NULL, NULL, NULL, NULL, NULL, tServicesVoiceServiceCallControlCallingFeaturesSetObj, tServicesVoiceServiceCallControlCallingFeaturesSetParams, NULL, BBFDM_BOTH},
|
||||
{"Set", &DMWRITE, addObjServicesVoiceServiceCallControlCallingFeaturesSet, delObjServicesVoiceServiceCallControlCallingFeaturesSet, NULL, browseServicesVoiceServiceCallControlCallingFeaturesSetInst, NULL, NULL, NULL, tServicesVoiceServiceCallControlCallingFeaturesSetObj, tServicesVoiceServiceCallControlCallingFeaturesSetParams, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -98,19 +98,19 @@ static int get_ServicesVoiceServiceCapabilitiesSIPClient_TLSAuthenticationKeySiz
|
|||
|
||||
static int get_ServicesVoiceServiceCapabilitiesSIPClient_TLSEncryptionProtocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = "AES,Blowfish,Camellia,SEED,CAST-128,IDEA,RC5,3DES,SM4";
|
||||
*value = "AES,Camellia,3DES";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ServicesVoiceServiceCapabilitiesSIPClient_TLSEncryptionKeySizes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = "256,32-448,256,128,40-128,128,128,168,128";
|
||||
*value = "256,256,168";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ServicesVoiceServiceCapabilitiesSIPClient_TLSKeyExchangeProtocols(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = "RSA,DSA,Diffie–Hellman key exchange,Elliptic curve,X25519,Ed25519,X448,Ed448,SM2";
|
||||
*value = "RSA";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,31 @@ static int get_ServicesVoiceServiceCodecProfile_Codec(char *refparam, struct dmc
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int set_ServicesVoiceServiceCodecProfile_Codec(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
int i;
|
||||
const char *uci_name;
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
for (i = 0; i < codecs_num; i++) {
|
||||
if (strcmp(supported_codecs[i].codec, value) == 0)
|
||||
return 0;
|
||||
}
|
||||
TR104_DEBUG("Wrong codec: [%s]\n", value);
|
||||
return FAULT_9007;
|
||||
case VALUESET:
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "name", value);
|
||||
// The UCI section name must be changed accordingly. Otherwise it can not be referenced correctly
|
||||
uci_name = get_codec_uci_name(value);
|
||||
if (uci_name) {
|
||||
dmuci_rename_section_by_section((struct uci_section *)data, (char *)uci_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*#Device.Services.VoiceService.{i}.CodecProfile.{i}.PacketizationPeriod!UCI:asterisk/codec_profile,@i-1/ptime*/
|
||||
static int get_ServicesVoiceServiceCodecProfile_PacketizationPeriod(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
|
|
@ -48,7 +73,7 @@ static int set_ServicesVoiceServiceCodecProfile_PacketizationPeriod(char *refpar
|
|||
/* *** Device.Services.VoiceService.{i}.CodecProfile.{i}. *** */
|
||||
DMLEAF tServicesVoiceServiceCodecProfileParams[] = {
|
||||
/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
|
||||
{"Codec", &DMREAD, DMT_STRING, get_ServicesVoiceServiceCodecProfile_Codec, NULL, NULL, NULL, BBFDM_BOTH},
|
||||
{"Codec", &DMWRITE, DMT_STRING, get_ServicesVoiceServiceCodecProfile_Codec, set_ServicesVoiceServiceCodecProfile_Codec, NULL, NULL, BBFDM_BOTH},
|
||||
{"PacketizationPeriod", &DMWRITE, DMT_STRING, get_ServicesVoiceServiceCodecProfile_PacketizationPeriod, set_ServicesVoiceServiceCodecProfile_PacketizationPeriod, NULL, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,6 +32,15 @@ static int browseServicesVoiceServiceSIPClientInst(struct dmctx *dmctx, DMNODE *
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*#Device.Services.VoiceService.{i}.SIP.Client.{i}.Contact.1*/
|
||||
static int browseServicesVoiceServiceSIPClientContactInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||
{
|
||||
// prev_data is from its parent node SIP.Client.{i}. i.e. the UCI section of asterisk.sip_service_provider
|
||||
DM_LINK_INST_OBJ(dmctx, parent_node, prev_data, "1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*#Device.Services.VoiceService.{i}.SIP.Network.{i}.!UCI:asterisk/sip_service_provider/dmmap_asterisk*/
|
||||
static int browseServicesVoiceServiceSIPNetworkInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||
{
|
||||
|
|
@ -50,6 +59,14 @@ static int browseServicesVoiceServiceSIPNetworkInst(struct dmctx *dmctx, DMNODE
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*#Device.Services.VoiceService.{i}.SIP.Network.{i}.FQDNServer.1*/
|
||||
static int browseServicesVoiceServiceSIPNetworkFQDNServerInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||
{
|
||||
// prev_data is from its parent node SIP.Network.{i}. i.e. a UCI section of asterisk.sip_service_provider
|
||||
DM_LINK_INST_OBJ(dmctx, parent_node, prev_data, "1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* ADD & DEL OBJ
|
||||
**************************************************************/
|
||||
|
|
@ -354,6 +371,11 @@ static int get_ServicesVoiceServiceSIPClientContact_ExpireTime(char *refparam, s
|
|||
struct uci_section *section = (struct uci_section *)data;
|
||||
json_object *res = NULL, *sip, *client;
|
||||
|
||||
if (!section) {
|
||||
TR104_DEBUG("section shall NOT be null\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dmubus_call("voice.asterisk", "status", UBUS_ARGS{}, 0, &res);
|
||||
if (res) {
|
||||
sip = dmjson_get_obj(res, 1, "sip");
|
||||
|
|
@ -383,6 +405,10 @@ static int get_ServicesVoiceServiceSIPClientContact_ExpireTime(char *refparam, s
|
|||
}
|
||||
time_expires = time_last + period;
|
||||
*value = dmstrdup(ctime_r(&time_expires, buf));
|
||||
// ctime_r() strangely adds a return at the end, e.g. "Fri Sep 25 12:24:39 2020\n". Remove it
|
||||
char *tmp = strchr(*value, '\n');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
} else {
|
||||
TR104_DEBUG("Unexpected time format: %s\n", last_reg_time);
|
||||
}
|
||||
|
|
@ -401,6 +427,11 @@ static int get_ServicesVoiceServiceSIPClientContact_UserAgent(char *refparam, st
|
|||
struct uci_section *section = (struct uci_section *)data;
|
||||
json_object *res = NULL, *sip, *client;
|
||||
|
||||
if (!section) {
|
||||
TR104_DEBUG("section shall NOT be null\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dmubus_call("voice.asterisk", "status", UBUS_ARGS{}, 0, &res);
|
||||
if (res) {
|
||||
sip = dmjson_get_obj(res, 1, "sip");
|
||||
|
|
@ -577,6 +608,11 @@ static int set_ServicesVoiceServiceSIPNetwork_ProxyServerPort(char *refparam, st
|
|||
static int get_ServicesVoiceServiceSIPNetwork_ProxyServerTransport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "transport", value);
|
||||
if (*value && **value) {
|
||||
// Convert to uppercase
|
||||
for (char *ch = *value; *ch != '\0'; ch++)
|
||||
*ch = toupper(*ch);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -640,6 +676,10 @@ static int set_ServicesVoiceServiceSIPNetwork_RegistrarServerPort(char *refparam
|
|||
static int get_ServicesVoiceServiceSIPNetwork_RegistrarServerTransport(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "transport", value);
|
||||
if (*value && **value) {
|
||||
for (char *ch = *value; *ch != '\0'; ch++)
|
||||
*ch = toupper(*ch);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -826,30 +866,36 @@ static int set_ServicesVoiceServiceSIPNetwork_DSCPMark(char *refparam, struct dm
|
|||
/*#Device.Services.VoiceService.{i}.SIP.Network.{i}.CodecList!UCI:asterisk/sip_service_provider,@i-1/codecs*/
|
||||
static int get_ServicesVoiceServiceSIPNetwork_CodecList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "codecs", value);
|
||||
if (*value && **value) {
|
||||
// Replace ' ' with ',' as per TR-104 syntax
|
||||
for (char *ch = *value; *ch; ch++) {
|
||||
if (*ch == ' ')
|
||||
*ch = ',';
|
||||
char *tmp = NULL;
|
||||
|
||||
*value = "";
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "codecs", &tmp);
|
||||
if (tmp && *tmp) {
|
||||
char buf[256] = "";
|
||||
char *token, *saveptr;
|
||||
int len = 0;
|
||||
|
||||
for (token = strtok_r(tmp, ", ", &saveptr); token; token = strtok_r(NULL, ", ", &saveptr)) {
|
||||
const char *codec = get_codec_name(token);
|
||||
if (codec && len < sizeof(buf)) {
|
||||
int res = snprintf(buf + len, sizeof(buf) - len, "%s%s", len == 0 ? "" : ",", codec);
|
||||
if (res <= 0) {
|
||||
TR104_DEBUG("buf might be too small\n");
|
||||
dmfree(tmp);
|
||||
return FAULT_9002;
|
||||
}
|
||||
len += res;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf[0] != '\0')
|
||||
*value = dmstrdup(buf);
|
||||
|
||||
dmfree(tmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the UCI section name of a codec, e.g. G.711ALaw --> alaw
|
||||
static const char *get_codec_uci_name(const char *codec)
|
||||
{
|
||||
if (codec && *codec) {
|
||||
for (int i = 0; i < codecs_num; i++) {
|
||||
if (!strcasecmp(supported_codecs[i].codec, codec))
|
||||
return supported_codecs[i].uci_name;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int del_codec_list(struct uci_section * section)
|
||||
{
|
||||
char *codec_list = NULL, *token, *saveptr;
|
||||
|
|
@ -942,11 +988,19 @@ static int get_ServicesVoiceServiceSIPNetworkFQDNServer_Origin(char *refparam, s
|
|||
/*#Device.Services.VoiceService.{i}.SIP.Network.{i}.FQDNServer.Domain!UCI:asterisk/sip_service_provider,@i-1/domain*/
|
||||
static int get_ServicesVoiceServiceSIPNetworkFQDNServer_Domain(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
if (!data) {
|
||||
TR104_DEBUG("data shall NOT be null\n");
|
||||
return 0;
|
||||
}
|
||||
return get_server_address(data, "domain", value);
|
||||
}
|
||||
|
||||
static int set_ServicesVoiceServiceSIPNetworkFQDNServer_Domain(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
if (!data) {
|
||||
TR104_DEBUG("data shall NOT be null\n");
|
||||
return 0;
|
||||
}
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (dm_validate_string(value, -1, 256, NULL, 0, NULL, 0))
|
||||
|
|
@ -962,11 +1016,19 @@ static int set_ServicesVoiceServiceSIPNetworkFQDNServer_Domain(char *refparam, s
|
|||
/*#Device.Services.VoiceService.{i}.SIP.Network.{i}.FQDNServer.Port!UCI:asterisk/sip_service_provider,@i-1/domain*/
|
||||
static int get_ServicesVoiceServiceSIPNetworkFQDNServer_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
if (!data) {
|
||||
TR104_DEBUG("data shall NOT be null\n");
|
||||
return 0;
|
||||
}
|
||||
return get_server_port(data, "domain", value);
|
||||
}
|
||||
|
||||
static int set_ServicesVoiceServiceSIPNetworkFQDNServer_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
if (!data) {
|
||||
TR104_DEBUG("data shall NOT be null\n");
|
||||
return 0;
|
||||
}
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (dm_validate_unsignedInt(value, RANGE_ARGS{{"0","65535"}}, 1))
|
||||
|
|
@ -993,7 +1055,7 @@ DMOBJ tServicesVoiceServiceSIPObj[] = {
|
|||
/* *** Device.Services.VoiceService.{i}.SIP.Client.{i}. *** */
|
||||
DMOBJ tServicesVoiceServiceSIPClientObj[] = {
|
||||
/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextdynamicobj, nextobj, leaf, linker, bbfdm_type*/
|
||||
{"Contact", &DMWRITE, addObjServicesVoiceServiceSIPClientContact, delObjServicesVoiceServiceSIPClientContact, NULL, NULL, NULL, NULL, NULL, NULL, tServicesVoiceServiceSIPClientContactParams, NULL, BBFDM_BOTH},
|
||||
{"Contact", &DMWRITE, addObjServicesVoiceServiceSIPClientContact, delObjServicesVoiceServiceSIPClientContact, NULL, browseServicesVoiceServiceSIPClientContactInst, NULL, NULL, NULL, NULL, tServicesVoiceServiceSIPClientContactParams, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
@ -1008,7 +1070,7 @@ DMLEAF tServicesVoiceServiceSIPClientParams[] = {
|
|||
{0}
|
||||
};
|
||||
|
||||
/* *** Device.Services.VoiceService.{i}.SIP.Client.{i}.Contact. *** */
|
||||
/* *** Device.Services.VoiceService.{i}.SIP.Client.{i}.Contact.{i}. *** */
|
||||
DMLEAF tServicesVoiceServiceSIPClientContactParams[] = {
|
||||
/* PARAM, permission, type, getvalue, setvalue, forced_inform, notification, bbfdm_type*/
|
||||
{"Origin", &DMREAD, DMT_STRING, get_ServicesVoiceServiceSIPClientContact_Origin, NULL, NULL, NULL, BBFDM_BOTH},
|
||||
|
|
@ -1021,7 +1083,7 @@ DMLEAF tServicesVoiceServiceSIPClientContactParams[] = {
|
|||
/* *** Device.Services.VoiceService.{i}.SIP.Network.{i}. *** */
|
||||
DMOBJ tServicesVoiceServiceSIPNetworkObj[] = {
|
||||
/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextdynamicobj, nextobj, leaf, linker, bbfdm_type*/
|
||||
{"FQDNServer", &DMWRITE, addObjServicesVoiceServiceSIPNetworkFQDNServer, delObjServicesVoiceServiceSIPNetworkFQDNServer, NULL, NULL, NULL, NULL, NULL, NULL, tServicesVoiceServiceSIPNetworkFQDNServerParams, NULL, BBFDM_BOTH},
|
||||
{"FQDNServer", &DMWRITE, addObjServicesVoiceServiceSIPNetworkFQDNServer, delObjServicesVoiceServiceSIPNetworkFQDNServer, NULL, browseServicesVoiceServiceSIPNetworkFQDNServerInst, NULL, NULL, NULL, NULL, tServicesVoiceServiceSIPNetworkFQDNServerParams, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -142,19 +142,33 @@ static int set_ServicesVoiceServiceVoIPProfileRTP_TelephoneEventPayloadType(char
|
|||
/*#Device.Services.VoiceService.{i}.VoIPProfile.{i}.RTP.JitterBufferType!UCI:asterisk/tel_advanced,tel_options/jbimpl*/
|
||||
static int get_ServicesVoiceServiceVoIPProfileRTP_JitterBufferType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
dmuci_get_option_value_string("asterisk", "tel_options", "jbimpl", value);
|
||||
char *tmp = NULL;
|
||||
|
||||
dmuci_get_option_value_string("asterisk", "tel_options", "jbimpl", &tmp);
|
||||
if (tmp && *tmp) {
|
||||
if (strcasecmp(tmp, "adaptive") == 0)
|
||||
*value = "Dynamic";
|
||||
else
|
||||
*value = "Static";
|
||||
dmfree(tmp);
|
||||
} else {
|
||||
*value = "";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ServicesVoiceServiceVoIPProfileRTP_JitterBufferType(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
char *uci_value = "fixed";
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (dm_validate_string(value, -1, -1, JitterBufferType, 2, NULL, 0))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
case VALUESET:
|
||||
dmuci_set_value("asterisk", "tel_options", "jbimpl", value);
|
||||
if (strcasecmp(value, "Dynamic") == 0)
|
||||
uci_value = "adaptive";
|
||||
dmuci_set_value("asterisk", "tel_options", "jbimpl", uci_value);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue