net: lwm2m: Allow cancel-observe to match path
The specification states that the server can cancel observations "at any moment, by sendinga GET request with Observe option=1, the LwM2M Server cancancel an “Observe”operation on a specified Resource, or specified Object Instance(s)." It does not mention any token matching requirement, but RFC 7641 does. The correct interpretation is not obvious. The EMQx LwM2M implementation uses a new token for instance, which does not work with Zephyrs token matching cancel-observe. This commit introduces cancel-observe via path matching as a Kconfig option. This could hypothetically introduce problems when we are connected to multiple peers simultaneously, but since that is not likely to be supported for a long time (if ever), this change should be fairly uncontroversial since path matching is only used as a fallback. Signed-off-by: Benjamin Lindqvist <benjamin.lindqvist@endian.se>
This commit is contained in:
parent
5a1d069ae7
commit
e3f8757b70
2 changed files with 64 additions and 1 deletions
|
@ -554,6 +554,54 @@ static int engine_remove_observer(const uint8_t *token, uint8_t tkl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_LOG)
|
||||
char *lwm2m_path_log_strdup(struct lwm2m_obj_path *path)
|
||||
{
|
||||
char buf[sizeof("65535/65535/65535/65535")];
|
||||
size_t cur = sprintf(buf, "%u", path->obj_id);
|
||||
|
||||
if (path->level > 1) {
|
||||
cur += sprintf(buf + cur, "/%u", path->obj_inst_id);
|
||||
}
|
||||
if (path->level > 2) {
|
||||
cur += sprintf(buf + cur, "/%u", path->res_id);
|
||||
}
|
||||
if (path->level > 3) {
|
||||
cur += sprintf(buf + cur, "/%u", path->res_inst_id);
|
||||
}
|
||||
|
||||
return log_strdup(buf);
|
||||
}
|
||||
#endif /* CONFIG_LOG */
|
||||
|
||||
#if defined(CONFIG_LWM2M_CANCEL_OBSERVE_BY_PATH)
|
||||
static int engine_remove_observer_by_path(struct lwm2m_obj_path *path)
|
||||
{
|
||||
struct observe_node *obs, *found_obj = NULL;
|
||||
sys_snode_t *prev_node = NULL;
|
||||
|
||||
/* find the node index */
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&engine_observer_list, obs, node) {
|
||||
if (memcmp(path, &obs->path, sizeof(*path)) == 0) {
|
||||
found_obj = obs;
|
||||
break;
|
||||
}
|
||||
|
||||
prev_node = &obs->node;
|
||||
}
|
||||
|
||||
if (!found_obj) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
LOG_INF("Removing observer for path %s", lwm2m_path_log_strdup(path));
|
||||
sys_slist_remove(&engine_observer_list, prev_node, &found_obj->node);
|
||||
(void)memset(found_obj, 0, sizeof(*found_obj));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_LWM2M_CANCEL_OBSERVE_BY_PATH */
|
||||
|
||||
static void engine_remove_observer_by_id(uint16_t obj_id, int32_t obj_inst_id)
|
||||
{
|
||||
struct observe_node *obs, *tmp;
|
||||
|
@ -3847,7 +3895,13 @@ static int handle_request(struct coap_packet *request,
|
|||
/* remove observer */
|
||||
r = engine_remove_observer(token, tkl);
|
||||
if (r < 0) {
|
||||
LOG_ERR("remove observe error: %d", r);
|
||||
#if defined(CONFIG_LWM2M_CANCEL_OBSERVE_BY_PATH)
|
||||
r = engine_remove_observer_by_path(&msg->path);
|
||||
if (r < 0)
|
||||
#endif /* CONFIG_LWM2M_CANCEL_OBSERVE_BY_PATH */
|
||||
{
|
||||
LOG_ERR("remove observe error: %d", r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue